Device Firmware Update (DFU) over USB on LPC4353

I would like to be able to program my microcontroller (LPC4353) over USB. For this, I have found the USBDEV_ROM project on IAR's information centre. The project includes code for a composite device (HID, DFU and mass storage). When I run the program, it enumerates OK (appears in Windows 7 device manager in HID category) and a 32 kB mass storage device appears in Windows explorer.

Initially in the "Other devices" category in device manager, a DFU device appears with an exclamation mark. I have downloaded AN4370SW, which contains a DFU_winusb_driver. The folder contains a DFU_Device.inf and DFU_Device_Runtime.inf. In device manager, I'm able to manually direct windows to use one of these inf files. If I do this, a "DFU device" category appears in the device manager along with a "Device firmware upgrade". Am I using the correct drivers? Have I followed the correct steps so far?

To check that the embedded code is doing what I think it should be doing, I would like to download a bin file over USB. What is the correct procedure for this? I've seen a number of programs mentioned on the NXP website: LPCscrypt, DFU_demo (comes with AN4370SW), dfu-util from sourceforge and LPCExpresso. None of these work for me. I've included the output from dfu-util at the bottom of this post.

I've made some progress: I've been able to associate the lpc-composite89-dfu.inf that was installed with LPCScrypt with my device. When I run my DFU code on my micro, it comes up as HID and as "LPC DFU device" in Windows' device manager.

If I power cycle my micro, the downloaded program doesn't appear to run. My bin file was output by IAR. I'd setup the vector table to start at 0x1A000000. Based on this, I tried the following to set the base address to 0x1A000000:

You can't download to a flash address, you can only download to a RAM address. For flash you need to to perform a programming, DFU doesn't include any flash programming algorithm.

The standard approach for DFU is that you download a secondary loader into internal RAM, this starts running and manages then the download and programming of the firmware into internal (or external) flash.

So if I understand correctly, it is possible to reflash the microcontroller by making it go into Boot ROM (which I've just done) OR by writing a custom Bootloader with USB-DFU (usbd_rom_dfu_composite) [not working yet] ?

When my device will be in the field, I'd don't want the reprogramming capability over USB to be exposed. I was considering writing a PC application (HID) that would send a command to the microcontroller to put into reprogramming mode. What's the best way to achieve this?

If P1_2 cannot be put on LOW level, then you can't get into USART0/USART3/USB0 bootmode.

But booting on USB1 would be possible.

Another option to program the flash in the development phase is the JTAG port.

In your application you can establish whatever you like for a firmware upgrade. To protect against unauthorized access you could use the Code Read Protection (CRP) mechanism.

Writing a waterproof firmware upgrade mechanism is a job on its own, especially when you use a more complicated i/O block like the USB or Ethernet for getting the new firmware over. I don't have any mature example project for this.

During development I normally flash my microcontroller using JTAG. I'm wanting to be able to reprogram my microcontroller in the field using USB.

In the short term, I could probably get around my P1_2 accessibility issue by setting the BOOT_SRC bits in the OTP register. I would also need to solder a wire onto P2_7 so that I could put the micro into ISP mode.

In the long term, would a bootloader made up of the usbd_rom_dfu_composite and periph_flashiap example work? This should make the micro enumerate as HID and DFU. Once the code is downloaded to RAM I could then write it to flash. What do you think?

When my device will be in the field, I'd don't want the reprogramming capability over USB to be exposed. I was considering writing a PC application (HID) that would send a command to the microcontroller to put into reprogramming mode. What's the best way to achieve this?

This means you have closed the standard mechanisms which are in the chip by default (the ISP mode)

Therefore you need to develop your own In-System-Programming mode

If you do this from the application, this functionality is just part of the normal firmware binary. Then you need to find a good way to make the update waterproof

If you want to go into a reprogramming mode after startup, for example by pressing a specific key combination at power-up, then it's better to establish a seperate bootloader firmware. Then you could lock this bootloader firmware somehow, so that the product is always able to come up at least in reprogramming mode if something went wrong with a firmware programming cycle.

Of course this approach with the standalone bootloader is also possible when you trigger the firmware update out of the application, for example selecting it from a display menu. Then you go out of the application binary, jump into the bootloader binary and manage things from there until the update was successful.

You can use the integrated USB ROM features for this, if you think that they give you the right functionality

The Chip_IAP_ReinvokeISP invokes the Bootloader ISP. Does this just allow ISP over UART? Can this be overwritten by the OTP boot src bits OR (P2_9, P2_8, P1_2 and P1_2)? Is there a function available for making the micro jump to USB0 ISP? If this was to work, no additionnal code would be required.

So if the above can't be done, I would need to implement IAP in my Bootloader by downloading my bin file to RAM and then copy it to flash. Since my Bootloader code would always need to be available, it would be running from flash in say Bank A. With this arrangement, would it be possible to read the code in RAM and copy it to Bank B (using flash IAP driver) and then reboot to run my application from bank B? Or does the code that is doing the copying need to run from RAM?

I have started working on my program. My bootloader program is based around the USBDEV_ROM example from LPCOpen using the default icf linker configuration file. So with these default settings my program should be running from flash bankA. I then use the dfu-util.exe program to download my bin file to the micro. Does my bin file need a header (with prefix/suffix)?

When the DFU download complete flag is set, I can view the correct code in RAM in my debugger (Memory 1 at 0x20004000 onwards). I then erase the entire bankB before copying the contents of the RAM in 4096 byte blocks to bankB (modified version of flashiap example). In each case the return code is 0. I then compute the signature and finally I set the bootflashbank to bank B.

Are the last 2 steps necessary or would the bootflashbank be sufficient? The userguide says something about it also computing a signature.

Unfortunately whenever I power cycle my micro, it doesn't appear to be running the new program.

If I remember correctly, the ReinvokeISP with the LPC1800/4300 is a little bit tricky, in case you can't modify the physical boot pins in this situation.

If you have foreseen a physical switch or a key in your product for one of these boot pins, then everybody can simply go into the ISP mode (UART or USB, depending on the pin configuration). This is not what you want.

With hardcoded boot pin settings (either fixed on the PCB or with the OTP bits) you have the same problem.

I worked out a procedure a few years ago for this, I need to check where it is.

For the bank-A/bank-B image flash signature see the User Manual Rev 2.3. in chapter 5.3.1.

It would be interesting to see your ReinvokeISP procedure from USB0. I tried to do it on the MCB4300 evaluation board, but it didn't work, despite boot pins being set. I thought it could only be done with the UART? Can you confirm?

I've been able to download a program into RAM and copy the contents of the RAM into the flash BankB. If I powercycle my microcontroller the downloaded program runs :-). I had a number of issues with my code and linker settings.

The LPC4353's flash banks are both 256kB and the RAM is up to 136 kB, which means that I won't be able to buffer a bigger program in RAM, which probably means that I would need to split the binary file. What's the best way to do this, use srec_cat (http://srecord.sourceforge.net/)?