Hello everyone,
I have an LPC4337 running uCLinux. I'm trying to get code to run in the M0 in parallell.
I load the code to 0x10080000, set the M0APPMEMMAP to 0x10080000, release the M0APP Reset and nothing happens. I have to reset the M0-core using J-link debugger to get it running.
This is my code for loading and storing the M0-code:
main() { // Testing to run code in M0 uint8_t *CM0image_start = (uint8_t *)0x10080000; RGU_RESET_CTRL1 = (1u << 24); // Put the M0-core in RESET int fd = open("m0.bin", O_RDONLY); if (fd) { while (read(fd, CM0image_start, 256) > 0) // Read the executable into internal SRAM area { ; } } unsigned int *pCREG_M0APPMAP = (unsigned int *) 0x40043404; *pCREG_M0APPMAP = (unsigned int) CM0image_start; RGU_RESET_CTRL1 = 0x0; // Release the M0 core from RESET while (1) { ; // Halt here, and let M0 execute. } }
I can confirm that the code gets to its destination at 0x10080000.
This is my M0-code, just toggling one of my event-lines, at GPIO3[8]:
#include <stdint.h> #define GPIO_PORT3_DIR (*((volatile uint32_t *) 0x400f600c)) #define GPIO_PORT3_TOGGLE (*((volatile uint32_t *) 0x400f630c)) void main() __attribute__ ((naked)); void main(void) { GPIO_PORT3_DIR |= 0x0100; // Set 8th bit to output while (1) { GPIO_PORT3_TOGGLE = 0x0100; // Toggle bit 8 on GPIO3. } }
My reset-vector is setup like this:
.syntax unified .cpu cortex-m0 .thumb .section resetvector .word 0x10087ff0 /* stack top address */ .word _start /* 1 Reset */ .word _start /* 2 NMI */ .word _start /* 3 HardFault */ .word _start /* 4 MemManage */ .word _start /* 5 BusFault */ .word _start /* 6 UsageFault */ .word _start /* 7 RESERVED */ .word _start /* 8 RESERVED */ .word _start /* 9 RESERVED*/ .word _start /* 10 RESERVED */ .word _start /* 11 SVCall */ .word _start /* 12 Debug Monitor */ .word _start /* 13 RESERVED */ .word _start /* 14 PendSV */ .word _start /* 15 SysTick */ .word _start /* 16 External Interrupt(0) */ .word _start /* 17 External Interrupt(1) */ .word _start /* 18 External Interrupt(2) */ .word _start /* 19 ... */ _start: bl main b hang hang: b .
And finally, my linker script:
SECTIONS { . = 0x10080000; .text : { startup.o (resetvector) *(.text*) } }
My problem is that the code execution wont start, even though I can verify that the M0-core is not in reset (by reading the RGU_RESET_ACTIVE_STATUS1 register) . The only way to start the code is to attach to the cpu using my J-Link debugger, and issuing a "reset and halt" (to step forward) or "reset and run" to run it.
If I exit my linux-app, the M0 code continues to run (if started as above), but as soon as I start my linux-app again, the execution of the M0-core stops.
If you have any pointers, please let me know.
Thanks,
Message was edited by: Bo Mellberg. Reason: formatting code sections.
Hmm. It so happens that this comment in some documentation:
"The Program Counter (PC) is register R15. It contains the current program address. On reset, the processor loads the PC with the value of the reset vector, at address 0x00000004. Bit[0] of the value is loaded into the EPSR T-bit at reset and must be 1."
made us try to hex-edit the binary file for the m0-core, forcing bit 0 of the reset vector to 1. Suddenly, the m0-core starts spinning.
Hello bomellberg,
I'm glad you were able to get the application running. When directly writing the PC, Setting '1' to bit 0 is a requirement; this is a feature of the Cortex-M architecture. NXP's dual core examples take care of this automatically, when formatting the Cortex-M0 image itself. Generally we load this image in the cstartup routine during memory initialization, so your method was just a bit different by using file access.
Happy coding!
-arw
Thank you for confirming this.
I added the following to my loader code:
// Set bit 0 of the reset vector to 1 CM0image_start[4] |= 0x01;
So I don't have to worry about the code generation.
/Bo