-
Notifications
You must be signed in to change notification settings - Fork 16
MCU Info Page: LPC1768
The LPC1768 was the very first MCU to receive support from Mbed back in 2009, and it's one of the only early MCUs that's still supported in the latest Mbed version. While it might be getting a little long in the tooth, with fairly high power consumption and small RAM compared to its modern competitors, it's still a capable chip with a large array of peripherals. Not to mention, it has a significant base of educational users who rely on the Mbed LPC1768 dev board for their courses and projects. Here's hoping we can keep this venerable chip supported for a long time coming!
Note: Confusingly, the LPC1768 MCU's dev board is also called the LPC1768. This seems to be an early naming standard that was later dropped. On this page I'll say "the dev board" when I specifically mean the LPC1768 PCB; otherwise I mean the microcontroller itself.
CPU | Flash/Code Memory | RAM | Communication Peripherals | Other Features |
---|---|---|---|---|
Cortex-M3, up to 100MHz (clocked at 96MHz on the dev board) |
Total: 512 kiB Available to user:* 481.5 kiB |
Total: 32 kiB (SRAM) + 16 kiB (AHBSRAM0) + 16 kiB (AHBSRAM1) Available to user:* 19.1kiB See note about memory banks below |
|
|
*"Available to user" subtracts both regions of memory unusable by default Mbed OS projects and the baseline memory used by a minimal build of Mbed OS.
The LPC1768 divides its RAM into three banks: main SRAM, AHBSRAM0, and AHBSRAM1. The AHBSRAM banks are optimized for use with DMA, but are also usable as standard RAM. However, they are not contiguous with the first one, so the GNU linker is not able to automatically place items in these memory banks. Thus, only the first 32k bank is available to naive code.
To make use of these memory banks, you need to manually place items in them using an attribute declaration. If you have code like this:
SomeLargeObject obj;
change it to:
SomeLargeObject obj __attribute__((section("AHBSRAM0")));
This will move the object into the ABHSRAM0 bank. This can be used on both global variables and static variables inside functions.
Additionally, when Ethernet connectivity is used, Mbed automatically places the networking buffers into AHBSRAM1.
As of 2022, new LPC1768 dev boards are still being shipped with very old firmware on their interface chips. Not only does this firmware not support debugging, it also makes thread sleeps run for an incorrect amount of time! You will find that your MCU sleeps for 10ms when you tell it to sleep for 1ms! No, I don't know why this happens, but I do know how to fix it.
To update the firmware, simply download this file and save it onto the LPC1768 dev board's USB drive. Then, unplug the USB connection to turn off the power and plug it back in again. Leave the board alone for a few seconds, and it should flash the firmware and boot like normal.
More details on the interface firmware here.
Mbed OS currently uses a fixed clocking configuration for the LPC1768. A 12Mhz input clock is required, either by connecting a crystal between XTAL1 and XTAL2, or by connecting an external 1.8V oscillator to XTAL1. See the electrical datasheet section 15.2 for details.
Additionally, a 32.768kHz crystal can be connected to the RTCX1 and RTCX2 pins to provide a clock source to the RTC. However, this is optional, and the crystal is not even powered up until the RTC is used in code.
Thanks to being the original Mbed design, this board has a unique feature that is no longer found on any other Mbed targets: the LocalFileSystem. Most Mbed boards emulate a USB drive, allowing you to drag and drop bin files onto the board to program it. The LPC1768 dev board takes this a step further, and allows your code to actually read and write files on the very same virtual USB drive.
How does this work? Well, it's a bit complicated. Essentially, the interface chip (the second MCU on the bottom of the LPC1768 dev board) is always debugging the LPC1768, even when you do not have a debugger connected. This interface chip is also connected to a 2MB flash that stores the virtual USB drive's data. When you interact with the LocalFileSystem, code inside Mbed stores magic values in certain registers, then issues a "bkpt" instruction to manually trigger a debugger break. The interface chip detects this breakpoint, carries out the requested operation (e.g. reading from a file), stores the data into the LPC1768's memory, and then unpauses the MCU. This Rube Goldbergian mechanism (using debugger breakpoints to transfer data) is called semihosting, and can also be used to transfer text between a host PC and a microcontroller (replacing a UART terminal). It was used on a lot of earlier ARM dev tools, but seems less common these days, perhaps because it has serious performance penalties.
However, there is a pretty major problem with LocalFileSystem as currently implemented: sleep mode. When the LPC1768 goes to sleep, the mbed interface debugger gets disconnected, and the semihosting connection is broken. This means that LocalFileSystem, and other semihosting features, will no longer be operational.
This is a serious issue because there are a lot of potential places the MCU can go to sleep. If you are using mbed-baremetal, sleeps will only really happen when you call ThisThread::sleep_for()
or one of the other sleep functions, so you just need to avoid those (wait_us() is safe). But if you are using mbed-os, sleeps occur whenever the idle thread runs -- basically, whenever a blocking operation like a sleep or a wait for a mutex happens and there is no thread that's able to execute. So, if you really want semihosting to work, you need to ensure that there is always at least one thread able to run at any given time in your application. One workaround is to create your own idle thread with a higher priority than the Mbed idle thread which does not sleep:
[[noreturn]] void sleeplessIdleFunc()
{
while(true) {}
}
Thread sleeplessIdleThread(osPriorityLow, OS_STACK_SIZE, nullptr, "Sleepless Idle Thread");
void main()
{
sleeplessIdleThread.start(&sleeplessIdleFunc);
...
}
Despite these issues, LocalFileSystem might still be useful if you just want to make a simple application which saves data onto the dev board memory, with minimal code and no external storage. For an example of how to use this API, see the Mbed CE LocalFileSystem example!
One of the 32-bit timers, TIM3, is used to implement the Mbed us_ticker. The other three timers, TIM0 through TIM2, are available for application usage.
This dev board is a bit harder to debug than most Mbed targets. First of all, the debugging interface didn't exist until the latest interface chip firmware revision. So, make sure to do the "Dev Board Firmware Update" section first. Additionally, while pyOCD used to work with this device, a change in version 0.11 broke something, so only 0.10 and older work (and those versions only run on Python 2.7, blech!). So, as of 2022, the only supported debugger option is OpenOCD (with some workarounds implemented by Mbed CE). If you install OpenOCD and use -DUPLOAD_METHOD=OPENOCD
, you should be able to flash and debug the LPC1768 just fine.
The LPC1768 can make use of interrupts (InterruptIn) on any of the port 0 or port 2 I/O pins (on the dev board, that's every pin except p19 and p20). However, each port shares a single interrupt for all its pins, so performance might not be great if you have a lot of different interrupts firing on different pins, since the interrupt handler has to read the interrupt registers to figure out which pin(s) triggered the interrupt.
There are also four external interrupt (EINT0-3) pins which have dedicated interrupts, but these are not supported natively by Mbed. Note also that the EINT3 interrupt number is shared with regular GPIO interrupts, so only EINT0-2 are usable as truly dedicated interrupts.
The current Mbed OS implementation for this MCU does not support deep sleep, due to an LPC1768 issue which prevents the MCU from waking up if a debugger is connected when it enters deep sleep.
See AN10915 section 4.4.6 for details.
If you make a custom board with the LPC1768 MCU, and you compile your code for the LPC1768
Mbed target, you will probably get random-seeming crashes. The reason for this is, operations like sleeping attempt to interact with the Semihosting API, which tries to communicate with the Mbed interface chip using BKPT instructions (see above). If this chip is not present, bad things happen.
To fix this problem, create a custom target (e.g. STANDALONE_LPC1768
) with a custom_targets.json file like this:
{
"STANDALONE_LPC1768": {
"inherits": ["LPC1768"],
"device_has_remove": ["LOCALFILESYSTEM", "SEMIHOST"]
}
}
This turns off the semihosting features, allowing code to run without an interface chip present. Needless to say, the semihosting and LocalFileSystem APIs will be unavailable.
The LPC1768 dev board includes an integrated Ethernet PHY, but needs external magnetics and an ethernet jack in order to actually communicate over the network. One easy way to do this is using a SparkFun MagJack breakout, hooked up per the diagram here.
- Mbed LPC1768 dev board schematic (note, this is an HTTP download, so you may have to copy the URL to a new tab to get it to download)
- Electrical Datasheet
- Programmer's Reference Manual (behind registration wall, but free)
- Errata