The Positive Rail
  • Blog
  • About
  • Contact

LPC 1873 USB ROM and SD Card

2/17/2015

2 Comments

 
One of the development boards I've been using recently is the LPC1830-Xplorer from NXP Semiconductors.  It is built around the LPC18xx series of Cortex M3+ based microcontrollers.  What makes this particularly interesting is that the LPC18xx series (and its M4 based LPC43xx siblings) have a high-speed USB 2.0 PHY built into the chip (along with a second USB controller).  The PHY is the physical driver for the USB port.  This eliminates an extra chip (along with about 10-15 wires) and a lot of complexity.  

Although many chips have full-speed USB 2.0 PHYs (capable of 12Mbps, 1.5MB)  built in (e.g. the KL25), I haven't seen another yet that has a high speed (480Mbps, or about 60MB per second).  The higher capacity is particularly important for some of the applications I am considering, which use large amounts of SD memory.  It also has a full SDIO controller so it will be able to communicate with SD cards at full bandwidth, and I hopefully should avoid many of the problems I ran into using the SPI bus.


The LPC1830 comes with a full development kit and IDE called LPC-Xpresso.  Here are some of my notes on getting the kit up and running, and on my first test application - combining the USB functionality with the SD card to make a basic USB-SD card reader.
There are a couple of things you need to know about the kit to get it running

  • Documentation and schematics: LPC contracted to NGX Technologies, based in India, for the board.  The quick start, schematic and user manuals (including pinouts) can be found on their website.  There is also some sample code - but this code appears to be an early subset of the code that is released with LPC-Xpresso.
  • Windows 8 bug in LPC-Xpresso Eclipse IDE: it turns out that Windows 8 broke some of the UI code that Eclipse uses.  What happens is that if a dialog box pops up and it is supposed to list several items, the first item is not visible.  This is especially problematic if there is only one item on the list, as it looks like a blank list.  This occurs when you are playing with settings, and most regularly when you are prompted to choose a debug device - it simply doesn't look like there is one, even though there is one on the list.  Press 'continue' and it will go.
  • LPC1837 vs LPC1830: The board is called the LPC1830-Xplorer and most of the demo software assumes an LPC1830 processor, which is a flashless version of the LPC18xx series.  But the kit itself contains the LPC1837 processor, which has on-board flash.  Therefore, to get any of the demos to work, you need to set the compiler settings in LPCExpresso to compile against the LPC1837, not the LPC1830 - otherwise it will load but the program will stall.  To do this, go to the Properties pane for the project and drill down to the 'MCU Settings' page under 'C/C++Build'.  Switch the target MCU to the LPC1837.  It will tell you that you will lose some manual settings - this is ok as those settings are only if you're using an 1830 hooked up to external flash.
  • Overriding default interrupt handlers: When I first started playing with the projects, it seemed like none of my interrupts were being triggered - interrupts would always fall through to the default handler.  It turns out that when using C++ (I had chosen the C++ option when building my files)you need to encapsulate your interrupt handlers in an extern "C" {} wrapper.  The symptom of this is that your interrupt handler (e.g. SDIO_InterruptHandler) is not being called, even though you have it defined.  LPC describes the problem in their FAQ on startup code and interrupt handler
  • The SWD debug port supplies power to the board - so you don't need to supply an external USB plug.
  • The UART pins are pins 9 and 10 on jumper 8 (I don't remember which is TX and which is Receive) - baud rate is 115200 and it appears as cu.usbserial-xxxxx on my Mac.  Ground is pin 0.

I got the basic examples running by following the instructions for LPC-Xpresso; the debugger is nice in that it includes not only CPU registers but a complete set of peripherals.  Then I set to work on the USB and SD card examples.

One the other, less obvious interesting features about the chip is that the USB stack is implemented in ROM - it includes code for CDC (Communication Device Class), DFU (Device Firmware Upgrade), HID (Human Interface Device) and Mass Storage Controller (MSC).  To use the ROM driver you supply a couple of parameters (e.g. memory location of its stack) and the addresses of callback functions that the ROM code calls.  Then you call the driver that you want.  I was interested in the MSC driver and hooking it up to my SD card - it looked like all I had to do was implement two functions: translate_rd and translate_wr.

It turns out that there are a couple of things I needed to figure out:
  • Early chips cannot address >2GB cards:  If you take a look at the callback function translate_read:  static void translate_rd(uint32_t offset, uint8_t * *buff_adr, uint32_t length, uint32_t hi_offset) - you can see that it passes an offset (in bytes; to find the sector divide by the sector size, typically 512), the address of a buffer, the length of the block to read (also in bytes) and the high-bytes (32 bits) of the offset.  In the sample code you combine the hi_offset and offset to form a 64 bit address.  But when you actually look at the values for hi_offset, you get nonsense.  Searching on LPC's online forums, they acknowledge that earlier versions of the ROM do not support >2GB cards and so you should ignore the hi_offset.  Unfortunately, they do not tell how to test whether you have an early or late version of the ROM.
  • Read requests with length 31: The 'length' parameter in the callback should almost always be a multiple of the sector size (almost always 512 for SD cards; it is also specified in the parameters that you pass on initializing the ROM driver) and the addresses should also be multiples of 512.  Otherwise it would be buffering nightmare to read fractional sectors.  However, when inspecting the calls, there are requests with length 31.  Again, in the online forums they explain that this is another bug - the ROM driver is mistakenly passing non-read packets.  Solution is to just ignore these requests.

  • Nested interrupts: The callbacks are called from an interrupt context, e.g. the USB is responding to an interrupt.  Unfortunately, the SD card also is interrupt driven - you have to send it a command, and then wait for an interrupt for when it is done.  The Cortex M3 has a Nested Vectored Interrupt Controller - which means that it can interrupt within an interrupt.  But you need to set the priorities correctly.  By default both the USB and SDIO cards are priority 0 - the highest priority.  And so when I was in the USB interrupt, the NVIC would not service the SDIO interrupt and my program would wait indefinitely for it.  Solution is simple - lower the interrupt priority of the USB interrupt (e.g. set it to >0 ;NVIC_SetPriority(LPC_USB_IRQ, 2))


  • Zero-copy buffers:  I was puzzled at first because it looked like, from the example, that you would want to create a separate buffer, then point the USB driver at it for reads and writes.  But the interface didn't have any synchronization - there was no way to tell it when I had finished reading a buffer (aside from returning from the function) or telling me when it was finished writing to the buffer.  It turns out I was making things too complicated.  The USB driver has an internal buffer that it exposes - this is the 'Zero-copy buffer' method.  I can then read from that buffer, or write directly to it. 

Finally after a little bit of work I got things running.  I was able to format the SD card through the USB port, add a couple of files, then remove the card and read the files using a separate reader. 

Happy USB-ing!



2 Comments
John McCabe
4/7/2018 04:06:12 pm

I've tried something similar with the LPC18S37 board (OM13076 + OM13082 general purpose expansion board) but get an error when I try to eject from Windows Explorer; did you see this at all? John

Reply
Scott Davis link
10/10/2022 05:50:27 pm

Though thank physical stock prove put sure. Nor hair yet idea. To ready director this step civil sound.
Decision prevent society. Budget institution number between.

Reply



Leave a Reply.

    What is this about?

    Embedded systems, nascent markets and minimalist product development

    Archives

    September 2014
    August 2014
    July 2014
    June 2014

    Categories

    All

    RSS Feed