Monday, September 1, 2014

Bootloader concept

Our CAN bus will work between 20 to max 100k baud rate. This limits me between 180 to max 900 CAN messages per second (given that each CAN message contains 8 bytes).

Any CAN-message consists of 47 bits overhead (including 3 bits 'Interframe Space') plus 0 to 8 bytes data (not taking into account the possibility of extra stuff-bits, which will increase the number of bits slightly). 

The used processor PIC24EP128 has 128kb of flash. In worst case, the entire flash has to be transmitted over the CAN bus for the firmware update. This means 88042 addresses of each 3 bytes will have to be transmitted. If we also include the flash address destination in each message, than again this would require 3 bytes.

With CAN, you can send 8 bytes maximum for each message. If we arrange it with 3 bytes FLASH address destination and 3 bytes FLASH data for destination, this means we can at most do 1 address for each can message thus we need to send 88042 CAN messages if the entire FLASH space is used.

With the maximum CAN bus messages per seconds that I've shown in the start, this leads to a firmware upload time between 489 seconds (8minutes) to 97 seconds. Of course, there are some optimizations reachable to reduce this.

Comm spec.
Each bracked equals a byte, max 8 byte for a CAN msg.

If mode = 255

[MODE=255][ADDR2][ADDR1][ADDR0][DATy2][DATy1][DATy0]

If mode = 254

In this mode the address will be automatically incremented. And each CAN frame will consist data for two FLASH data addresses.

[MODE=254][DATx2][DATx1][DATx0][DATy2][DATy1][DATy0]

Combining the above two methods almost reduces the time with 50%. Leaving 4 minutes as worst case scenario as wait time. For my project, this is acceptable.

If mode =  253

When all the firmware data has been transmitted, the PC will send a mode = 3 message with as data the start and end address of the FLASH memory.

[MODE=253][START_ADDR2][ADDR1][ADDR0][END_ADDR2][ADDR1][ADDR0]

This will request a CRC16 from the updated node. The CRC16 will be made up from the written data in the flash, not the received data. This is to prevent the possibility that there was a write error into the flash and to make sure that everything went fine.

If mode =  252

Erases the flash DST from start to end.

[MODE=252][START_ADDR2][ADDR1][ADDR0][END_ADDR2][ADDR1][ADDR0]

If mode =  251

Reads the flash DST and respond this on the CANbus network as a RTR

PC -> Embedded
[MODE=251][ADDR2][ADDR1][ADDR0]

Embedded -> PC
[MODE=251][ADDR2][ADDR1][ADDR0][DATy2][DATy1][DATy0]












Bootloader for PIC24E

I`m making a bootloader for the PIC24E device. The device I use is an PIC24EP128GP004. The idea is that I will place the bootloader at the end of the flash area, not at the beginning. This way, I avoid remapping all of the interrupt sources and thus very little changes I've to make to the *.GLD file.

The PIC24EP I use, is equipped with two CAN bus controllers on my PCB (So NO on-board CAN). From one of this external CAN controllers, the bootloader must be able to communicate and receive new firmware if available. The CAN bus controller is of the type MCP2515.

About the micro controller

The FLASH area addressing starts from 0x0 to 0x015800 for the 128kb device. This means the total available pages on this device is 42 (1024*3*42=129024 bytes). Please note that these 24EP devices have 0x400 instructions in a single page, not 0x200 like the 24FJ series. This means 3072 bytes or 3kb for a single page for the PIC24EP series.

I will reserve 2 pages for the bootloader. So I will use the following layout;
  • Page 0 to 39 dedicated for user application
  • Page 40 and 41 dedicated for bootloader
  • Page 42 dedicated for configuration fuses
By dedicating the configuration fuses, it will still be possible for the bootloader to change the configuration fuses if needed. e.g. if you want to be able to change the code protection with the bootloader. Please note this is a choice of me, not a requirement of microchip. This choice will come at a price that you will waste 1 entire page since it cannot be used by the bootloader nor user application.

Scratchpad below

Using code:
            nvmAdru = __builtin_tblpage(&myRowData1InFlash[0]);
            nvmAdr = __builtin_tbloffset(&myRowData1InFlash[0]);
            nvmAdrPageAligned = nvmAdr & 0xF800; // Get the Flash Page Aligned address

Declared:

uint16_t myRowData1InFlash[] __attribute__((space(prog), address(0xFC00))) ;

Result

  • nvmAdru = 0x100
  • nvmAdr = 0xFC00
  • nvmAdrPageAligned = 0xF800

Declared

uint16_t myRowData1InFlash[] __attribute__((space(prog), address(0x10400)));

Result
  • nvmAdru = 0x101
  • nvmAdr = 0x400
  • nvmAdrPageAligned = 0x0
Declared

uint16_t myRowData1InFlash[] __attribute__((space(prog), address(0x11200))) ;

Result
  • nvmAdru = 0x101
  • nvmAdr = 0x1200
  • nvmAdrPageAligned = 0x1000
Declared

uint16_t myRowData1InFlash[] __attribute__((space(prog), address(0x200))) = {

  • nvmAdru = 0x100
  • nvmAdr = 0x200
  • nvmAdrPageAligned = 0x0

The microchip PIC24EP simulator, when erasing a page, it only erases 0x100 addresses. In real world test, this is wrong, the same code will erase 0x800 addresses.





























Thursday, August 21, 2014

Comparing DACs

Just some scratch paper comparing DAC converters currently on the market. I`m looking for a +-1% output accuracy without need to calibrate each device if possible. Resolution starting from 12bit is required. SPI or I2C has no preference. Price must be lower than 5 euro per part at 10pc quatities.

MCP4725 - 12 bit resolution *4095 steps* - Costs 0.79euro each @10pc
Powering from 3.0 volts ==> Each LSB equals 3v/12bit = 0.73mV

INL Error +-14.5 LSB MAX ==> 29.00 LSB per part variation MAX ==> 29LSB equ 24.25mV
DNL Error  +-0.75 LSB MAX ==> 1.50 LSB per part variation MAX ==> 1.50LSB equ 1.01mV
Offset error 0.75% of FSR ==> FSR = 3.0Volts, 0.75% from 3 volts = 22.5mV
Gain Error +-2% MAX of FSR ==> FSR = 3.0Volts, 4% from 3 volts = 120mV

Absolute output error 5.7% maximum or -2.4% to 3.3%. 
Please note: I assumes those error terms are additive -> aka worst case scenario. In reality, they may offset each other, at least partially.(thanks for the note @dannyf)

Note: Datasheet makes exception that specs are only valid from decimal value 100 to 4000, beyond that, there is no way telling what the accuracy is. Otherwise, don't use this DAC if you use it below 100 or above 4000 unless you don't care about unspecified accuracy.

AD5620b (b-grade) - 12 bit resolution - Costs 4.21euro each @10pc
Powering from 3.0 volts ==> Each LSB equals 3v/12bit = 0.73mV

Relative accuracy: +-1 (is this INL??)  ==> +-0.73mV ==> 1.46mV per part variation
DNL: +-0.25 ==> +-0.18mV ==> 0.36mV per part variation
Offset error: +-9mV==> 18mV per part variation possible.
FullScale error: +-0.85% FSR Max ==> +-25,5 mV ==> 51mV per part variation possible
Gain error: +-0.85% FSR max ==> +-25.5mV ==> 51mV per part variation possible
Zero-code error: 8mV ==> This parameter is useful to know that you do not select this part if you need to go below 8mV, because there is a change the output won't make it below 8mV.

0.73mV INL + 0.18mV DNL + 9mV OffSet + 25.5mV FullScale error = +-35,41mV
For 3000mV reference 35.41mV is +-1,18%
Absolute output error 2,36% maximum

MAX5705BAUB - 12bit resolution - Costs 1.11 euro each @10pc
Powering from 3.0 volts ==> Each LSB equals 3v/12bit = 0.73mV

INL : +- 0.25 ==> +-0.18mV ==> 0.36mV per part variation
DNL: +-1.00 ==> 1.46mV per part variation
Offset error: +-5mV ==> 10mV per part variation
Gain error: +-1.0% of full scale ==> 60mV per part variation
Zero scale error: 0 to +10mV
Full scale error: +-0.5% of FS ==> 30mV per part variation ==> why can this be less than gain error? Wasn't it gain error + gain error = full scale error?
Bonus/Pro: this one also includes internal precision reference.

0.18mV INL + 0.73mV DNL + 5mV offset + 60mV gain = +-65,91mV
For 3000mV reference 65,91mV is +-2,19%
Absolute output error 4.4% maximum

AD5641BKSZ - 14 bit resolution *16383 steps* - Costs 4.00 euro each @10pc
Powering from 3.0 volts ==> Each LSB equals 3v/14bit = 0,183mV

INL: +-4 LSB ==> +-0,732mV
DNL +-1 LSB ==> +-0.183mV
Offset error : +-10mV
Gain error: +-0.037% of FSR ==> +-11.1mV

0,732mV INL + 0.183mV DNL + 10mV Offset + 11.1mV gain = +-22,015mV
For 3000mV reference 22,015mV is +-0,734%
Absolute output error 1,47% maximum

AD7849A - 14 bit resolution *16383 steps* - costs 16.50 euro each @10pc
Powering from 3.0 volts ==> Each LSB equals 3v/14bit = 0,183mV

INL: +-5 LSB Max ==> +-0,915mV
DNL: +- 0.25LSB Max ==> +-0,04575mV
Gain Error: +-4LSB Max==> +-0,732mV
Offset error: +-6 LSB Max.==> +-1,098mV

0.915mV INL + 0.04575mV DNL + 0.732mV Gain + 1.098mV offset = 2,79075mV
For 3000mV reference 2,79075mV is +-0,093025%
Absolute output error 0,18605% maximum -WOW!-

AD5621b - 12 bit resolution - costs 1.94 euro each @10pc
Powering from 3.0 volts ==> Each LSB equals 3v/12bit = 0.73mV

INL (finally, this datasheet actiually calls it INL instead of only Relative Accuracy)
INL: +1 LSB max ==> +-0.73mV
DNL: +- 0.5 LSB max ==>+-0,365mV
Offset error: +- 10mV
Gain error: +-0.037% of FSR ==> +-11.1mV

0.73mV INL + 0.365 DNL + 10mV offset + 11.1mV Gain = 22,195mV
For 3000mV reference 22,195mV is +-0,74%
Absolute output error 1,48% maximum
Note: This one is a look alike of the AD5641 above, almost identical accuracy.

Please note that a gain and offset error are more easily calibrated by doing a 2 point measurement. INL error is more difficult to calibrate since it acts non-linear over the entire output so you will have to do multiple point measurement and try to extrapolate from each calibration to cover the INL error.