Brief introduction
This page provides some basic information on using the dual-core features of the LPC43XX device. The information and topics on this page are demonstrated using the Keil UVision4 tool, using dual-core engineering. The project initializes two cores to run FreeRTOS and uses a tri-color led to indicate the operation of the M0 and M4 cores, as well as the communication between the dual-core processors. The project focuses on the details of the dual-core project, and strives to be basic and simple.
Layout and memory usage of executable images
Shared peripherals and memory resources
Driver initialization code
Inter-processor communication through shared memory and interrupt events
Dual-Core Commissioning
Potential issues and considerations
What this project does
This project creates a bootable image for the M4 kernel that loads, sets up, and starts the M0 kernel (using an image embedded in the M4 binary image or an address in memory). All two cores run FreeRTOS, where the M4 kernel uses the cortex M4 system timer as the RTOs timer, while the M0 core uses timer 0. M4 kernel initialization requires most of the chip peripherals-including the M0 core timer 0. Both cores use the same 1KHz beat rate for FreeRTOS.
This project can be configured using one of the following two methods:
As an event-driven (integer mode) with no M0 kernel queue and feedback
Event-driven as a queue and feedback between M4 and M0 dual-core
When no queue is running, the M4 kernel provides interrupts at different times to the M0 core. At each interrupt, the M0 core switches the green component of the tri-color led. When the M4 core is stopped, the green LED will stop blinking immediately.
When there is a queue running, the M4 core provides a green component of the tri-color led in the time queue. The queue is filled (as fast as possible) at one end of the M4 kernel, while the M0 kernel consumes queue items based on the entry time of each queue item. When the M0 kernel consumes an item, it sends the M4 kernel a signal that the item has been released, and the M4 kernel will refill it. If the M4 core is stopped, the green LED will continue to blink at the rate defined by the queue until the queue is empty.
To help determine that the kernel is running, the M4 core blinks at about 0.5Hz at a frequency of red led,m0 cores flashing blue LEDs at approximately 1Hz.
When operating normally, the red, blue, and green components of the tri-color LEDs switch at different rates. Stopping or starting a core (via JTAG) will cause the red or blue LEDs to stop switching. Restarting any of the cores will allow the queue management process to continue. When a queue is used, the queue is shared between the two cores and the Iram 0x10080000 location. When the system is running, you can see in shared memory that the queue is being updated with two cores.
The configuration options for this project are located in the Shmem.h file.
Code:
Note: Paste some tapes or files on the tri-color LEDs on the Hitex 4350 board to reduce their brightness. It's very bright! Don't stare at led! for a long time.
The code can be downloaded from the Project contribution page: HTTP://WWW.LPCWARE.COM/CONTENT/CONTRIBPROJ/LPC43XX-DUAL-CORE-FREERTOSX2-...
For specific steps on how to compile, load and run the project see: Http://www.lpcware.com/content/project/lpc43xx-dual-core-notes/lpc43xx-d ...
The configuration options for this project are located in the Shmem.h file.
Code Overview
The project consists of two Keil uVision4 projects-a M0 core project, a M4 kernel project. In this project, the M4 kernel embeds an image of M0 into its executable file, although this is not a necessary way.
M4 Code sequence
M4 initialization
The M4 kernel code initializes the system in the following manner:
System alignment and Configuration (CGU)
Pin multiplexing (tri-color LED)
Debug framework
Set timer 0 to 1kHz rate. Timer 0 can be set as part of the M0 kernel initialization sequence, but adding a timer driver causes the M0 image to grow larger. The timer driver also relies on the CGU driver (and possibly other drivers), so joining such a simple driver might significantly increase the size of the image, since all two cores have a copy of the driver. Another consideration is how the driver initializes the hardware. Because the timer driver requires CGU drivers, and some of the CGU-driven data is initialized at runtime (that is, through the Cgu_init () method), when the CGU driver is initialized in the M4 kernel and then initialized in the M0 kernel, this may change the system's CGU settings-- Causes the CGU data state in the M4 kernel to be inaccurate.
Start FreeRTOS when the system timer is 1KHz and the initial task will start
M4 Initial Tasks
The initial task for FreeRTOS in the M4 kernel performs the following actions:
Clear shared Memory queue
Create a sync signal for the M0 core interrupt Event
Preparing and starting the M0 kernel
Place the M0 core in the reset position
Start the M0 core timer (at M4 core speed)
Set the M0appmemmap register to point to the M0 base code
Release the reset key for the M0 kernel
Setting up and enabling event interrupts for M0 to M4 cores
Create and start a communication task between processes
Continuously switches the red portion of the tri-color led at approximately 0.5Hz
M4 inter-process communication tasks
The interprocess communication task FreeRTOS in the M4 kernel performs the following actions:
If you do not set up in queue mode, repeat the following actions
Generating an interrupt event in the M0 kernel
Wait. 333 seconds
If established in queue mode, repeat the following actions
Continuously pushes events into the shared memory queue until the queue is full
Waits for an event sent from the M0 kernel that emits at least 1 queue items for idle signals
The M4 kernel initiates interprocess communication tasks using binary signals from M0 to M4 interrupt events. In each event, the queue items are re-declared and populated as needed. Note that a count signal can be used to count events, but if M0 sends several events to the M4 kernel quickly, but the M4 kernel is too busy to handle two events, it acts as an event. Over time, this can result in a count signal loss value. For example, if the M4 kernel is processing a timer interrupt, the kernel interrupt M0 to M4 is waiting, but is preempted by a higher priority interrupt, the M0 kernel sends an event before the M4 kernel can handle it, and the two events sent from the M0 kernel will be 1 events for the M4 kernel.
M0 Code sequence
M0 initialization
The M0 kernel does not do any initialization because all of them are executed by the M4 kernel! It starts FreeRTOS directly and starts the initial task.
M0 Initial Tasks
The initial task for FreeRTOS in the M0 kernel performs the following actions:
Enable timer 0 Interrupt for FreeRTOS timer (started from M4 kernel)
Create a signal synchronization for interrupt events from the interrupt event of the M4 core
Create and start a communication task between processes
Continuously switches the blue portion of the tri-color led at approximately 1Hz
M0 inter-process communication tasks
The interprocess communication task FreeRTOS in the M0 kernel performs the following actions:
If you do not set up in queue mode, repeat the following actions
Waiting for events from the M4 kernel
Toggle the status of the green LEDs
Wait. 333 seconds
If established in queue mode, repeat the following actions
Waiting for events from the M4 kernel
Remove an event from a queue
Setting the status of green LEDs based on events
Defer tasks based on events
Send a signal to the M4 kernel to indicate that the event is complete
JTAG settings for dual-core debugging
The Keil ULINK2 Jtag Debugger on the Hitex LPC4350 board uses the Keil uVision4 IDE. The board uses a 10-pin JTAG connector. When the IDE scans the JTAG bus through ULINK2, it detects 2 cores. For each core project, JTAG needs to be set for the kernel it will use. Each core can be independently debugged with its uVision4.
For M0 Engineering, the JTAG configuration is shown in the two figure below. M0 debugging will always attempt to attach to a running image without changing the contents of the system or kernel.
For M4 Engineering, the JTAG configuration is shown in the two figure below.
JTAG Image Setup Script
When the image is loaded in the M4 kernel to run both the M0 and M4 cores, the M0 kernel should remain reset before downloading. This can be done through the JTAG initialization script before downloading. M0 and M4 core interrupts should also be disabled in Creg M0txevent and m4txevent registers to prevent spurious interrupts at the beginning of the program.
Layout and memory usage of executable images-different Iram
The M0 kernel has a limited boot address. The M0 core is idle when the system is started for the first time after the reset. The M4 kernel starts first, setting the M0appmemmap register-it points to the base address of the M0 boot code-and then starts the M0 kernel. Due to the 11 ... in the M0appmemmap register. The 0-bit must be 0,M0 kernel only from starting with 64K boundary code.
The following table shows the layout used for Iram-based engineering. Iram-based engineering can be loaded and booted via JTAG or DFU boot.
Zone Kernel address range Description M4 code/Data area M4 0X10000000-0X1000FFFF includes code and data up to 64K M0 code/Data area M0 0X10010000-0X10017FFF includes code and data up to 32K extra Iram /idle 0x10018000-0x1001ffff Shared memory area m0/m4 0x10080000-0x10083fff M0 and M4 kernel, one of the good features for the queue M0 kernel is that It can have the same memory mapping as the M4 kernel (mostly). So, you can link the M0 image to an SPI flash or nor flash of the system's flash address. When you use the M0APPMEMMAP register to map address 0x00000000 to the flash of address I, the M0 kernel only needs to use address 0x00000000 as the original stack value and the load of the PC counter, The PC counter points to an address in Flash (that is, 0x1cxxxxxx).
M0 Engineering--iram Version
In M0 's Iram version of the project, the code was compiled to run in address 0x10010000 with a maximum space of 32K (code, data, stacks, and heaps). If the total memory usage of the M0 run-time image exceeds 32K, the link step will fail. When run from Iram, it places the image in the Iram memory range of 128K, bounded by 64K. The 32K of the 64K and M0 images before the M0 image can be used by the M4 kernel. The following is a link script setting for M0 code and data--including stacks and heaps--all the code, data, heap allocations, and stacks will be in this range.
Er_ro 0x10010000 nocompress 0x8000 {
STARTUP_LPC43XX_M0.O (RESET, +first)
*.O (+ro)
*.O (+RW, +zi)
Note the use of the Nocompress property. If the M0 image is embedded in the M4 image and does not have a static size, the data may be compressed in the linked image and then decompressed at run time. If M4 code or data is directly behind an embedded M0 image, M4 code may be rewritten when decompressed. The Nocompress property stores the uncompressed pre-initialized data to prevent such a phenomenon from occurring.
M4 Engineering--iram Version
In the Iram version of M4, the code is compiled to run in address 0x10010000 with a maximum space of 64K. The M0 image is located at address 0x10010000 (matching the link address of the M0 image) with a maximum space of 32K and 64K queues. By placing the image in a pre-linked M0 boot address, the M4 kernel does not need to copy the image to its correct location at run time, M0appmemmap can point directly to an image that is in memory.
The M4 link script is as follows. Note that the M4 image is populated with 0x0--which will keep the data in the M0 image in the correct place, thus helping to generate a binary image-this is not a problem when creating a hex file ... Unless you increase the size of the file. Note also that the M0 image is populated, although not necessary in this setting, but if the data or code is placed directly after the M0 image, this guarantees that the data is not in the M0 memory area.
Er_ro 0x10000000 Padvalue 0x0 0x10000 {
STARTUP_LPC43XX.O (RESET, +first)
*.O (+ro)
*.O (+RW, +zi)
} er_ro2 0x10010000 FIXED padvalue 0x0 0x8000 {
INCM0.O (+ro)
} M0/M4 Shared Memory area
The Iram located at address 0x10080000 is used for shared memory queues. Although both M0 and M4 both read and write in the queue for this region, they do not have both reading and writing permissions on the same part of the queue. The data values modified by the M4 kernel are readable only by the M0 kernel, while the data values modified by the M0 kernel are readable only by the M4 kernel. With this approach, shared data regions do not need to be managed as a critical area.
Layout and memory usage of executable images--Different flash
The different flash of these works is similar to the Iram version, but there are the following differences:
Two cores of image code and read-only data, stored and executed in Flash
Pre-initialized data regions must be copied to Iram before they are used
The following table shows the layout of the flash-based project. The data segment will be copied and initialized at run time, but two cores will execute code outside of Flash.
Zone Kernel address range Description M4 code area M4 0X1C000000-0X1C00FFFF includes code and data up to 64K M0 code area M0 0X1C010000-0X10007FFF includes code and data M4 to 32K data area M4 0x 10000000-0X1000FFFF pre-initialized RW data, Zi data, heap, stack, maximum 64K M0 data area M0 0x10001000-0x10017fff pre-initialized RW data, Zi data, heap, stack, max 32K extra iram/idle 0x100 18000-0X1001FFFF Shared memory Area m0/m4 0x10080000-0x10083fff M0 and M4 cores for queues
Shared peripherals and memory resources
The M0 and M4 cores share the same memory mappings and can access the same system resources. The following guidelines may be helpful for memory access and event sharing.
Avoid the use of inter-processor interrupt events to generate count events. If the processor receiving the event is busy (that is, it is processing a higher priority interrupt) and cannot immediately handle a kernel outage, it suspends the event until it can process it. At that time, other cores could produce another event, causing the original event to be lost.
When creating an image for each core into a specific memory layout, ensure that the link script monitors the size of the image-code and data-to prevent code/data from overlapping at run time. Just because an image link at an address doesn't mean it will run in the same area! Linking scripts are used in conjunction with the nocompress, Padvalue/fill, and region size properties, which helps to strengthen the layout and notifies you of any possible memory conflicts when they are linked.
Consider using a minimum number of drivers for a kernel. A seemingly simple driver may depend on other drivers and can significantly increase the size of the image.
Remember to initialize the driver when using a driver in two cores. For example, if you use the CGU driver in two cores, the driver that finally calls the Cgu_init () method overrides the CGU configuration of the other kernel settings.
If you really need a shared memory area that is protected by a key zone lock, you can test and set the shared memory lock using the cortex atom ' load and storage (LDREX,STREX) directive. M0 and M4 do not stagger access to the shared zone. Alternatively, you can use a bit band.
Can I share code between two cores?
Use the arrows to expand or collapse this section, but the code needs to be compiled within the M0 instruction set because the M0 kernel has only one subset that can be used for M4 kernel directives.
Inter-processor communication through shared memory and interrupt events
Each core has an interrupt that can be triggered by another kernel (or its own kernel). For two cores, this is Nvic interrupt number 1th. To generate an interrupt for another kernel, you can use one of two methods.
Method 1:sev directives
Setting an event instruction will result in an interrupt for the other kernel. If the directive is executed in the M4 kernel, it will generate interrupts in the M0 kernel. If executed in the M0 kernel, interrupts will be generated in the M4 kernel.
void Signal_other_core (void)
{
__DSB ();
__sev ();
} Method 2: Call through Creg
The CREG m0txevent and m4txevent registers can be used to generate events directly. Unlike the SEv directives, they can be used to generate an interrupt in another kernel or in their own kernel.
Generates an interrupt (from any kernel) in the M0 kernel, using the
Lpc_creg->m4txevent = 0x1;
Generates an interrupt (from any kernel) in the M4 kernel, using the
Lpc_creg->m0txevent = 0x1;
In both cores, setting the value of M0txevent or m4txevent to 0 clears the interrupt event.
In the M0 kernel,
Lpc_creg->m4txevent = 0x0; In the M4 kernel,
Lpc_creg->m0txevent = 0x0;
LPC43XX Dual-Core notes