Coldfire firmware update

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Coldfire firmware update

968 Views
oakie_doke
Contributor III

Hi,

I'm working with CodeWarrior 10.6 and mcf51mm256 mcu. I want to make update firmware functionality (program flash memory from .s19 file transmitted on i2c).  I have problem with upgrade mechanism and configuring .lcf file. Where I have to place new firmware? I think I can't place it in the place of old firmware while program is running. I can place new firmware next to old but how to set mcu to start with new firmware?

 

What do you suggest me to do?

 

Thanks

Labels (1)
0 Kudos
5 Replies

653 Views
TomE
Specialist II

Generally you can't access FLASH while erasing or programming it.

If you have a "big" design with lots of FLASH and RAM, then the usual thing to do is to treat the Flash as a filesystem/disk, and run all code from RAM.

So you copy the new code to RAM and program to FLASH from there.

Otherwise, if you're running code directly from FLASH, you run whatever comms protocol you have to load all the code to RAM, then to program it you copy a small programming-kernel to RAM that then goes and does the erasing and programming.

The MCF51MM256 has 32k of RAM and 256k of FLASH, so you can't do that.

But you're lucky:

4.3.1 Features
Features of the flash memory include:
* The MCF51MM256 series incorporate dual flash controllers, allowing the microcontroller to
execute code from one flash array while programming the other.

It also has "256 sectors if 1024 bytes each". You can erase individual sectors.

Now if you can fir all of your code into half of that (into 128k) then you can have the "old" and "new" versions of the code both there at the same time.

So I'd suggest you reserve the first sector in the first controller as being the "initial bootstrap", and burn a copy of it into the first sector of the second controller (if you're using fixed vectors and not using vectors in RAM).

Have that code check to see which "half" is the newer one (have a word at a fixed location that contains a version number you increment for each new version) and then have that startup code program the "ARRAYSEL bit in the SOPT3" as documented in "4.3.2 Dual Flash Controllers". You should also have each half checksummed, so the startup code will run the newest version that has a good checksum. That lets you recover from upgrades that fail half way through.

The tricky bit is having the code know which half it is in and which controller to use. The controllers don't "swap" addresses, but the flash they manage does.

That locks your code into this chip as it will depend on the chip it runs on having two controllers. The alternative is to write a "general purpose" one which copies a small program into RAM that receives the new firmware and erases FLASH and burns it in. You have the risk of "bricking" the device if this fails half way through as there's no way back. Using the two controllers does give you a way back.

Tom

653 Views
oakie_doke
Contributor III

Thank you for help. So, I would like to update firmware using flash swapping as you described.

Size of my code is ~10kB and code is running directly from flash.

I have few questions:

"So I'd suggest you reserve the first sector in the first controller as being the "initial bootstrap", and burn a copy of it into the first sector of the second controller (if you're using fixed vectors and not using vectors in RAM)."

I don't understand why I should reserve first sector in the first controller and copy it to first sector in the second controller. Why don't write all data of .s19 file in second flash memory? In .s19 file there are also adresses from first sector. And when writing is completed then change bit ARRAYSEL to swap flash. When upgrade fail then do not change ARRAYSEL and old firmware starts as usualy.

Reference manual tells that function which changes ARRAYSELL must be located in RAM. After finish this function program jump to main application in flash but new (because swapped flash)?

After swap new code will be physicaly in second flash, but adress will be show first flash?

PS. Sorry for my english.

0 Kudos

653 Views
TomE
Specialist II

> I don't understand why I should reserve first sector in the first controller

When the CPU starts up it will always execute code starting at the Reset vector in the first page of the first half of the Flash.

That code will have to decide whether the code in that half is both VALID (by checking a checksum) and is also the NEWEST version, or whether that applies to the other half. So it has to decide to run the code in the first half, or to swap and then run the code in the second half.

When you are running in the first half and upgrading the second half, it doesn't matter what you do to the second half. You can erase 100% of it.

When you are running in the SECOND half and upgrading the first half, you don't want to erase the code in the first block. That is a "bootstrap" which you should only load during "production" and should never update "in the field".

That means you build two programs. You build the "boot" which you burn into the first few sectors and the "Application" which you burn higher and can upgrade.

It is possible, but risky to just have "one program". If you're running in the SECOND half and the upgrade of the FIRST half fails (and doesn't erase properly or write the code) then the device is "bricked" and can't recover.

Are you running with interrupts? Do you have the interrupt vectors in FLASH or do you copy them to(or construct them in) RAM? If you do that then you don't need a copoy of the "Boot" in both halves. If you're running vectors in FLASH then you need copies in both halves.

Tom

653 Views
oakie_doke
Contributor III

I think I understand now, I will try do it as you described.

Are you running with interrupts? Do you have the interrupt vectors in FLASH or do you copy them to(or construct them in) RAM?

I'm running with interrupts in flash. InterruptVectorTable is in the first sector.

Now I have problem with copy function which changes ARRAYSEL to RAM. I'm working with AN4329 application note. I wrote code from application note by myself, not copy/paste because I heard that it might couse problems. I changed optimization (speed) and code model (Far 32bit) in Properties of project.

After done point 5.2 from application note everything is ok and I can see .my_ram section and my funcInRAM() in .xMAP file.

Problem starts when I add copyToMyRAM() function. After compilation there are few problems:

Illegal 16-bit small data area relative reference to symbol '___CodeSize' from address 0x00001602 in section '.text' of file 'main_c.obj '. This type of reference has a range from 4294934528 to 32767 bytes.

Illegal 16-bit small data area relative reference to symbol '___CodeStart' from address 0x000015F2 in section '.text' of file 'main_c.obj '. This type of reference has a range from 4294934528 to 32767 bytes.

Link failed.

mingw32-make: *** [bowlcw10tst.elf] Error 1

There are my .lcf, .xMAP, source code:

# Memory ranges

MEMORY {

   code        (RX)  : ORIGIN = 0x00000414, LENGTH = 0x0001FFE8

   code_00020410 (RX) : ORIGIN = 0x00020410, LENGTH = 0x0001FBF0

   userram     (RWX) : ORIGIN = 0x00800000, LENGTH = 0x00007000

   myram        (RWX) : ORIGIN = 0x00807000, LENGTH = 0x00001000

}

SECTIONS {

# Heap and Stack sizes definition

  ___heap_size     = 0x0400;

  ___stack_size    = 0x0400;

# MCF51MM256 Derivative Memory map definitions from linker command files:

# ___RAM_ADDRESS, ___RAM_SIZE, ___FLASH_ADDRESS, ___FLASH_SIZE linker

# symbols must be defined in the linker command file.

# 32 Kbytes Internal SRAM

   ___RAM_ADDRESS = 0x00800000;

   ___RAM_SIZE    = 0x00008000;

# 256 KByte Internal Flash Memory

   ___FLASH_ADDRESS  = 0x00000000;

   ___FLASH_SIZE     = 0x00040000;

  .userram        : {} > userram

  .code      : {} > code

  .code1     : {} > code_00020410

  .text :

  {

    *(.text)

    . = ALIGN (0x4);

    *(.rodata)

    . = ALIGN (0x4);

    ___ROM_AT = .;

    ___DATA_ROM = .;

  } >> code

  .data : AT(___ROM_AT)

  {

    ___DATA_RAM = .;

    . = ALIGN(0x4);

    *(.exception)

    . = ALIGN(0x4);

    __exception_table_start__ = .;

    EXCEPTION

    __exception_table_end__ = .;

    ___sinit__ = .;

      STATICINIT

    __START_DATA = .;

    *(.data)

    . = ALIGN (0x4);

    __END_DATA = .;

    __START_SDATA = .;

    *(.sdata)

    . = ALIGN (0x4);

    __END_SDATA = .;

    ___DATA_END = .;

    __SDA_BASE = .;

    . = ALIGN (0x4);

  } >> userram

___CodeStart = ___ROM_AT + SIZEOF(.data);

.my_ram : AT(___CodeStart)

{

    . = ALIGN (0x4);

    ___myRAMStart = .;

    *(.myCodeInRAM)

    ___myRAMEnd = .;

    . = ALIGN (0x4);

} > myram

___CodeSize = ___myRAMEnd - ___myRAMStart;

  .bss :

  {

    ___BSS_START = .;

    __START_SBSS = .;

    *(.sbss)

    . = ALIGN (0x4);

    *(SCOMMON)

    __END_SBSS = .;

    __START_BSS = .;

    *(.bss)

    . = ALIGN (0x4);

    *(COMMON)

    __END_BSS = .;

    ___BSS_END = .;

    . = ALIGN(0x4);

  } >> userram

  .custom :

  {

    ___HEAP_START       = .;

    ___heap_addr        = ___HEAP_START;

    ___HEAP_END         = ___HEAP_START + ___heap_size;

    ___SP_END             = ___HEAP_END;

    ___SP_INIT          = ___SP_END + ___stack_size;

    ___mem_limit        = ___HEAP_END;

    ___stack_safety     = 16;

    . = ALIGN (0x4);

  } >> userram

  __SP_INIT             = ___SP_INIT;

  ___SP_AFTER_RESET     = __SP_INIT;

  _romp_at = ___ROM_AT + SIZEOF(.data) + SIZEOF(.my_ram);

  .romp : AT(_romp_at)

  {

    __S_romp = _romp_at;

    WRITEW(___ROM_AT);

    WRITEW(ADDR(.data));

    WRITEW(SIZEOF(.data));

    WRITEW(0);

    WRITEW(0);

    WRITEW(0);

  }

}

/*********************/

extern unsigned long __CodeStart[];

#define CodeStart    (unsigned long)__CodeStart;

extern unsigned long __CodeSize[];

#define CodeSize    (unsigned long)__CodeSize;

extern unsigned long __myRAMStart[];

#define StartAddr    (unsigned long)__myRAMStart;

/*********************/

uint8_t *Source;

uint8_t *Destiny;

uint32_t MemorySize;

/*********************/

void copyToMyRAM();

void copyToMyRAM(){

      Source = (unsigned char*)CodeStart;

    Destiny = (unsigned char*)StartAddr;

    MemorySize = (unsigned long)CodeSize;

    while(MemorySize--){

        *Destiny++ = *Source++;

    }

}

#pragma define_section mySectionInRAM ".myCodeInRAM" far_absolute RX

#pragma section mySectionInRAM begin

void funcInRAM();

void funcInRAM(){

   

}

#pragma section mySectionInRAM end

In function main() at the begining I call copyToMyRam() function and next funcInRAM() few times.

Do you have any idea what may couse this error?

0 Kudos

653 Views
TomE
Specialist II

> I'm running with interrupts in flash. InterruptVectorTable is in the first sector.

So you'll need to ensure there's a valid table in both halves of the FLASH with the vectors matching the entry points in the code.

You only have 10k of code so your download program can load it ALL into RAM and check it before committing to program. It is more complicated if you have to erase the FLASH and then download a block, program a block, repeat. That can go wrong if it fails part way though. It also means you can probably safely replace everything in the "other half" of the FLASH.

> Do you have any idea what may couse this error?

Sorry can't help. This is a CodeWarrior question, and would be best posted in the forums specific to that.

You should always SEARCH for error messages before asking questions. Searching for 'Illegal 16-bit small data area relative reference to symbol" finds this in the CodeWarrior forum and hundreds of other matches:

https://community.freescale.com/message/304984#304984

Back to what you're doing.

I searched Freescale for "AN4239" and found this one, which looks to be better suited to what you are doing:

Avoiding Read While Write Errors When Developing In-Software Flash Programming Applications for
Kinetis and ColdFire+ MCUs, Rev. 0, 04/2013

http://cache.freescale.com/files/32bit/doc/app_note/AN4695.pdf

Tom

0 Kudos