<div dir="ltr"><div>I've managed to get Xilinx XMD to put up a pair of gdbservers such that I can inspect the target and see what's wrong[2].  The system has deadlocked with both cores waiting for an event from the other one.<br><br>I've been reading the RTEMS Zynq BSP source code, and I do not see how CPU1 gets its start address.  The Zynq manual [1] describes that the CPU0 application should place the start address in 0xfffffff0 and sev to wake up the other core, which ultimately jumps to the requested start address.  However, it appears by my reading of the assembly code that the address has never been loaded, since the start address pointer just forms a loop by pointing back to the original wfe instruction.<br><br></div><div>What should the start address be to start up RTEMS on the second core?  Beware that it must be an ARM mode instruction, since 'bl' is used to make the jump, rather than 'blx'.  I noticed that my application code is compiled in Thumb mode.<br></div><div><br></div><div>Thanks,<br></div><div>Jonathan Brandmeyer<br><br></div><div>[1] UG585, Section 6.1.10<br></div><div><br></div><div>[2] GDB Traces:<br><br></div><div>First off, CPU1 has the following code injected into it:<br><br>   0xffffff20:    dsb    sy<br>   0xffffff24:    wfe<br>   0xffffff28:    b    0xffffff20<br>   0xffffff2c:    dsb    sy<br>   0xffffff30:    wfe<br>=> 0xffffff34:    mvn    r0, #15<br>   0xffffff38:    ldr    lr, [r0]<br>   0xffffff3c:    cmn    lr, #212    ; 0xd4<br>   0xffffff40:    beq    0xffffff2c<br>   0xffffff44:    mcr    15, 0, r0, cr7, cr5, {0}<br>   0xffffff48:    mcr    15, 0, r0, cr7, cr5, {6}<br>   0xffffff4c:    mcr    15, 0, r0, cr8, cr7, {0}<br>   0xffffff50:    mov    r4, #0<br>   0xffffff54:    mcr    15, 0, r4, cr1, cr0, {0}<br>   0xffffff58:    bx    lr<br><br>   0xfffffff0 contains value 0xffffff2c<br></div><div>0xfffffff0 has type void (*)(void), and is used by the Zynq boot ROM to receive an address to start executing.<br></div><div><br></div>And CPU0 is waiting on CPU1:<br><div><br>gdb) bt full<br>#0  _ARM_Data_memory_barrier ()<br>    at ../../cpukit/../../../xilinx_zynq_zedboard/lib/include/rtems/score/cpu.h:303<br>No locals.<br>#1  _CPU_SMP_Processor_event_receive ()<br>    at ../../cpukit/../../../xilinx_zynq_zedboard/lib/include/rtems/score/cpu.h:541<br>No locals.<br>#2  _Per_CPU_State_wait_for_non_initial_state (cpu_index=cpu_index@entry=1, timeout_in_ns=57999, <br>    timeout_in_ns@entry=0)<br>    at ../../../../../../rtems/c/src/../../cpukit/score/src/percpustatewait.c:50<br>        state = PER_CPU_STATE_INITIAL<br>#3  0x0011ae0a in _CPU_SMP_Start_processor (cpu_index=cpu_index@entry=1)<br>    at ../../../../../../../../rtems/c/src/lib/libbsp/arm/xilinx-zynq/startup/bspsmp.c:23<br>No locals.<br>#4  0x00110516 in _SMP_Start_processors (cpu_count=2)<br>    at ../../../../../../rtems/c/src/../../cpukit/score/src/smp.c:42<br>        started = <optimized out><br>        cpu_index = 1<br>#5  _SMP_Handler_initialize () at ../../../../../../rtems/c/src/../../cpukit/score/src/smp.c:99<br>        cpu_max = <optimized out><br>        cpu_count = <optimized out><br>        cpu_index = <optimized out><br>#6  0x0010c814 in rtems_initialize_data_structures ()<br>    at ../../../../../../rtems/c/src/../../cpukit/sapi/src/exinit.c:138<br>No locals.<br>#7  0x00104934 in boot_card (cmdline=<optimized out>)<br>    at ../../../../../../../../rtems/c/src/lib/libbsp/arm/xilinx-zynq/../../shared/bootcard.c:92<br>No locals.<br>#8  0x00104112 in bsp_vector_table_copy_done ()<br>    at ../../../../../../../../rtems/c/src/lib/libbsp/arm/xilinx-zynq/../shared/start/start.S:279<br>No locals.<br><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, May 6, 2015 at 9:19 PM, Jonathan Brandmeyer <span dir="ltr"><<a href="mailto:jonathan.brandmeyer@gmail.com" target="_blank">jonathan.brandmeyer@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div><div>The enclosed program is intended to run on the Microzed platform with SMP support enabled.  It is a POSIX version of the ticker sample program, and it does run in single-core mode.  However, if the #defines for CONFIGURE_SMP_APPLICATION and CONFIGURE_SMP_MAXIMUM_PROCESSORS are left uncommented, the application does not run at all.  It does not reach the first printf that marks entry into POSIX_Init().<br><br></div><div>The RTEMS BSP was built with<br>$ ../rtems/configure --prefix=$HOME/Programs/rtems_4_11 --enable-posix --enable-smp --disable-networking --enable-cxx --enable-tests=samples --enable-rtemsbsp="xilinx_zynq_zedboard" --target=arm-rtems4.11<br></div><div><br></div>I didn't see anything special in the Zynq manuals about the bitstream design or FSBL configuration that needs changes to support SMP operation.  Unfortunately, my attempts to GDB into the target through OpenOCD have failed, such that I cannot tell where RTEMS has locked up.<br><br></div>Any ideas would be greatly appreciated.<br><br></div>Thanks,<br></div>Jonathan<br><br><br>#include <bsp.h><br>#include <stdlib.h><br>#include <stdio.h><br><br>void *POSIX_Init(void *args);<br>void *ticker_threadfunc(void *closure);<br><br>#define CONFIGURE_SMP_APPLICATION<br>#define CONFIGURE_SMP_MAXIMUM_PROCESSORS 2<br>#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER<br>#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER<br><br>#define CONFIGURE_UNIFIED_WORK_AREAS<br>#define CONFIGURE_UNLIMITED_OBJECTS<br>#define CONFIGURE_POSIX_INIT_THREAD_TABLE<br><br>#define CONFIGURE_INIT<br>#include <rtems/confdefs.h><br><br>void *<br>POSIX_Init(void *args)<br>{<br>    printf("Entry to POSIX_Init\n");<br>    const char *names[] = {<br>        "TAI1",<br>        "TAI2",<br>        "TAI3",<br>        NULL,<br>    };<br>    pthread_t threads[4];<br>    for (unsigned i = 0; names[i] != NULL; ++i) {<br>        pthread_create(&threads[i], NULL, ticker_threadfunc, (void *)names[i]);<br>        // Spread the tasks' start times out a pinch.<br>        sleep(2);<br>    }<br><br>    // Verify SMP operation.<br>    printf("Running on %lu cores\n", rtems_get_processor_count());<br><br>    for (unsigned i = 0; names[i] != NULL; ++i) {<br>        pthread_join(threads[i], NULL);<br>        printf("joined with thread %d\n", i);<br>    }<br>    printf("Exiting\n");<br>    // Huh.  The following does not behave as expected.  Instead of calling<br>    // exit(), nothing happens.<br>    // pthread_exit(NULL);<br>    exit(EXIT_SUCCESS);<br>    return NULL;<br>}<br><br>#include <stdbool.h><br>#include <time.h><br>#include <unistd.h><br><br>void *<br>ticker_threadfunc(void *closure)<br>{<br>    const char *threadname = closure;<br><br>    struct timespec begin;<br>    clock_gettime(CLOCK_REALTIME, &begin);<br>    while (true) {<br>        struct timespec now;<br>        clock_gettime(CLOCK_REALTIME, &now);<br>        <br>        struct tm formatted_now;<br>        gmtime_r(&now.tv_sec, &formatted_now);<br>        printf("%s: %04d-%02d-%02d %02d:%02d:%02d\n",<br>                threadname,<br>                formatted_now.tm_year,<br>                formatted_now.tm_mon,<br>                formatted_now.tm_mday,<br>                formatted_now.tm_hour,<br>                formatted_now.tm_min,<br>                formatted_now.tm_sec);<br><br>        sleep(5);<br>        if (now.tv_sec - begin.tv_sec >= 30) {<br>            pthread_exit(NULL);<br>        }<br>    }<br>    // Unreachable.<br>    return NULL;<br>}<br><br><div><div><div><br><br></div></div></div></div>
</blockquote></div><br></div>