LPC4337 M0APP Core Startup Failure

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC4337 M0APP Core Startup Failure

1,008 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Master Chef on Wed Mar 09 12:18:18 MST 2016
‎09 ‎March, ‎2016 - O.K. Here's the scenario:

I've been working on a dual-core DSP application using only the M4 initially because I wanted to first validate the design of the hardware platform (external peripheral hardware) before complicating it with code running on the "Slave" core (M0APP).  I've got an Ethernet Switch and it's associated IP stack running along with my DSP code on the M4 without problems.  I want to migrate the Network Code to the M0APP in order to minimize the impact of the Networking to my DSP code.  I'm developing on Keil uVision 5.15 with MDK-Pro middleware via a Keil uLink Pro.  I have +30 years experience in bare metal and embedded software development.

I've added a second project for the M0APP and have verified (in debug) that the LR0 array is being generated properly and included in the M4 project, which places its image at the beginning of Flash Bank B.  So, the Flash ROM arrangement is M4 image in Flash Bank A / M0APP image in Flash Bank B.  When the M4 runs the post-reset SystemInit does the following:

[list=1]
  [*]Enables the M0APP Branch Clock [LPC_CCU1->CLK_M4_M0APP_CFG = (1UL << 0)]
  [*]Puts the M0APP in Reset [LPC_RGU->RESET_CTRL1 = (1UL << 24)]
  [*]Sets VTOR to the start of Flash Bank A [SCB->VTOR = ( (uint32_t)(&__Vectors) ) & 0xFFF00000UL]
  [*]Programs the PLL1 (CPU) Clock Frequency
  [*]Starts up the M4 DSP application
[/list]

Once the RTOS and DSP application are up and running, I initialize the interprocessor communication structures and then do the following:

[list=1]
  [*]Set the M0APP Shadow Register to the start of Flash Bank B
  [*][LPC_CREG->M0APPMEMMAP = (uint32_t) &LR0]
  [*]Execute a Data Synchronization Barrier (just to be sure)
  [*]Clear and enable the M0APP_IRQ
  [*]Take the M0APP core out of Reset [LPC_RGU->RESET_CTRL1 = 0]
  [*]Wait for the M0APP to SEV to the M4 that it has completed its startup
[/list]

One of the first things that I do in the M0APP code is to change the state of an LED that is already setup by the M4.  It is literally within the first 10 lines of main().  I never even get there.  What above or elsewhere could be hanging the M0APP core?  When I look at the M0_Reset_Handler in startup_LPC43xx_M0.s all I see is:

LDRR0, =__main
BXR0


Could the M0APP be getting hung up in the Run-Time scatter/init code?  If so, what would cause that?
Labels (1)
0 Kudos
8 Replies

711 Views
lpcware
NXP Employee
NXP Employee
bump
0 Kudos

711 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Master Chef on Fri Mar 11 10:12:55 MST 2016
‎11 ‎March, ‎2016 - O.K. Here's my solution:

After inserting a "Branch to Self" in the M0_Reset_Handler in startup_LPC43xx_M0.s such that it reads:

LDRR0, =__main
B.
BXR0


I was able to bring up the debugger and stop execution at this infinite loop.  I then set the Program Counter to the BX jump through R0 and let it run.  I then stopped execution to see where the M0 was hung up.

It was locked up at the M0_SVC_Handler in startup_LPC43xx_M0.s (a bit of a surprise).

Apparantly, the __main run-time scatter/init code is interacting with the CMSIS RTOS code and this handler and the one for PendSV are NOT being resolved properly during the program linkage.  When I looked at the .map file, these two handlers are in the ARM RTX HAL_CM0.c file with different names (SVC_Handler and PendSV_Handler respectively).  Note the LACK of the M0_ prefix in names of these two functions.

So, the program link is being resolved with the default (infinite loop) handlers BECAUSE the Keil/ARM LPC4300 support Pack (2.6.0) startup_LPC43xx_M0.s Template File is using Handler names INCOMPATIBLE with their CMSIS RTOS (RTX) HAL_CM0.c abstraction layer.  After simply renaming these in the startup_LPC43xx_M0.s file of my project, this has been FIXED.  The program now resolves during link properly.

My two LPC4337 cores are now happily running their independent RTOS' and sending messages back and forth across the IPC boundary (the Network IP stack is now running on the M0APP core just fine as well).

Perhaps the NXP Support Team already knows about this issue, perhaps the Keil Support Team already knows about this issue.
(I'm NOT a betting man)

Now back to our normal programming...
0 Kudos

711 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by bavarian on Thu Mar 10 10:42:00 MST 2016
The attached example is based on the setup Keil did for their MCB4300 board.
I modified it in such a way that it runs M4 code from flash bank A and M0 code from flash bank B.

It is pretty "bare metal", so maybe it helps you to identify where the problem in your setup is.

There is a project for the M4 and another one for the M0, the downloade into the respective flash banks takes place from these projects. So no obscure array or binary which needs to be assembled into one file.
Compile the M4 project --> flash it
Compile the M0 project --> flash it
Press the reset button --> Some LEDs (respectively GPIOs) will flash based on an inter-core IRQ mechanism

Regards,
NXP Support Team.
0 Kudos

711 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by LessThanZero on Thu Mar 10 08:15:15 MST 2016

The ITM is on the Private Peripheral Bus of the M4.I don't recall whether Keil has a semihosting mechanisim available. If so, you could use printf debugging on the M0, albeit at a huge code size increase. Since the M0 has an entire flash bank available, space is not a concern. The only problem there is semihosting isn't realtime. Probably not a concern here.

LessThanZero.
0 Kudos

711 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Master Chef on Thu Mar 10 07:24:02 MST 2016
The Flash waitstate setting for bank A and B should be the same coming out of reset?
(which as I recall is set to the maximum value of 16 base M4 clocks)
I'll optimize that later based upon my target CPU clock frequency.

I'll try using the debug configuration that you've indicated to 'Break-In' to the M0 after startup and take a look at the execution state of the core.

Does the M0APP have the ability to printf to the ITM as the M4 does (I've made extensive use of the ITM during startup of the M4 code, so I know things are working well on that side).
0 Kudos

711 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Master Chef on Thu Mar 10 06:58:52 MST 2016
Well... no I'm not using the LPCOpen library.
This is at such a low level and I really don't want layers of code obscuring what I'm doing.
(I'll leave that to the RTOS ;)

All clocking and pinmux programming has already occurred in the M4 code and I'm using customized .sct files for both projects that eliminate the possibility of ROM/RAM conflicts (except in the cases of shared memory for IPC messaging between the cores).  I've verified from the linker .map file that there are NO conflicts in RAM usage (except the shared areas mentioned above) and that the M0APP is being built for the address range where that code is going to live in the combined image built for the M4.
0 Kudos

711 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by bavarian on Thu Mar 10 06:14:57 MST 2016
Yes, the dual core setup has its specialities. Dual core software as well, but with the LPC4300 architecture NXP did not have the intention to compete with real dual core solutions.

Step by step, let's first try to solve the startup problem:
[list]
  [*]  Don't touch the M0APP reset configuration in the beginning, after a reset the M0APP is in reset, you don't need to do this with an instruction.
  [*]  Take care that the flash waitstate setting for bank #B is also set correctly
  [*]  Insert a "branch-to-itself" instruction in the assembler startup code of the M0APP or alternatively a while(1) loop as first instruction in your M0APP C code. This would mean that after a correct start of the M0APP the core hangs up there and you can jump on it with a debugger.
  [*]  Compile and download your code as usual and perform a hardware reset. Then configure the debugger not to Load Application at Startup, to connect without running to main, without a reset and select the second core in the list. (see picture).
  [*]  If you then start the debugger, you should catch the M0APP hanging in this loop. Then you can go on from there and step through until you hit the instzrcution which is causing the problem.
  [*]  As mentioned, take care that your memory areas for the M4 and the M0 do not overlap, even if I don't expect that you have a problem here. If the M0 would do something on memory areas of the M4, you would see a crash in the M4 software.
[/list]

There are quite some projects out there which use the 2 cores, using different software setups. If you are not successful using the hints above I could recommend some of them to you, bare metal stuff, LPCOpen based etc.

The mutex:  yes, that's really missing in the LPC4300 in hardware. In a later chip, the LPC54114, we have implemented that. But this chip is intended for another class of applications, without ethernet etc.

Regards,
NXP Support Team.

0 Kudos

711 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by LessThanZero on Wed Mar 09 16:34:40 MST 2016

Are you using the LPCOpen library for Keil? There's example LPC4337 multicore projects you can check your code against if you're going bare metal.

https://www.lpcware.com/content/nxpfile/lpcopen-software-development-platform-lpc43xx-packages

I'd look at the M0 initialization (clocking, pinmux, etc.) first. You mentioned Flash Bank A is reserved for M4 code, and Flash Bank B is reserved for the M0. You didn't mention how you've split up the the usage of the RAM between these cores. Any conflicts you can identify there?

LessThanZero
0 Kudos