The following gem of an application note gives the elusive details about how to gain access to the second core:
OCM is 256K of ram that ends up mapped to the very end of the addess space. Core1 gets parked in a loop that lives in OCM at 0xfffffe00. (OCM itself extends from 0xfffc0000 to 0xffffffff.) The loop has the cpu execute WFE, where it sits and waits for an exception. When one comes along, it pops out of the WFE, inspects location 0xfffffff0 and if it finds it non-zero, branches there. If it is zero, it loops back and executes the WFE again and sits waiting for another exception.
I played around putting addresses into 0xfffffff0 and got no action. What was required was to put an address there and then execute a SEV instruction. This got results! The SEV instruction sends an exception to all cores in a multicore system (or else is a NOP if not implemented). Hence it is just what we require.
When the core starts up, nothing has been initialized. In particular the SP is zero, which works out OK since the first push onto the stack will wrap back to the end of OCM. This is fortunate behavior, and allows me to aim the second core directly at C code without bouncing through some assembler setup in a file like start.S. Ultimately of course I will want to do a considerable amount of assembler setup to get the second core running.
FFFFFF20 F57FF04F E320F002 EAFFFFFC F57FF04F FFFFFF30 E320F002 E3E0000F E590E000 E37E00D4 FFFFFF40 0AFFFFF9 EE070F15 EE070FD5 EE080F17 FFFFFF50 E3A04000 EE014F10 E12FFF1E 00000000And after some fooling around, I obtained this disassembly:
20: f57ff04f dsb sy 24: e320f002 wfe 28: eafffffc b 20 ?? 2c: f57ff04f dsb sy 30: e320f002 wfe 34: e3e0000f mvn r0, #15 ; 0xfffffff0 38: e590e000 ldr lr, [r0] 3c: e37e00d4 cmn lr, #212 ; 0xd4 40: 0afffff9 beq 2c 44: ee070f15 mcr 15, 0, r0, cr7, cr5, {0} 48: ee070fd5 mcr 15, 0, r0, cr7, cr5, {6} 4c: ee080f17 mcr 15, 0, r0, cr8, cr7, {0} 50: e3a04000 mov r4, #0 50: ee014f10 mcr 15, 0, r4, cr1, cr0, {0} 50: e12fff1e bx lr 50: 00000000We have two loops. The first does not seem of interest. The second does what has been described. Note that it does not compare against 0, but against a specific value, the negative of 0xd4. So the magic location must have been preloaded with this value. And in fact, an experiment shows the magic location has been preloaded with 0xFFFFFF2C -- the very address of the loop we are examining. In a way this is nice because we could specify a jump to address 0 if we had code there.
Last we have a gang of these mcr instructions which are placing values into registers in the system control coprocessor. Here is a short summary of that.
mcr 15, 0, r0, cr7, cr5, {0}15 is the coprocessor number (the system coprocessor)
So what do these do?
cr7,cr5,0 - invalidate all instruction caches to PoU cr7,cr5,6 - invalidate all branch predictors cr8,cr7,0 - invalidate entire unified TLB cr1,cr0,0 - system control register (SCTLR) set to zeroThe first 3 don't care what is in the processor register (r0), they invalidate entire objects. The last one writes the contents of r4 (which is zero) to the SCTLR.
Tom's Computer Info / [email protected]