The LPC541xx series of MCUs contain a main or 'Master' Cortex M4 core, plus an optional 'Slave' Cortex M0+ core. At the time of writing the parts are:
- MCUs with Cortex M4 only
- MCUs with Cortex M4 Master plus Cortex M0+ Slave
After a power-on or Reset, the Master and Slave cores both boot, but the slave core is then immediately put to sleep. The Master core is then responsible for releasing the slave core; hence the names Master and Slave. In reality Master and Slave only applies to the booting process; after boot, your application may treat any of the cores as the Master or Slave.
LPCXpresso IDE provides highly flexible support for creating and debugging LPC541xx applications, for both single core and multicore systems. This FAQ provides details the process of creating and debugging such multicore applications.
- This FAQ assumes that you are familiar with standard LPCXpresso IDE behavior, such as creating projects (including projects linked to LPCOpen library projects) and editing memory configuration in project properties. For more details of using LPCXpresso, please read the LPCXpresso User Guide provided in the product.
- Any use of Cortex-M0 (or M0) in this document should be read as a reference to the Cortex-M0+ implemented on LPC541xx.
Overview of creating a master / slave project pair
A multicore application in LPCXpresso consists of two linked projects - one project containing the slave code, and the other project containing the master code. The 'Master' project will also contain a link to the 'Slave' project which will cause the output image from the 'Slave' to be included into the 'Master' image. The following steps detail how such a pair of projects can be created and linked.
- It is recommend to create and build LPC541xx multicore projects which are linked to LPCOpen. Thus before you follow the below sequence, please ensure that you have imported the chip and (optionally) the board library projects (for both the M4 and M0+) from an LPCOpen package for the LPC5410x family or LPC5411x family (depending upon your target part).
Step 1 - Create slave project
Go to either:
- Quickstart -> New project -> LPC5410x -> LPC5410x Multicore (M0+ slave)
- Quickstart -> New project -> LPC5411x -> LPC5411x Multicore (M0+ slave)
- Select required project type (e.g LPCOpen - C Project) and click Next.
- Enter project name (for example, mc_slave) and click Next.
- Select the required target MCU, say LPC54102J512-M0, and click Next.
- On the LPCOpen Library Project Selection page, select the appropriate chip library for the M0+, for example lpc_chip_5410x_m0 and then the appropriate board library, for example lpc_board_lpcxpresso_54102_m0, and click Next.
- Click Next through CMSIS DSP Library selection
- On 'Other options', ensure Code Read Protect (CRP) is unticked
- On the Memory Configuration Editor page, you should see the various memory blocks defined by default for the target MCU:
We need to modify the default memory map to only use the memory that will be used by the Cortex-M0+ (rather than the Cortex-M4).
- Highlight the “MFlash512/ Flash” line in the table and click on the 'Delete' button.
- Highlight the “Ram0_64/RAM” line in the table and click on the 'Delete' button.
- Highlight the "Ram2_8/RAM2" line in the table and click on the 'Delete' button.
This should leave just the “Ram1_32/RAM2” line. This is the memory block that the Cortex-M0+ slave image will be executed from.
Then click through until you can click 'Finish'.
Step 2 - Create master project
Go to either
- Quickstart -> New project -> LPC5410x -> LPC5410x Multicore (M4 master):
- Quickstart -> New project -> LPC5411x -> LPC5411x Multicore (M4 master):
- Select required project type (e.g LPCOpen - C Project) and click Next.
- Enter project name, say mc_master, and click Next.
- Select the required target MCU, say LPC54102J512, and click Next.
- On the LPCOpen Library Project Selection page, select the LPC5410x chip library for the M4, say lpc_chip_5410x, and then the appropriate board library, for example lpc_board_lpcxpresso_54102, and click Next.
- Click Next through CMSIS DSP Library selection and Part specific options pages.On 'Other options', ensure Code Read Protect (CRP) is ticked.
- On ‘Memory Configuration Editor’ leave the memory definitions as per the default.
- On 'Multicore Project Setup' page, use the 'Browse' button in the Multicore Slave Project selection box to select the Multicore M0+ project that you created previously:
Then click Next, then Finish.
If you now select the master project in the Project Properties view, then select the Build option in the Quickstart view, this should trigger a build of the slave project, followed by the master project (and if necessary also the LPCOpen library projects).
Note that a copy of the executable generated by the Slave project will actually be embedded into the Master project executable.
Overview of debugging a master / slave project pair
Note: LPC541xx debugging is only supported via LPC-Link2 with NXP's CMSIS-DAP firmware.
Start a debug session for Master project using the Debug option in the Quickstart view.
When prompted, select SWD target to connect to, which in this case is the one labeled in the ‘Details’ column as ‘Cortex-M4’:
Note that this setting will get stored in the project’s debug launch configuration, and so should be remembered between debug sessions.
Having selected the appropriate core, LPCXpresso should download the executable containing both the Master and Slave images into the target MCU flash memory.
Once the connection has been made, you should hit the default breakpoint at the start of main() in the Master executable :
At this point, select the Slave project in the Project Explorer view, then use the Quickstart view Debug option to start a second debug connection.
Select SWD target to connect to. Note that as long as you have already connected to the M4, then the M0 slave should be selected automatically...
Note: In LPCXpresso IDE 7.6.2 and later, The Cortex-M0 will appear as Device 1, not Device 16.
LPCXpresso should detect that this is a Slave project and make an ‘attach only’ connection (and hence not download code and leaving the slave image 'executing').
Now step over the boot_multicore_slave() function in the master image, and the slave core will begin to execute, hitting the default breakpoint on it’s main():
You can now debug both cores in parallel, selecting which core to step, resume, suspend, etc by switching between them in the Debug View.
Note: Although there is no debug logic synchronising debug operations on the two cores, you can select both applications at the same time in the Debug View (typically by using CTRL-Click) and operations like step, resume, suspend, etc will then be carried out on both cores by the debugger in parallel.
The currently selected core will be the one used for displaying many of the debug related views, such as Registers and Locals. It is also possible to create copies of many of the debug related views, and lock each copy to a particular core.
For example, to create two register views, one for the M4 and one for the M0+ ...First of all, use the “Open New view” button in the Registers view to create a second Registers view:
Now pin the original view to the core currently selected in the Debug, using the “Pin to Debug context” button :
Now select the other core in the Debug view, and go to the second Register view. Use this view’s “Pin to Debug Context” button to lock this second Registers view to the selected core:
Note that when you have finished debugging, you can use “Terminate/Disconnect All” button on the icon bar to disconnect the debug connections to both the Master and Slave cores at the same time:
Multicore projects – additional information
A number of compiler defines are automatically created for LPC5410x projects to allow conditional compilation of certain blocks of code depending upon whether a specific project is configured to be a slave, a master or neither.
- Defined automatically by LPCXpresso for a project that has been configured to be a Master project
- Defined automatically by LPCXpresso for a project that has been configured to be a Master project and has had a Slave project associated with it (hence indicating to the Master project which cpu type the Slave project is for).
- Appropriate one defined automatically by LPCXpresso for a project that has been configured to be a slave project
- Defined automatically by LPCXpresso for a project which has not been configured as either a slave or master project
Note: The multicore support within LPCXpresso IDE is highlighly flexible and provides functionality beyond that required for the LPC5410x family. Thus the symbols __MULTICORE_MASTER_SLAVE_M4SLAVE and __MULTICORE_M4SLAVE are also provided for completeness, but are not required for any existing parts.
Slave boot Code
boot_multicore_slave() is called by the Master project code created directly by the LPCXpresso project wizard to release the Slave core from sleep. This calls functions from LPCOpen package for LPC5410x which are supplied in pre-built library form. This means that it is currently only possible to create and build LPC5410x multicore projects which are linked to LPCOpen.
Note that the source files containing this function will be included in all LPC5410x projects, but will be conditionally compiled so that it is included only when required. This has been done to allow projects originally created, for example, as a slave project, to be reconfigured (via the project properties – linker multicore tab) as a master project.
Be aware that if you look at the multicore projects provided within the LPC5410x LPCOpen package, the slave boot code is incorporated directly into the main function. However this carries out the same initialisation as the code generated by the LPCXpresso wizards.
Reset Handler code
When configured as a master project, the LPC5410x startup file will be built with additional (assembler) code at the beginning of the reset handler, ResetISR(), with the ‘standard ‘ reset handler code moved to ResetISR2().
This additional code is required in order to allow correct booting of both the Master and Slave cores. It is written in assembler in order to force it to be ‘Thumb1’ code, and hence runnable by both cores.