Serial Bootloader for the Freedom Board with Processor Expert

Bootloaders are a very useful thing: it allows programming an application file without a debugger. This makes it ideal for upgrading a system in the field.

Usually, there are application notes and examples from silicon vendors available. But typically they are for a certain microcontroller, and hard to change it to another system without a lot knowledge about its implementation. What I need for a project based on the FRDM-KL25Z is a bootloader which shall be small and portable. As I’m using Processor Expert to keep my applications portable across different microcontroller families: why not create a bootloader with Processor Expert components?  With the Processor Expert drivers available, things can get a lot simpler compared to the ‘traditional’ approach. With less than 10 KByte footprint?

Serial Bootloader made with Processor Expert

Serial Bootloader made with Processor Expert

A bootloader is a program which is able to load another program (the application program). Typically the bootloader program is not changed, and is kept in the microcontroller. That way the bootloader can load again and again a different program.

Bootloader and Application Memory Map

Bootloader and Application Memory Map

💡 Architecturally there can be a ‘mini’ or ‘micro’ bootloader which can load the ‘real’ bootloader. E.g. the OpenSDA bootloader on the Freedom boards have this capability.

The Bootloader Code and the Bootloader Vectors are programmed into a new part (e.g. with a debugger or a standalone flash programmer (e.g. with USBDM). Then the Bootloader can be used to load or change the Application Code and Application Vectors. With this, the Bootloader remains the same, while the Application can be updated.

Bootloader Sequence

A typical bootloader is doing something like this

  1. The bootloader decides at startup if it should enter bootloader mode or if it shall run the application. Typically this is decided with a button or jumper set (or removed). If it shall run the application, the bootloader calls the application and we are done :-).
  2. Otherwise, the bootloader will reprogram the application with a new file. S19 (S-Record) files are often used for this, as they are easy to parse and every tool chain can produce them.
  3. The bootloader needs to use a communication channel to read that file. That can be RS-232, USB or an SD card file system (e.g. FatFS).
  4. Using that file, the bootloader programs the flash memory. Special consideration has to be taken into account for the application vector table. As the bootloader runs out of reset, it is using its own (default) vector table, and needs to relocate the vector table if running the application.

💡 It would be possible to use the reset button on the FRDM-KL25Z board as a user button (see this post). To keep things simple, I’m using a dedicated bootloader push button on PTB8.

So writing a bootloader requires the following parts:

Bootloader System Block Diagram

Bootloader System Block Diagram

  • Communication Channel: File I/O or any other means to read the Application File.
  • File Reader: A reader which reads the Application File.
  • Flash Programming: to program the Application.
  • Vector Redirection: To switch between the Bootloader and Application Vector Table.
  • User Interface: Showing status and information to the user, and to switch between application and bootloader mode at system startup.

Processor Expert comes with Flash Programming and Communication components (USB, SCI, I2C, …) installed. I have a Shell user interface already, plus an S19 file reader component created. Combining this with my other components should enable me to make a bootloader :-).

Flash Memory of the Bootloader

To make sure the bootloader gets linked only into its space, I reduce the FLASH memory for it. With the settings below I limit the FLASH memory from 0x0000 (vector table) up to 0x3FFF. That means my application memory area starts at 0x4000.

So I change the available flash for the bootloader in the CPU properties, and cut the available FLASH size on the KL25Z128 from 0x1FBF0 (~128 KByte) in the Build Options tab to 0x3FB0:

Bootloader FLASH Area

Bootloader FLASH Area

With this, the bootloader occupies the space from address 0x0000 (vector table) up to 0x3FFF.

Flash Protection

My bootloader resides in the first lower flash pages. To avoid that it might get destroyed and overwritten by the application, I protect the bootloader flash blocks. There is a setting in the CPU component properties where I can protect 4 KByte regions:

Protecting Regions in the CPU Component

Protecting Regions in the CPU Component

Terminal Program

For my bootloader I need a way to send a file with a terminal program. As my serial connection has only Tx and Rx, but no RTS/CTC lines for flow control, it is useful if the terminal program either implements software flow control (XON/XOFF), or a delay value for sending a file.

After some searching the internet, I have found an open source terminal program which exactly can do this: https://sites.google.com/site/terminalbpp/

Terminal Program

Terminal Program

It supports sending a file with a delay (shown above with 1 ms delay), and supports XON and XOFF. I used it successfully with my bootloader.

💡 Using a zero delay did not work in all cases. Not yet sure why. What worked was sending a file with a 1 ms delay setting.

Bootloader Shell

The bootloader features a shell with following commands:

--------------------------------------------------------------
FRDM Shell Bootloader
--------------------------------------------------------------
CLS1                      ; Group of CLS1 commands
  help|status             ; Print help or status information
BL                        ; Group of Bootloader commands
  help|status             ; Print help or status information
  erase                   ; Erase application flash blocks
  restart                 ; Restart application with jump to reset vector
  load s19                ; Load S19 file

The ‘BL status’ command shows the application flash range, and the content of the application vector table (more about this later):

  App Flash  : 0x00004000..0x0001FFFF
  @0x00004000: 0xFFFFFFFF 0xFFFFFFFF

With ‘BL restart’ it starts the user application (if any), and with ‘BL erase’ the application flash can be erased:

CMD> Erasing application flash blocks...done!

Bootloading an Application

With ‘BL load s19’ a new application file can be loaded. It will first erase the application flash blocks, and then waits for the S19. To send the file, I use the ‘Send File’ button:

Loading S19 File

Loading S19 File

It writes then the address of each S19 line programmed to the shell console:

CMD> Erasing application flash blocks...done!
Waiting for the S19 file...
S0 address 0x00000000
S1 address 0x00008000
S1 address 0x00008010
...
S1 address 0x00009420
S1 address 0x00009430
S1 address 0x00009440
S9 address 0x00009025
done!
CMD>

Bootloader Details

If I enter ‘BL Load S19’, it executes the function BL_LoadS19() in Bootloader.c:

static uint8_t BL_LoadS19(CLS1_ConstStdIOType *io) {
  unsigned char buf[16];
  uint8_t res = ERR_OK;

  /* first, erase flash */
  if (BL_EraseAppFlash(io)!=ERR_OK) {
    return ERR_FAILED;
  }

  /* load S19 file */
  CLS1_SendStr((unsigned char*)"Waiting for the S19 file...", io->stdOut);
  parserInfo.GetCharIterator = GetChar;
  parserInfo.voidP = (void*)io;
  parserInfo.S19Flash = BL_onS19Flash;
  parserInfo.status = S19_FILE_STATUS_NOT_STARTED;
  parserInfo.currType = 0;
  parserInfo.currAddress = 0;
  parserInfo.codeSize = 0;
  parserInfo.codeBuf = codeBuf;
  parserInfo.codeBufSize = sizeof(codeBuf);
  while (AS1_GetCharsInRxBuf()>0) { /* clear any pending characters in rx buffer */
    AS1_ClearRxBuf();
    WAIT1_Waitms(100);
  }
  do {
    if (S19_ParseLine(&parserInfo)!=ERR_OK) {
      CLS1_SendStr((unsigned char*)"ERROR!\r\nFailed at address 0x", io->stdErr);
      buf[0] = '\0';
      UTIL1_strcatNum32Hex(buf, sizeof(buf), parserInfo.currAddress);
      CLS1_SendStr(buf, io->stdErr);
      CLS1_SendStr((unsigned char*)"\r\n", io->stdErr);
      res = ERR_FAILED;
      break;
    } else {
      CLS1_SendStr((unsigned char*)"\r\nS", io->stdOut);
      buf[0] = parserInfo.currType;
      buf[1] = '\0';
      CLS1_SendStr(buf, io->stdOut);
      CLS1_SendStr((unsigned char*)" address 0x", io->stdOut);
      buf[0] = '\0';
      UTIL1_strcatNum32Hex(buf, sizeof(buf), parserInfo.currAddress);
      CLS1_SendStr(buf, io->stdOut);
    }
    if (parserInfo.currType=='7' || parserInfo.currType=='8' || parserInfo.currType=='9') {
      /* end of records */
      break;
    }
  } while (1);
  if (res==ERR_OK) {
    CLS1_SendStr((unsigned char*)"\r\ndone!\r\n", io->stdOut);
  } else {
    while (AS1_GetCharsInRxBuf()>0) {/* clear buffer */
      AS1_ClearRxBuf();
      WAIT1_Waitms(100);
    }
    CLS1_SendStr((unsigned char*)"\r\nfailed!\r\n", io->stdOut);
    /* erase flash again to be sure we do not have illegal application image */
    if (BL_EraseAppFlash(io)!=ERR_OK) {
      res = ERR_FAILED;
    }
  }
  return res;
}

It first fills a callback structure of type S19_ParserStruct:

typedef struct S19_ParserStruct {
  uint8_t (*GetCharIterator)(uint8_t*, void*); /* character stream iterator */
  void *voidP; /* void pointer passed to iterator function */
  uint8_t (*S19Flash)(struct S19_ParserStruct*); /* called for each S19 line to be flashed */
  /* the following fields will be used by the iterator */
  S19_FileStatus status; /* current status of the parser */
  uint8_t currType; /* current S19 record, e.g. 1 for S1 */
  uint32_t currAddress; /* current code address of S19 record */
  uint16_t codeSize; /* size of code in bytes in code buffer */
  uint8_t *codeBuf; /* code bufffer */
  uint16_t codeBufSize; /* total size of code buffer, in bytes */
} S19_ParserStruct;

That structure contains a callbacks to read from the input stream:

static uint8_t GetChar(uint8_t *data, void *q) {
  CLS1_ConstStdIOType *io;

  io = (CLS1_ConstStdIOType*)q;
  if (!io->keyPressed()) {
#if USE_XON_XOFF
    SendXONOFF(io, XON);
#endif
    while(!io->keyPressed()) {
      /* wait until there is something in the input buffer */
    }
#if USE_XON_XOFF
    SendXONOFF(io, XOFF);
#endif
  }
  io->stdIn(data); /* read character */
  if (*data=='\0') { /* end of input? */
    return ERR_RXEMPTY;
  }
  return ERR_OK;
}

Parsing of the S19 file is done in S19_ParesLine() which is implemented in a Processor Expert component which I already used for another bootloader project:

S19 Parser

S19 Parser

This parser is calling my callback BL_onS19Flash() for every S19 line:

static uint8_t BL_onS19Flash(S19_ParserStruct *info) {
  uint8_t res = ERR_OK;

  switch (info->currType) {
    case '1':
    case '2':
    case '3':
      if (!BL_ValidAppAddress(info->currAddress)) {
        info->status = S19_FILE_INVALID_ADDRESS;
        res = ERR_FAILED;
      } else {
        /* Write buffered data to Flash */
        if (BL_Flash_Prog(info->currAddress, info->codeBuf, info->codeSize) != ERR_OK) {
          info->status = S19_FILE_FLASH_FAILED;
          res = ERR_FAILED;
        }
      }
      break;
    case '7':
    case '8':
    case '9': /* S7, S8 or S9 mark the end of the block/s-record file */
      break;
    case '0':
    case '4':
    case '5':
    case '6':
    default:
      break;
  } /* switch */
  return res;
}

Of interest are the S1, S2 and S3 records as they contain the code. With BL_ValidAppAddress() it checks if the address is within the application FLASH memory range:

/*!
* \brief Determines if the address is a valid address for the application (outside the bootloader)
* \param addr Address to check
* \return TRUE if an application memory address, FALSE otherwise
*/
static bool BL_ValidAppAddress(dword addr) {
return ((addr>=MIN_APP_FLASH_ADDRESS) && (addr<=MAX_APP_FLASH_ADDRESS)); /* must be in application space */
}

If things are ok, it flashes the memory block:

/*!
* \brief Performs flash programming
* \param flash_addr Destination address for programming.
* \param data_addr Pointer to data.
* \param nofDataBytes Number of data bytes.
* \return ERR_OK if everything was ok, ERR_FAILED otherwise.
*/
static byte BL_Flash_Prog(dword flash_addr, uint8_t *data_addr, uint16_t nofDataBytes) {
  /* only flash into application space. Everything else will be ignored */
  if(BL_ValidAppAddress(flash_addr)) {
    if (IFsh1_SetBlockFlash((IFsh1_TDataAddress)data_addr, flash_addr, nofDataBytes) != ERR_OK) {
      return ERR_FAILED; /* flash programming failed */
    }
  }
  return ERR_OK;
}

The Flash Programming itself is performed by the IntFLASH Processor Expert components:

Processor Expert Flash Programming Component

Processor Expert Flash Programming Component

This component is used for erasing too:

/*!
 * \brief Erases all unprotected pages of flash
 * \return ERR_OK if everything is ok; ERR_FAILED otherwise
 */
static byte BL_EraseApplicationFlash(void) {
  dword addr;

  /* erase application flash pages */
  for(addr=MIN_APP_FLASH_ADDRESS;addr<=MAX_APP_FLASH_ADDRESS;addr+=FLASH_PAGE_SIZE) {
    if(IFsh1_EraseSector(addr) != ERR_OK) { /* Error Erasing Flash */
      return ERR_FAILED;
    }
  }
  return ERR_OK;
}

Bootloader or Not, that’s the Question

One important piece is still missing: the bootloader needs to decide at startup if it shall run the Bootloader or the application. For this we need to have a decision criteria, which is typically a jumper or a push button to be pressed at power up to enter bootloader mode.

In this bootloader this is performed by BL_CheckForUserApp():

/*!
 * \brief This method is called during startup! It decides if we enter bootloader mode or if we run the application.
 */
void BL_CheckForUserApp(void) {
  uint32_t startup; /* assuming 32bit function pointers */

  startup = ((uint32_t*)APP_FLASH_VECTOR_START)[1]; /* this is the reset vector (__startup function) */
  if (startup!=-1 && !BL_CheckBootloaderMode()) { /* we do have a valid application vector? -1/0xfffffff would mean flash erased */
    ((void(*)(void))startup)(); /* Jump to application startup code */
  }
}

The function checks if the ‘startup’ function in the vector table (index 1) is valid or not. If the application flash has been erased, it will read -1 (or 0xffffffff). So if we have an application present and the user does not want to run the bootloader, we jump to the application startup.
Below is the code to decide if the user is pressing the button to enter the startup code:

static bool BL_CheckBootloaderMode(void) {
  /* let's check if the user presses the BTLD switch. Need to configure the pin first */
  /* PTB8 as input */
  /* clock all port pins */
  SIM_SCGC5   |= SIM_SCGC5_PORTA_MASK |
             SIM_SCGC5_PORTB_MASK |
             SIM_SCGC5_PORTC_MASK |
             SIM_SCGC5_PORTD_MASK |
             SIM_SCGC5_PORTE_MASK;
  /* Configure pin as input */
  (void)BitIoLdd3_Init(NULL); /* initialize the port pin */
  if (!BL_SW_GetVal()) { /* button pressed (has pull-up!) */
    WAIT1_Waitms(50); /* wait to debounce */
    if (!BL_SW_GetVal()) { /* still pressed */
      return TRUE; /* go into bootloader mode */
    }
  }
  /* BTLD switch not pressed, and we have a valid user application vector */
  return FALSE; /* do not enter bootloader mode */
}

I’m using BitIOLdd3_Init() to initialize my port pin, which is part of the BitIO component for the push button:

BitIOLdd Component

BitIOLdd Component

💡 When creating a BitIO component for Kinetis, Processor Expert automatically creates a BitIO_LDD component for it. As I do not have control over the name of that BitIO_LDD, I need to use in my bootloader whatever Processor Expert has assigned as name.

I’m using PTB8 of the Freedom board, and have it connected to a break-out board (pull-up to 3.3V if button is not pressed, GND if button is pressed):

FRDM-KL25Z with Bootloader Switch Board

FRDM-KL25Z with Bootloader Switch Board

You might wonder why I have to initialize it, as this is usually done automatically by PE_low_level_init() in main()? The reasons is: I need to do this *before* main() gets called, very early in the startup() code. And that’s the reason as well why I need to set the SIM_SCGC5 register on Kinetis to clock the peripheral.

Inside the CPU component properties, there is a Build option setting where I can add my own code to be inserted as part of the system startup:

User Code before PE initialization

User Code before PE initialization

To make sure it has the proper declaration, I add the header file too:

User data declarations

User data declarations

These code snippets get added to the __init_hardware() function which is called from the bootloader startup code:

Custom startup code with Bootloader code inserted

Custom startup code with Bootloader code inserted

This completes the Bootloader itself. Next topic: what to do in the application to be loaded…

Application Memory Map

As shown above: the bootloader is sitting in a part of the memory which is not available by the application. So I need to make sure that application does not overlap with the FLASH area of the bootloader. My bootloader starts at address 0x0000 and ends at 0x3FFF:

Bootloader Memory Map

Bootloader Memory Map

While the application can be above 0x4000. These numbers are used in Bootloader.c:

/* application flash area */
#define MIN_APP_FLASH_ADDRESS        0x4000  /* start of application flash area */
#define MAX_APP_FLASH_ADDRESS       0x1FFFF  /* end of application flash */

#define APP_FLASH_VECTOR_START      0x4000  /* application vector table in flash */
#define APP_FLASH_VECTOR_SIZE       0xc0    /* size of vector table */

The application just needs to stay outside the FLASH used by the bootloader:

Application Memory Map

Application Memory Map

To make this happen, I need to change the addresses for m_interrupts and m_text in the CPU build options:

Application Memory Area Settings

Application Memory Area Settings

That’s it 🙂

💡 As for the ARM Cortex-M4/0+ do not need to copy the vector table in the bootloader to a different location, I can debug the application easily without the bootloader.

S-Record (S19) Application File Generation

The bootloader loads S19 or S-Records. This post explains how to create S19 files for Kinetis and GNU gcc.

Code Size

The bootloader is compiled with gcc for the FRDM-KL25Z board. Without optimization (-O0), it needs 13 KByte of FLASH. But optimized for size, it needs only 8 KByte 🙂 :

text       data        bss        dec        hex    filename
8024         24       2396      10444       28cc    FRDM_Bootloader.elf

Summary

With this, I have a simple serial bootloader for only 8 KByte of code. The bootloader project and sources are are available on GitHub here.

And I have several ideas for extensions:

  • Using a memory stick to load the appliation file (USB MSD Host).
  • Using a SD-Card interface with FatFS.
  • Using a USB MSD device to load the file.
  • Performing vector auto-relocation: the bootloader should detect the vector table at address 0x00 of the application file and automatically relocate it to another location in FLASH. That way I can debug the Application without change of the vector table.
  • Making sure it runs on other boards and microcontroller families.
  • Creating a special component for the bootloader.

While the bootloader only needs 8 KByte for now, I keep the reserved range at 16 KByte, just to have room for future extensions.

Happy Bootloading 🙂

Advertisements

469 thoughts on “Serial Bootloader for the Freedom Board with Processor Expert

  1. Hi Erich,

    Where Can I find the complete source code of this project? The above link has only few files.

    Thanks and Regards,
    Naruto

    Like

    • Hi Naruto,
      all the needed files are on GitHub. The thing is that all the other files are generated by Processor Expert, and it does not make sense to put generated files on GitHub. Simply load the project with Eclipse/Processor Expert, and you will have all the sources.

      Like

  2. Hello Erich,
    I am a complete newbie in ARM MCUs ,I am on a project of making my custom MK22DX256VLF5 board.After some researching I was able to flash a blink code to my board using the SWD debug port of the OpenSDA hardware of my FRDM kl25z(Of course I have removed the J11 trace ). I have flashed the CMSIS-DAP.s19 bootloader to debug and flash my board using Keil IDE.This too wasnt easy either for me as there was no ready made examples for MK22DX256xxx5 so I had tried a few combinations and finally after modifying the example code of MK22FN512xxx12 and importing MK22DX256xxx5 libraries I was finally able to flash the blink code to my custom development board.Now I want to develop a bootloader for my board so that I can connect my Board directly through USB and can flash the code using Keil or Code warrior but I dont have that good understanding of ARM devices, in this post I thought you have mentioned a way to make a bootloader using Processor expert software but it is not so.I am also not familiar with the terms as,Shell,FreeRTOS,So kindly help me in this respect to meet my purpose to create a USB DFU bootloader of my own that has MSD Properties as well.

    My next purpose is to implement OpenSDAV2.1 on MK22DX256VLF5 to make it a general ARM debuuger for other boards,How to achieve that ?

    Along with Bootloader development I would finally like to combine my above two purposes and would make a custom dev board with a OpenSDAV2.1 circuitary(with MK22DX256VLF5 if possible) for flashing and debugging the target MCU on that board (MK22DX256VLF5).The things is I want to make make the board flexible so that it can be programmed directly (using its own DFU USB bootloader) and also I want to develop a S.19 file (a bootloader) that can be used on the ON-Board Opensda debugger’s MSD (primary) bootloader to flash and Debug the target MCU.If possible kindly provide me with enough references so that a newbie like me is able to make/develop a bootloader using Processor expert or KDS or CodeWarrior.

    Here are few of my posts that i have made to get help from others but was not successful till now

    https://community.freescale.com/thread/366615

    https://community.freescale.com/thread/379038

    https://community.freescale.com/thread/379120

    Thank you so much 🙂

    Best Regards,
    Shubham Paul

    Like

      • Hello erich.
        Thank you so much for replying. I now understand what I want but still I am stuck, my purpose can be met by Porting AN4379 USB MSD bootloader to my MCU but I am not able to do it (even with the pdf ). Sorry I sent you a direct mail because I didnt see your reply.Can you provide me a guide to port AN4379 to my MCU ?

        Like

      • Hello Erich,

        I have done all the procedure step by step, but i have one issue in this,

        I am using FRDM-KL25z board, now after load .S19 file in flash, some time after power on, the FRDM board goes in to the bootloader mode, or some time in the application mode. I am not getting what happened inside, why FRDM goes in the bootloader mode.

        is there any facility to put device in the bootloader mode from the application mode during application run? so that we can flash new application in it.

        I have another query, can we use this code for KL26 after some modification.

        Thanks.

        Like

      • If it goes into bootloader mode or not, depends on your bootloader decision inside the bootloader. If you are using a GPIO pin, make sure you are using the proper pull-down or pull-up resistor.
        And if you are debugging your application, you should see exactly why it is entering bootloader mode or not.
        And yes, you can go into bootloader mode from the application: See the way how to reset the target (see as well https://mcuoneclipse.com/2015/07/01/how-to-reset-an-arm-cortex-m-with-software/) and then use a mofified bootloader decision code.
        I have not used it with the KL26, but I don’t see why it should not work with it too.

        Like

      • Hi Erich,

        Thanks for your reply,

        I am debugging the application as you suggested, But now i am facing another issue like to share with you.

        I am using CW10.6 IDE, Now when i am using your any example code like.. Freedom_LED, the output Freedom_LED.hex file is ok . In this Freedom_LED project, the memory address is for flash code start from 0x4000 and ends at 1B000. so in this application, the application will be in flash from 0x4000 to 0x1b000, Now when i open this .hex file, its ok as per our requirement. In this hex file does’t have any address between 0x0000 to 0x4000. But My problem start now,
        When i create the same project using CW10.6 with all same settings with same components, the “frdm_led_kl25.hex” has one string which contain address 0x0400, so in this case bootloader gives error, as 0x0000 to 0x4000 is protected memories in bootloader code.

        Now the twist is now, When i copy your MKL25Z processor component from example project to my project, and compile the project, the frdm_led_kl25.hex file doesnt have 0x0400 address line.

        Can you explain what will be the issue …
        For your ref : Freedom_LED.hex file

        S012000046726565646F6D5F4C45442E68657884
        S113400000300020BD470000194500002145000094—> 2nd line
        S11340102145000021450000214500002145000004
        S113402021450000214500002145000021450000F4
        S113403021450000214500002145000021450000E4
        S113404021450000214500002145000021450000D4
        S113405021450000214500002145000021450000C4
        S113406021450000214500002145000021450000B4
        S113407021450000214500002145000021450000A4
        S11340802145000021450000214500002145000094
        S11340902145000021450000214500002145000084
        S11340A02145000021450000214500002145000074
        S11340B02145000021450000214500002145000064
        S1134410002934D00123002210B488422CD3012473
        S11344202407A14204D2814202D209011B01F8E708
        S1134430E400A14204D2814202D249005B00F8E7C1
        S1134440884201D3401A1A434C08A04202D3001BED
        S11344505C0822438C08A04202D3001B9C08224320
        S1134460CC08A04202D3001BDC082243002803D05E
        S11344701B0901D00909E3E7101C10BC7047002890
        S113448001D00020C04307B4024802A140180290A2
        S113449003BDC046190000000029F0D003B5FFF7A2
        S11344A0B9FF0EBC4243891A1847C0467047C0463C
        S11344B0C046C046C04670470020C046C046C046FD
        S11344C0C046C04601300928F7D9C0467047C046E7
        S11344D038B5051E1ED0FFF7EFFFD024013CA4B26F
        S11344E0013CA4B2FFF7E8FFFFF7E6FF002CF5D18B
        S11344F0013DADB2FFF7DCFFFFF7DAFFFFF7D8FFAE
        S1134500FFF7D6FFFFF7D4FFFFF7D2FFFFF7D0FF87
        S1134510002DE0D138BDC04608B500F087F908BDCC
        S1134520FFBE7047234B244A244910B5D150244C74
        S113453088235A010020C021224BA0508802224A1D
        S1134540E050A058B0214B010343A3501F4CA27864
        S1134550110704D5A07808210143CBB2A370184BEE
        S1134560184C00221A491A515C581A4820405850D5
        S11345701C681948204018605C5818482040802462
        S1134580640420435850164906230B704A70CC78B3
        S11345901F200440134BCC7080241C700A714A7194
        S11345A0102288790242FCD00D490C248B791C42DC
        S11345B0FCD110BD080D000000E000E00040000048
        S11345C000700440441000003810000000D0074080
        S11345D004100000FFFFFEFFFFFFF3FFFFFFFFFCDF
        S11345E00040064000500640224A38B5224813696C
        S11345F0E0210340C9000B431361204B1F255C7964
        S1134600AC435C711C790725AC431C711C4B7325AE
        S11346101C78AC4350252C431C705C786325AC4358
        S113462040252C435C709C781925AC439C70154B39
        S113463000241C70156D284001431165C120124AE5
        S113464084001359114900201940115100F022F837
        S11346500F4D286800F042F8002000F04FF8686819
        S113466000F070F8002000F07DF8A86800F09AF8D7
        S113467062B638BD00900440FFF8FFFE00F007402A
        S113468000D0074000E0074000E100E0FFFF00FF2A
        S113469000F0FF1F0B4B0C4A802110605869C902BF
        S11346A0014359611868094901401960084B0949D7
        S11346B0986C01408020400001439964064B101C13
        S11346C01A60704740F00F400CF0FF1FFFFFFBFF24
        S11346D000A00440FFF8FFFE00F0FF1F8022024B01
        S11346E0D00258607047C04640F00FF88022024B59
        S11346F0D002D8607047C04640F00FF80B4B0C4A0C
        S113470080211060586909030143596118680949F7
        S113471001401960084B0949D86C014080204000D1
        S11347200143D964064B101C5A60704740F00F4097
        S113473010F0FF1FFFFFF7FF00A00440FFF8FFFE8B
        S113474000F0FF1F8022024B100358607047C046E0
        S113475040F00FF88022024B1003D8607047C04627
        S113476040F00FF80A4B0B4A0221106058690843C5
        S11347705861186888431860074B08495868014015
        S11347808020400001435960054B101C9A6070471B
        S1134790C0F00F4014F0FF1F00C00440FFF8FFFEFC
        S11347A000F0FF1F014B02225A607047C0F00FF85F
        S11347B0014B0222DA607047C0F00FF800F02AFCC7
        S11347C0FFF7B0FE0848094A0021121A00F04CF81D
        S11347D000F0F8FB00F094FB00F02AFC04490020F0
        S11347E000F00AF800F024F800F0FF1F34F0FF1F77
        S11347F018F0FF1F00B5FEE710B5FFF7F5FE0A4CF1
        S11348006420FFF765FE2068FFF770FFC820FFF7FC
        S11348105FFE6068FFF79EFFC8204000FFF758FE68
        S1134820A068FFF7C5FFEBE700F0FF1F7047C04625
        S113483038B5051C00F0E0FB00F086FB084C23684B
        S1134840002B02D0984700202060064C21680029E4
        S113485002D0884700222260281CFFF7CBFF38BD16
        S11348601CF0FF1F20F0FF1F10B5041C00F0E4FA39
        S1134870201C10BDF0B589B001901F1C0EAB039134
        S1134880079202901A78081C01990FAC013800268F
        S1134890049225780670B14217D1119BB34214D10A
        S11348A0049B002B01D06F2D2FD0642D02D0692DD5
        S11348B000D0A8E0022F02D1039802389FE0012F14
        S11348C000D0A0E00398023894E0692D0ED004D8FB
        S11348D0582D16D0642D1CD108E0752D04D0782DE8
        S11348E00FD06F2D15D110E0002712E0019A002A95
        S11348F00FDA80242606B2420DD051420191029172
        S113490009E000273E1C102407E000273E1C082471
        S113491003E0002600E001260A240090002006900F
        S11349200298211CFFF7B8FD02980591211CFFF79E
        S11349306FFD059A0290092A01D8303205E0059AE4
        S11349403732782D01D1059A57320098069B029987
        S11349500138D2B2009002700133002901D00693CD
        S1134960DEE7011C082C0BD10498002808D0302A5B
        S113497006D00B1C013B302200931A70069B0233B5
        S1134980079802280FD1002E01D1002F02D01099D0
        S113499001391091109A1192102C04D10498002816
        S11349A001D0023A119203990098119A091A8918B0
        S11349B0164A914226DC0099CA181199121A8A42A1
        S11349C003DA013830220270F5E7102C0AD1049C76
        S11349D0002C07D0019B002B04D0421E302102384A
        S11349E015700170002E02D001382D2108E0012F2E
        S11349F002D101382B2103E0022F04D101382021F8
        S1134A00017000E0002009B0F0BDC046FD010000C7
        S1134A10F0B5B64C1E1CA5446B460A900B913E3370
        S1134A2020210020197008920590089A1578002D0D
        S1134A3000D1F9E10898252100F04AFA0C900028E9
        S1134A4011D1089800F053FA0599021C0818059032
        S1134A50002A00D1E8E10B9808990A9EB047002883
        S1134A6000D0E1E1CEE00C9F089C05993A1B8B181D
        S1134A700593002A0CD10C980C9A437801321D1E20
        S1134A80252D0CD000270121BC460D97069119E075
        S1134A900B9808990A9DA8470028ECD1B2E00C9A1B
        S1134AA00021023201240892079106943DE02B2B49
        S1134AB00BDC202B10D0232B00D0BAE001239C4622
        S1134AC0013213782B2BF2D1ABE12D2B00D1A5E1D0
        S1134AD0302B00D0ADE004E00D9D012DF0D002207C
        S1134AE0A0E1069C002CEBD002200690E8E7376892
        S1134AF00436FB43D80F937802321C1C683C002117
        S1134B00042C00D8C1E0DDB26E2B00D0C7E0013226
        S1134B1008926E2D00D149E100D900E1632D00D146
        S1134B2059E107D8252D00D0F3E010AC2570099683
        S1134B30012619E0642D00D0EEE0321D09923068A0
        S1134B40032900D0F6E00799664600960195029184
        S1134B50039790A9069A0D9BFFF78CFE041E00D1C3
        S1134B603FE1634F6F443E1A069800283CD020234F
        S1134B70022800D130236F463E373B7022782B2A1F
        S1134B8004D02D2A02D0371C202A0BD1371C302BFD
        S1134B9008D10B98211C01220A9B9847002831D088
        S1134BA00134771E069902290ED1612D01D0412DC1
        S1134BB00AD1012F26DD0B98211C02220A9DA84749
        S1134BC000281FD0023F0234351C079EB54209DA83
        S1134BD069460B983E3101220A9B9847002811D060
        S1134BE00135F2E73E1C00E0351C002E03D1069887
        S1134BF0002819D115E0211C0B98321C0A9CA047EF
        S1134C000028F4D10122554205950DE169463F3152
        S1134C1020240B9801220A9F0C70B8470028F1D079
        S1134C200135079FBD42F1DB059A53190593099E8F
        S1134C30FBE6171C2A2B00D0E1E0341D36680796EA
        S1134C40002E03DA73420025079306957B78013220
        S1134C50261C284F0798B84200DDC2E02E2B11D144
        S1134C6053782A2B00D142E7013200271C1C303C28
        S1134C70092C05D80A214F4301323F191378F5E76F
        S1134C8001203AE70027381C37E71B4D295D1B4DEF
        S1134C902C57002C00D136E75378013233E76E2BC2
        S1134CA00ADC632B2CD002DC582B30D115E0642BAA
        S1134CB013D0692B2BD110E0732B23D009DC6F2B7D
        S1134CC00BD0702B23D101237825082703219C4680
        S1134CD01DE7752B01D0782B19D1002815D0069C1F
        S1134CE0022C00D013E70123069310E7BCFDFFFF5D
        S1134CF03F020000FD0100003A5000003550000062
        S1134D00002804D1002902D101E70127FFE6FF258D
        S1134D10FDE6582D65D116E0692D62D10DE7732D9E
        S1134D2023D002D86F2D5CD10DE0752D0BD0782DDA
        S1134D3057D108E0022901D100B204E7012900D0CB
        S1134D4001E740B2FFE6341D09943068032906D018
        S1134D50022901D180B202E0012900D1C0B2079E2C
        S1134D606246009201950296F2E63468311D09917B
        S1134D70002C00D12F4C6346002B07D02678013439
        S1134D80002800D1F0E6BE4237DCEDE6002808D06A
        S1134D90201C61463A1C00F08EF800282DD0061B1A
        S1134DA0E2E6201C00F0A3F8061CDDE6351D09959B
        S1134DB03468022907D003290AD0002900D036E735
        S1134DC00598206033E76F461421CB5B23802EE7E0
        S1134DD0059A22602BE73368301D10AC09902370CC
        S1134DE0A6E60C9800F083F8059E021C351805957C
        S1134DF0002819D00B980C992FE63E1CB4E6002429
        S1134E000794191C3039092900D922E7079D0A2380
        S1134E106B430132581807901378F2E7002706977E
        S1134E204EE601200D904BE605989124A400A5447C
        S1134E30F0BDC0463450000030B5C9B2031C1F2A6F
        S1134E4031D944420323234005D0D21AC518017036
        S1134E500130A842FBD1002905D00D060C042C43D7
        S1134E600B02214319435409031C002C0ED0251CAA
        S1134E70013D196059609960D9601961596199615E
        S1134E80D9612033002DF3D16301C318D006400F3C
        S1134E9007D0041C1D1C013C02C5002CFBD1800062
        S1134EA01B18032422409D18002A03D019700133D3
        S1134EB0AB42FBD130BD00B5C9B28218904205D0D7
        S1134EC0037801308B42F9D1013800E0002000BDA5
        S1134ED000B5C9B20378421C002B03D08B4205D025
        S1134EE0101CF7E74B4259414942084000BD00B548
        S1134EF0431E01331A78002AFBD1181A00BD0000A2
        S1134F0010B50B4C0B4B9C4202D001CC8047F9E707
        S1134F10094C0A48844202D008CC9847F9E7084C67
        S1134F2008498C4202D004CC9047F9E710BDC04632
        S1134F30405000004050000040500000405000002D
        S1134F40405000004050000010B5084C084B9C42F3
        S1134F5002D004CC9047F9E7064C0748844203D0BA
        S1134F60043C21688847F8E710BDC0464050000063
        S1134F7040500000405000004050000000B58842FE
        S1134F801FD0002A1DD00323194207D1184205D18E
        S1134F909A4203D908C9043A08C0F2E70123194226
        S1134FA009D1184207D19A4205D90B88023A0380E5
        S1134FB002310230E5E70B78013A03700131013028
        S1134FC0DFE700BD38B50B4D002D11D000242B199F
        S1134FD01968002906D02B1958689A68FFF7CEFF84
        S1134FE00C34F4E75A68002AF5D198680028F2D105
        S1134FF038BDC04640500000054B10B51C68002C5D
        S113500004D0A068616888472468F8E710BDC046EA
        S113501030F0FF1F054B181C002805D0854681B0D1
        S11350200020C043009001B0F746704700300020D4
        S1135030F746704700010000000102000000030071
        S11350404050000000F0FF1F0000000000000000BE
        S10B5050000000000000000054
        S90347BDF8

        And frdm_led_k25.hex

        S01300006672646D5F6C65645F6B32352E6865780B
        S1130400FFFFFFFFFFFFFFFFFFFFFFFF7EFFFFFF79——-> 2nd line
        S113400000300020E547000041450000494500001C
        S11340104945000049450000494500004945000064
        S11340204945000049450000494500004945000054
        S11340304945000049450000494500004945000044
        S11340404945000049450000494500004945000034
        S11340504945000049450000494500004945000024
        S11340604945000049450000494500004945000014
        S11340704945000049450000494500004945000004
        S113408049450000494500004945000049450000F4
        S113409049450000494500004945000049450000E4
        S11340A049450000494500004945000049450000D4
        S11340B049450000494500004945000049450000C4
        S113441002B4714649084900095649008E4402BC59
        S11344207047C04602B4714649084900095C490016
        S11344308E4402BC7047C046002934D001230022B8
        S113444010B488422CD301242407A14204D281420F
        S113445002D209011B01F8E7E400A14204D281421F
        S113446002D249005B00F8E7884201D3401A1A439C
        S11344704C08A04202D3001B5C0822438C08A042D3
        S113448002D3001B9C082243CC08A04202D3001B89
        S1134490DC082243002803D01B0901D00909E3E703
        S11344A0101C10BC7047002801D00020C04307B482
        S11344B0024802A14018029003BDC0461900000042
        S11344C00029F0D003B5FFF7B9FF0EBC4243891AA7
        S11344D01847C0467047C046C046C046C0467047ED
        S11344E00020C046C046C046C046C0460130092828
        S11344F0F7D9C0467047C04638B5051E1ED0FFF731
        S1134500EFFFD024013CA4B2013CA4B2FFF7E8FFC2
        S1134510FFF7E6FF002CF5D1013DADB2FFF7DCFF5C
        S1134520FFF7DAFFFFF7D8FFFFF7D6FFFFF7D4FF57
        S1134530FFF7D2FFFFF7D0FF002DE0D138BDC04612
        S113454008B500F087F908BDFFBE7047244B254A23
        S1134550254910B5D150254C88235A010020C0218B
        S1134560234BA0508802234AE050A058B0214B01AD
        S11345700343A350204CA278110704D5A078082146
        S11345800143CBB2A370194B194C00221B491A5199
        S11345905C581B48204058501C68C020000320432E
        S11345A018605C5817482040802464042043585005
        S11345B0154906230B704A70CC781F200440134B16
        S11345C0CC7080241C700A714A71102288790242CE
        S11345D0FCD00D490C248B791C42FCD110BDC04683
        S11345E0080D000000E000E00040000000700440FE
        S11345F0441000003810000000D0074004100000F0
        S1134600FFFFFEFFFFFFFFFC004006400050064096
        S1134610224A38B522481369E0210340C9000B43FC
        S11346201361204B1F255C79AC435C711C79072511
        S1134630AC431C711C4B73251C78AC4350252C4394
        S11346401C705C786325AC4340252C435C709C78DB
        S11346501925AC439C70154B00241C70156D284023
        S113466001431165C120124A8400135911490020E5
        S11346701940115100F082F80F4D286800F0A2F89B
        S1134680002000F047F8686800F068F8002000F0A7
        S113469015F8A86800F032F862B638BD00900440FE
        S11346A0FFF8FFFE00F0074000D0074000E007409D
        S11346B000E100E0FFFF00FF00F0FF1F0A4B0B4A80
        S11346C002211060586908435861186888431860CB
        S11346D0074B084958680140802040000143596055
        S11346E0054B101C9A607047C0F00F400CF0FF1F80
        S11346F000C00440FFF8FFFE00F0FF1F014B022240
        S11347005A607047C0F00FF8014B0222DA6070471C
        S1134710C0F00FF80B4B0C4A802110605869090354
        S1134720014359611868094901401960084B094956
        S1134730D86C0140802040000143D964064B101C12
        S11347405A60704740F00F4010F0FF1FFFFFF7FF63
        S113475000A00440FFF8FFFE00F0FF1F8022024B80
        S1134760100358607047C04640F00FF88022024B97
        S11347701003D8607047C04640F00FF80B4B0C4A4A
        S1134780802110605869C9020143596118680949B8
        S113479001401960084B0949986C01408020400091
        S11347A001439964064B101C1A60704740F00F4097
        S11347B014F0FF1FFFFFFBFF00A00440FFF8FFFE03
        S11347C000F0FF1F8022024BD00258607047C046A1
        S11347D040F00FF88022024BD002D8607047C046E8
        S11347E040F00FF801F08CF8FFF7B0FE0848094AD2
        S11347F00021121A00F04CF801F05AF800F0F6FF0C
        S113480001F08CF80449002000F00AF800F024F8C4
        S113481000F0FF1F34F0FF1F18F0FF1F00B5FEE784
        S113482010B5FFF7F5FE0A4C6420FFF765FE20681B
        S1134830FFF7D0FFC820FFF75FFE6068FFF796FF21
        S1134840C8204000FFF758FEA068FFF75DFFEBE7C4
        S113485000F0FF1F7047C04638B5051C01F042F850
        S113486000F0E8FF084C2368002B02D09847002092
        S11348702060064C2168002902D08847002222606B
        S1134880281CFFF7CBFF38BD1CF0FF1F20F0FF1FD3
        S113489010B5041C00F03EFF201C10BDF0B589B01B
        S11348A001901F1C0EAB0391079202901A78081C0A
        S11348B001990FAC01380026049225780670B142A4
        S11348C017D1119BB34214D1049B002B01D06F2D3F
        S11348D02FD0642D02D0692D00D0A8E0022F02D180
        S11348E0039802389FE0012F00D0A0E0039802381B
        S11348F094E0692D0ED004D8582D16D0642D1CD107
        S113490008E0752D04D0782D0FD06F2D15D110E04F
        S1134910002712E0019A002A0FDA80242606B24208
        S11349200DD051420191029109E000273E1C102450
        S113493007E000273E1C082403E0002600E00126CF
        S11349400A240090002006900298211CFFF7B8FD6D
        S113495002980591211CFFF76FFD059A0290092A20
        S113496001D8303205E0059A3732782D01D1059A05
        S113497057320098069B02990138D2B20090027017
        S11349800133002901D00693DEE7011C082C0BD16A
        S11349900498002808D0302A06D00B1C013B302292
        S11349A000931A70069B0233079802280FD1002E39
        S11349B001D1002F02D0109901391091109A11924F
        S11349C0102C04D10498002801D0023A11920399C2
        S11349D00098119A091A8918164A914226DC0099FE
        S11349E0CA181199121A8A4203DA01383022027065
        S11349F0F5E7102C0AD1049C002C07D0019B002B56
        S1134A0004D0421E3021023815700170002E02D0ED
        S1134A1001382D2108E0012F02D101382B2103E0B8
        S1134A20022F04D101382021017000E0002009B0D8
        S1134A30F0BDC046FD010000F0B5B64C1E1CA544F7
        S1134A406B460A900B913E33202100201970089286
        S1134A500590089A1578002D00D1F9E108982521D0
        S1134A6000F0ADFE0C90002811D1089800F0B6FEBD
        S1134A700599021C08180590002A00D1E8E10B985A
        S1134A8008990A9EB047002800D0E1E1CEE00C9FCF
        S1134A90089C05993A1B8B180593002A0CD10C9895
        S1134AA00C9A437801321D1E252D0CD000270121BC
        S1134AB0BC460D97069119E00B9808990A9DA847E2
        S1134AC00028ECD1B2E00C9A0021023201240892B1
        S1134AD0079106943DE02B2B0BDC202B10D0232BCD
        S1134AE000D0BAE001239C46013213782B2BF2D17B
        S1134AF0ABE12D2B00D1A5E1302B00D0ADE004E0DB
        S1134B000D9D012DF0D00220A0E1069C002CEBD0DD
        S1134B1002200690E8E737680436FB43D80F937801
        S1134B2002321C1C683C0021042C00D8C1E0DDB218
        S1134B306E2B00D0C7E0013208926E2D00D149E1FE
        S1134B4000D900E1632D00D159E107D8252D00D00B
        S1134B50F3E010AC25700996012619E0642D00D00D
        S1134B60EEE0321D09923068032900D0F6E007997F
        S1134B706646009601950291039790A9069A0D9BAB
        S1134B80FFF78CFE041E00D13FE1634F6F443E1AD1
        S1134B90069800283CD02023022800D130236F46F9
        S1134BA03E373B7022782B2A04D02D2A02D0371CA2
        S1134BB0202A0BD1371C302B08D10B98211C012241
        S1134BC00A9B9847002831D00134771E06990229A0
        S1134BD00ED1612D01D0412D0AD1012F26DD0B9874
        S1134BE0211C02220A9DA84700281FD0023F02343C
        S1134BF0351C079EB54209DA69460B983E310122FD
        S1134C000A9B9847002811D00135F2E73E1C00E0CA
        S1134C10351C002E03D10698002819D115E0211C5B
        S1134C200B98321C0A9CA0470028F4D1012255425B
        S1134C3005950DE169463F3120240B9801220A9F16
        S1134C400C70B8470028F1D00135079FBD42F1DB55
        S1134C50059A53190593099EFBE6171C2A2B00D0CD
        S1134C60E1E0341D36680796002E03DA734200250E
        S1134C70079306957B780132261C284F0798B84283
        S1134C8000DDC2E02E2B11D153782A2B00D142E74C
        S1134C90013200271C1C303C092C05D80A214F4343
        S1134CA001323F191378F5E701203AE70027381C51
        S1134CB037E71B4D295D1B4D2C57002C00D136E7DF
        S1134CC05378013233E76E2B0ADC632B2CD002DCE1
        S1134CD0582B30D115E0642B13D0692B2BD110E065
        S1134CE0732B23D009DC6F2B0BD0702B23D1012322
        S1134CF07825082703219C461DE7752B01D0782BC6
        S1134D0019D1002815D0069C022C00D013E70123EA
        S1134D10069310E7BCFDFFFF3F020000FD01000009
        S1134D202659000021590000002804D1002902D18D
        S1134D3001E70127FFE6FF25FDE6582D65D116E0C2
        S1134D40692D62D10DE7732D23D002D86F2D5CD16C
        S1134D500DE0752D0BD0782D57D108E0022901D133
        S1134D6000B204E7012900D001E740B2FFE6341D98
        S1134D7009943068032906D0022901D180B202E0E7
        S1134D80012900D1C0B2079E6246009201950296A5
        S1134D90F2E63468311D0991002C00D12F4C634692
        S1134DA0002B07D026780134002800D1F0E6BE425B
        S1134DB037DCEDE6002808D0201C61463A1C00F0E0
        S1134DC0E8FC00282DD0061BE2E6201C00F006FDBE
        S1134DD0061CDDE6351D09953468022907D0032930
        S1134DE00AD0002900D036E70598206033E76F46E3
        S1134DF01421CB5B23802EE7059A22602BE73368CE
        S1134E00301D10AC09902370A6E60C9800F0E6FC67
        S1134E10059E021C35180595002819D00B980C998D
        S1134E202FE63E1CB4E600240794191C30390929E6
        S1134E3000D922E7079D0A236B43013258180790D3
        S1134E401378F2E7002706974EE601200D904BE613
        S1134E5005989124A400A544F0BDC0462059000043
        S1134E60F0B50027A9B0059006910F9309920D970C
        S1134E700B9708970A970C970497099D2C78002C98
        S1134E8000D103E3201C00F047FB002822D0099A3C
        S1134E9001321078099200F03FFB0028F7D1002F6F
        S1134EA000D0F1E2002106980A1C059CA047061CCC
        S1134EB000F032FB002803D0049B01330493F1E794
        S1134EC0701C04D12E98002800D1DFE20127069837
        S1134ED0311CABE2252C1BD0002F19D1391C0698AC
        S1134EE03A1C059EB047C1B2A1420AD006980122DD
        S1134EF0B0472E9F002F00D1C8E2099D01350995C6
        S1134F00C2E2049B09990133013104930991B4E786
        S1134F101EAC201C00212822FFF7BAFC0998A54EDC
        S1134F2045786660281E25280CD1211C14A8282247
        S1134F30E57000F03BFC099C0020023409940790C2
        S1134F400E90D7E02A2D02D0099C013405E00123FC
        S1134F5009992370099C88780234021C303A092A82
        S1134F601FD800260A256E433038013436182078BD
        S1134F70031C303B092BF5D91EAD6E60002E0ED1FB
        S1134F8001235942E97014A8291C2822013400F095
        S1134F900DFC2B780994FF2507960E969DE00126BB
        S1134FA06E701EA9682804D06C280CD10320887068
        S1134FB007E0637802228A70682B02D101258D7084
        S1134FC06419607801341EABD8705838202871D821
        S1134FD0FFF728FA7270702B707070707070701513
        S1134FE0727070707072707070707272117070196B
        S1134FF070727070720003269E7078215BE09A785C
        S1135000002A59D056E09978002901D0FF20D870A1
        S113501000231EAAD518FF2601332E72202BF8D1A7
        S1135020C121FE205172107346E09D78002D01D0FD
        S1135030FF26DE7063785E2B02D00134002102E08B
        S1135040A378012102345D2B07D11EAB2020D87434
        S11350506378013401E0E3780334002B00D139E2B2
        S11350605D2B00D139E2DDB2EA081EAE0720B2188A
        S1135070184001258540107A2E1C65780643167267
        S11350802D2D14D1A278002A11D05D2A0FD001331E
        S11350909342E0DCDEB2F0081EAD281807251D405F
        S11350A00126AE40351C067A35430572EFE701341C
        S11350B02B1CD2E7FF21D9701EAE311C282214A864
        S11350C000F074FB6A467A327178107833780E9166
        S11350D00790F578013476680994002B06D1252DC4
        S11350E008D00F9A146804320F9200E000246E2D49
        S11350F001D1ADE10024002F01D001270AE0069878
        S1135100391C0222059B9847002803D02E9F002FAC
        S1135110F3D1BBE1692D25D012D85B2D00D115E167
        S113512006D8252D00D1D3E0582D00D0AEE13EE0C5
        S1135130632D00D17CE0642D00D0A7E10A2012E0A9
        S1135140732D00D1E6E007D86E2D00D180E16F2DDC
        S113515000D09BE1082030E0752D2DD0782D00D0B3
        S113516094E124E00020002F48D112A913AA11AD24
        S113517001910292311C0095059A069B00F0E3F917
        S1135180119E002E05D12E98002828D101240B94BD
        S11351907CE1049B129D9E190496002D05D080216C
        S11351A00A06904201D043422AE0031C28E0102062
        S11351B003E0C046FFFFFF7F0A20002F1ED111AB82
        S11351C013A912AD00930291069B311C0195059A17
        S11351D000F0B9F9119E031C002E03D1D3E7012777
        S11351E0331C0DE0049A129D90190490002D07D0F1
        S11351F080210E06B34203D05B4201E00127002365
        S1135200002C11D0079E032E09D8301CFFF70AF991
        S113521006020406237002E0238000E023600C9D54
        S1135220794279416A180C920A9801300A906EE02A
        S11352300E98002800D10126002C33D000211191B2
        S1135240A6198F4200D01FE1B44219D02E9A002A29
        S113525004D01198002811DA01230D930021069837
        S11352600A1C059DA8470890013009D008AB1D7899
        S113527025701199013401311191E5E700240D9451
        S1135280119E2E9A002E00D1A0E0002A03D00D9981
        S1135290002900D1F8E0049A0C9C90190134049080
        S11352A00C94D1E01194013E701C0CD0002106989E
        S11352B00A1C059B9847013E0890013003D0119DBC
        S11352C001351195F0E7119E002E00D0BCE0DDE021
        S11352D0002F00D0D5E0002106980A1C059EB04797
        S11352E0051C00F019F9002803D0049C013404942F
        S11352F0F1E7252D08D001220698291CB0472E9AE3
        S1135300002A00D142E7BCE0049901310491012450
        S11353100B94B2E501230B93002F17D10698391C87
        S11353203A1C059DA847051C00F0F6F8002806D095
        S1135330049B00210133049306980A1CF1E701221F
        S11353400698291C059B984701220B92002C49D0F2
        S1135350002111918F4200D096E0013E351C711C52
        S113536024D02E9A002A04D0119B002B1CDC01208F
        S11353700D90002106980A1C059B9847089001305F
        S113538014D008A90B7814A8DA0882180898072101
        S11353900140127A01208840104207D02370119DE9
        S11353A0013401351195D8E700260D96119B08AEFE
        S11353B03178002B05D02E9800280AD00D9A002AA7
        S11353C007D101220698059FB8472E9A002A5DD07E
        S11353D05AE00020049E20700C9CF31801340493BE
        S11353E00C942BE01194013E351C711C19D0002142
        S11353F006980A1C059CA0470890013011D008A803
        S1135400017814AACB080898D41807230340012173
        S1135410247A9940013E214203D0119D0135119512
        S1135420E2E7119E002E05D1069808990122059BFA
        S1135430984722E5049B089998190490002D03DBF2
        S113544006980122059DA8470A9901310A9114E59D
        S1135450002C00D111E5079A032A00D90DE5101C90
        S1135460FEF7E0FF070A02076D4610214A5B22801F
        S113547003E50498206000E568461026335C237039
        S1135480FBE401270B97F8E40127F6E400210698D2
        S11354900222059DA8470A99002805D0002928D191
        S11354A0012670420C9024E0002922D10B9A002A94
        S11354B01FD00A9906980A1C059FB8470A99041C2C
        S11354C002220698B8470028EAD10698211C012236
        S11354D0B8470EE0FF211EABEDE5002900D1EBE556
        S11354E020AD2A7828A8D6432E7001358542F8D1FC
        S11354F0E2E50C9829B0F0BD8022031C00B5002021
        S113550051008B4204D803480122C3185878104034
        S113551000BDC0462B5900008022031C00B50020AA
        S113552051008B4204D803481022C3185878104005
        S113553000BDC0462B590000031C613B00B5192B6C
        S113554000D8203800BDF0B587B0059101930D99BE
        S11355500E9B009200220A60071C1A60904216DB20
        S1135560012814D0242812DC0598904207DD009C01
        S11355700198111CA0470126041C351C02E0141CD0
        S1135580161C402500220392974209D002E0141C05
        S1135590161C402501214842391CFEF74DFF03909B
        S11355A00023029304930598864200DD9EE0621C6A
        S11355B000D19BE06022154200D097E0681E0F28BE
        S11355C0F1D8FEF725FF082EF03FF0F0F052F0F08E
        S11355D0F0F0F0F0F052201CFFF79EFF021E09D0FD
        S11355E00021009C01980A1CA047041C0498013067
        S11355F00490D8E72B2C07D1009D0198111CA847D3
        S11356000136041C0225CEE702252D2CCBD1111C1A
        S11356100198009B98470D9901220136041C0A60E9
        S1135620C1E7002F02D00825102FBCD10825302C4B
        S1135630B9D10021009C01980A1CA0470136041C22
        S11356400425B0E7582C01D0782C09D10021019809
        S11356500A1C009B98470136041C08251027A2E762
        S11356601025002F9FD108279DE7002F00D10A277E
        S11356700398002805D101225042391CFEF7DCFEB4
        S11356800390201C3038092802D8B84211DB0BE003
        S1135690201CFFF731FF002806D0201CFFF74CFF29
        S11356A0011C3639B94203DD102D1DD120257AE7BE
        S11356B03738029D039C0123A54201D80E9B1B6829
        S11356C0029AC5B27A43D1438D4200D901230E9C7C
        S11356D08018002123600290009D01980A1CA847AD
        S11356E00136041C10255EE740255CE734273D4065
        S11356F003D10C9B02951D6004E0049D013E0C99AE
        S113570076190E60211C01980122009CA047029882
        S113571007B0F0BD30B5C9B2031C1F2A31D94442C9
        S11357200323234005D0D21AC51801700130A842C2
        S1135730FBD1002905D00D060C042C430B02214398
        S113574019435409031C002C0ED0251C013D19607B
        S113575059609960D960196159619961D96120339F
        S1135760002DF3D16301C318D006400F07D0041CE9
        S11357701D1C013C02C5002CFBD180001B18032416
        S113578022409D18002A03D019700133AB42FBD18B
        S113579030BD00B5C9B28218904205D003780130FB
        S11357A08B42F9D1013800E0002000BD10B5002380
        S11357B0934203D0CC5CC4540133F9E710BD00B567
        S11357C0C9B20378421C002B03D08B4205D0101CB5
        S11357D0F7E74B4259414942084000BD00B5431E1A
        S11357E001331A78002AFBD1181A00BD10B50B4CEE
        S11357F00B4B9C4202D001CC8047F9E7094C0A4884
        S1135800844202D008CC9847F9E7084C08498C42F6
        S113581002D004CC9047F9E710BDC0462C5A0000D2
        S11358202C5A00002C5A00002C5A00002C5A00005C
        S11358302C5A000010B5084C084B9C4202D004CCF2
        S11358409047F9E7064C0748844203D0043C21689A
        S11358508847F8E710BDC0462C5A00002C5A0000B7
        S11358602C5A00002C5A000000B588421FD0002A90
        S11358701DD00323194207D1184205D19A4203D9F6
        S113588008C9043A08C0F2E70123194209D11842B1
        S113589007D19A4205D90B88023A038002310230BB
        S11358A0E5E70B78013A037001310130DFE700BD11
        S11358B038B50B4D002D11D000242B19196800297F
        S11358C006D02B1958689A68FFF7CEFF0C34F4E71A
        S11358D05A68002AF5D198680028F2D138BDC0462C
        S11358E02C5A0000054B10B51C68002C04D0A0688D
        S11358F0616888472468F8E710BDC04630F0FF1F90
        S1135900054B181C002805D0854681B00020C043F3
        S1135910009001B0F746704700300020F74670470A
        S1135920000100000001020000000300808080806C
        S11359308080808080909090909080808080808013
        S1135940808080808080808080808080180404042F
        S1135950040404040404040404040404020202020B
        S11359600202020202020404040404040443434342
        S1135970434343414141414141414141414141410D
        S113598041414141414141040404040404232323CB
        S113599023232321212121212121212121212121ED
        S11359A0212121212121210404040480000000007C
        S11359B000000000000000000000000000000000E3
        S11359C000000000000000000000000000000000D3
        S11359D000000000000000000000000000000000C3
        S11359E000000000000000000000000000000000B3
        S11359F000000000000000000000000000000000A3
        S1135A000000000000000000000000000000000092
        S1135A100000000000000000000000000000000082
        S10F5A2000000000000000000000000076
        S1135A2C2C5A000000F0FF1F0000000000000000D2
        S10B5A3C00000000000000005E
        S90347E5D0

        You can see the second line in each hex. file.

        Can you guide me what to do to solve this issue.

        Thanks.

        Like

      • Hello,
        can you check in the CPU settings (as in image “Application Memory Area Settings”) that you don’t have anything allocated at address 0x400 or in the area of the bootloader?
        You might check as well the linker file for this.

        Erich

        Like

      • Hi Erich,

        Thanks again for your reply..

        The problem solved… In the CPU’s flash configuration settings in CW10.6, The “Flash configuration field” was Enabled. So after disabled it 0x0400 problem solved.

        Have a nice week, thanks again!

        Anand –

        Like

  3. Hi Erich,
    during the build process, is possible to know the crc or checksum of flash-image builded, via a variable/macro similar to the date and time-of-build as __DATE__, __TIME__?
    Thats to validate/unvalidate an eventually partial storage of .S19 during an uploader, avoiding any launch of incomplete/errored .s19 file.

    Like

  4. Hi Erich,
    Mind blowing work as always. If You have written any basic bootloader program say ” Hello World” bootloader for freescale KE-02Z processor kindly send me the link.
    Thanks & Regards
    Ganesh R
    (Ardent follower of Erich’s Blog)

    Like

  5. Hi Erich
    I have 2 doubts.
    1. I am using J link segger to dump the code into board. Do I still need a terminal ?
    2. I don’t have COM port, so I cant use terminal program right ?
    I am yet to be graduated. So my doubt may sound rubbish to you. Kindly clear my doubt Erich.
    Thanks & Regards
    Ganesh R

    Like

    • Hi Ganesh,

      1) If you are using a Segger J-Link to program your device/board, then you don’t need a serial bootloader.

      2) You don’t need a COM (UART?) port, this works as well with USB CDC (Serial over USB)
      I hope this helps,
      Erich

      Like

      • Hi Erich,
        Thanks for your speedy and clear response 🙂 . Have you tried writing a bootloader for any controller which is programmed by J link ? If you have kindly post the link. Sorry for pestering you often.
        Thanks & Regards
        Ganesh R
        (An ardent follower of Erich’s Blog)

        Like

      • Yes, that board presented in this post with this bootloader is programmed with a J-Link. The board can be programmed by any programmer, it does not matter for the bootloader.

        Like

      • Hey Erich,
        Thanks for the Updates to my KDS. When I tried to Include Shell to project I got this Pop Up message
        “The component “CLS1” uses another shared component for item “Console Interface”. You can add new one just now or use existing one.”
        1.FSL_USB_Stack
        2.Bluetooth_EGBT
        3.Serial
        4.SeggerRTT
        Which should I select.

        Like

      • This configures the ‘default’ configuration channel. It depends on what you want/need. Serial uses UART, SeggerRTT is using the debug channel, Bluetooth uses a UART-to-Bluetooth channel and FSL_USB_Stack uses USB_CDC.

        Like

      • Hey Erich,
        I included USB CDC, but inside USB CDC Device’s CPU settings, the controller series which I use is not present. I am using Kinetis E series Controller. MKE02Z64VLD2
        Thanks

        Like

  6. Hi Erich!

    I’m trying to use this example of bootloader . I’m just configured the KDS 3.1 to create a flash image and the “Output file format (-O)” like “Motorola S-record”, to generate the “.srec” file. When I try to load the “.srec” file on “Terminal v1.93b” some errors appear, like these:
    ———————————————–
    Erasing application flash blocks…done!
    Waiting for the S19 file…
    S0 address 0x00000000ERROR!
    Failed at address 0x00000400

    failed!
    Erasing application flash blocks…done!
    *** Failed or unknown command: BL load s19
    *** Type help to get a list of available commands
    CMD> *** Failed or unknown command: S113400000300020454300001544000
    *** Type help to get a list of available commands
    CMD> *** Failed or unknown command: 02144000016
    *** Type help to get a list of available commands
    CMD> *** Failed or unknown command: S113401021440000214400002144000
    *** Type help to get a list of available commands
    CMD> *** Failed or unknown command: 02144000008
    *** Type help to get a list of available commands
    CMD> *** Failed or unknown command: S113402021440000214400002144000
    *** Type help to get a list of available commands
    CMD> *** Failed or unknown command: 021440000F8
    …….and more!

    Do I need check some extra configuration on the Kinetis Design Studio 3.1?

    Thanks!

    André Lemke

    Like

      • Hi Erich, thank you for reply!

        The problem wasn’t in the bootloader application, but in my main application. In the component CPU, the “Flash Configuration Field” was Enabled, I just turn it to Disabled and everything works fine.

        Have a nice week, thanks again!

        André Lemke

        Like

  7. Hey Erich,
    As per your advice I used a USB to Serial converter and created a virtual com port. You said segger rtt wont go well, instead use SERIAL from processor expert. But when I included it, it is again showing that red color cross mark “X” over the component. I dono how to include screenshots in comments here. So I created a wordpress blog and posted it. Pls check out to understand my doubt clearly.This is the link: https://oscarganesh.wordpress.com/2016/03/17/problem-in-including-serial-component-in-kds/
    I am using MKE02Z64VLD2 controller for your info.
    Thanks Erich

    Like

  8. Hey Erich,
    What is the use of terminal app ? I am a beginner(Still in undergraduation) with no previous experience in embedded. My understanding from this article is,
    1. Write down the code you uploaded in GITHUB in the IDE (I use KDS)
    2. Follow the first 2 steps of this article.
    3. Before using Terminal App, dump the code into the Controller (I use KE-02Z) by using a debugger (I use Segger’s J link) connected, with the help of “Flash from file” option in KDS.
    4. Once the code is dumped into the controller, disconnect the debugger, and connect the Serial to USB converter between the PC and Controller.
    5. Now in the Terminal App, choose the virtual COM port created and then follow the 3rd step as mentioned in this article.
    My 1st Doubt is, why do I need Terminal app, what exactly it does here ?.
    I got this doubt because we have programmed a Press Button whose pressing and depressing is going to switch the control between Boot loader and Application codes.
    My 2nd doubt is what should be sent over Terminal app and why ?
    My 3rd doubt is https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/CodeWarrior/FRDM-KL25Z/FRDM_Bootloader
    In this link there is no BL_Blink_s19 file. Where can I find it ?
    Hope I create a boot loader without any hurdles after getting this doubt cleared by you.
    Thanks
    Ganesh R

    Like

  9. Hey Erich,
    It is saying syntax error for this statement.
    SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK |
    SIM_SCGC5_PORTB_MASK |
    SIM_SCGC5_PORTC_MASK |
    SIM_SCGC5_PORTD_MASK |
    SIM_SCGC5_PORTE_MASK;
    Is the syntax different for Kinetis E series controller ? I am using MKE02Z64VLD2. I am working on Kinetis Design Studio IDE.
    Thanks

    Like

  10. Hey Erich,
    Is this step mandatory, because in the Github this code snippet is mentioned in Bootloader.c but in this article where you have explained, you have skipped this step. If its mandatory to be included can you explain what this code snippet will do ?
    #if 0
    /* GPIOB_PDDR: PDD&=~0x0100 */
    GPIOB_PDDR = (uint32_t)((GPIOB_PDDR & (uint32_t)~0x0100UL) | (uint32_t)0x00UL);
    /* Initialization of Port Control register */
    /* PORTB_PCR8: ISF=0,MUX=1 */
    PORTB_PCR8 = (uint32_t)((PORTB_PCR8 & (uint32_t)~0x01000600UL) | (uint32_t)0x0100UL);
    Thanks

    Like

    • If you need that code or not depends how you want to use the bootloader. This code is about initializing the PORTB pin which can be used for a push button to enter bootloader mode.
      If you don’t need something like that, you can skip that code.

      Like

  11. Hey Erich, I need to configure PTB1 (PORTB1) pin as bootloader button in my customized board. Mine is a Kinetis E series controller (KE-02Z). Will this code (which I edited in one or two places from your original code) work ?
    /* clock all port pins */
    SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK |
    SIM_SCGC5_PORTB_MASK |
    SIM_SCGC5_PORTC_MASK |
    SIM_SCGC5_PORTD_MASK |
    SIM_SCGC5_PORTE_MASK;
    /* Configure pin as input */
    #if 0
    /* GPIOB_PDDR: PDD&=~0x0100 */
    GPIOB_PDDR = (uint32_t)((GPIOB_PDDR & (uint32_t)~0x0100UL) | (uint32_t)0x00UL);
    /* Initialization of Port Control register */
    /* PORTB_PCR1: ISF=0,MUX=1 */
    PORTB_PCR1 = (uint32_t)((PORTB_PCR1 & (uint32_t)~0x01000600UL) | (uint32_t)0x0100UL);
    #else
    (void)BitIoLdd1_Init(NULL); /* initialize the port pin PTB8 */
    /* enable internal pull-up on PTB1 */
    PORT_PDD_SetPinPullSelect(PORTB_BASE_PTR, 1, PORT_PDD_PULL_UP);
    PORT_PDD_SetPinPullEnable(PORTB_BASE_PTR, 1, PORT_PDD_PULL_ENABLE);

    Thanks in advance

    Like

      • Hey Erich,
        Thanks, I ll try to include KIN1.h as per your suggestion. Now coming to the LEDR_Neg doubt. See am not using Freedom board am using a customized board and I know its schematics. In this bootloader, we are sending s19 converted file of a LED blinking code right, my LED blinking code is like this

        unsigned int i;
        for(;;){
        Bit1_ClrVal();

        for(i=0;i<=1000000;i++); //software delay

        Bit1_SetVal();

        for(i=0;i<=1000000;i++); //software delay
        }

        In this code I have included a " General 1 Bit Input/ Output" Processor Expert Component. From the schematics of the board am using I found that the PORTD's PIN1 is connected to an LED. So I configured the " General 1 Bit Input/ Output" Processor Expert Component to PTD1 and set the Direction as Output, Initial value as 1. I executed the code, LED blinked fine. I tried with NegVal() instead of ClrVal and SetVal combination, the LED glew, probably the blinking was so fast to be noticed by human eyes. In you Code you have included LEDR_NegVal (). For my setup, what statement will serve the purpose instead of LEDR_NegVal()
        Thanks & Regards

        Like

      • Your software delay method is not appropriate and subject of compiler optimizations. At least you should use
        volatile unsigned int i;
        or use a timer based or more accurate delay method (e.g. using the Wait component).

        Liked by 1 person

      • https://mcuoneclipse.com/2013/04/28/serial-bootloader-for-the-freedom-board-with-processor-expert/#comment-82112
        In reply to this comment. Actually the code works fine Erich. LED is blinking without givin volatile unsigned.. my doubt is in the place of LEDR_NegVal() what should I write for my led blinking code which is working fine for the syntax i followed. whether it should be
        SHELL_Parse();
        LEDR_SetVal();
        WAIT1_Waitms(100);
        Ledr_ClrVal();
        WAIT1_Waitms(100);
        instead of
        SHELL_Parse();
        LEDR_NegVal();
        WAIT1_Waitms(100);
        Sorry for brooding you. Thanks for help..

        Like

      • LEDR_NegVal() is fine. Just mame sure that the NegVal() method is enable in the component (it is disabled by default, having an ‘x’ in the icon).
        Just one thing: you parse the shell every 100 ms. That’s a bit slow. I usually do it every 20 or 50 ms.

        Liked by 1 person

  12. static void BL_PrintStatus(CLS1_ConstStdIOType *io) {
    unsigned char buf[32];

    CLS1_SendStatusStr((unsigned char*)”BL”, (const unsigned char*)”\r\n”, io->stdOut);
    UTIL1_strcpy(buf, sizeof(buf), (unsigned char*)”0x”);
    UTIL1_strcatNum32Hex(buf, sizeof(buf), MIN_APP_FLASH_ADDRESS);
    UTIL1_strcat(buf, sizeof(buf), (unsigned char*)”..0x”);
    UTIL1_strcatNum32Hex(buf, sizeof(buf), MAX_APP_FLASH_ADDRESS);
    UTIL1_strcat(buf, sizeof(buf), (unsigned char*)”\r\n”);
    CLS1_SendStatusStr((unsigned char*)” App Flash”, buf, io->stdOut);

    UTIL1_strcpy(buf, sizeof(buf), (unsigned char*)” @0x”);
    UTIL1_strcatNum32Hex(buf, sizeof(buf), MIN_APP_FLASH_ADDRESS);
    CLS1_SendStatusStr(buf, (unsigned char*)””, io->stdOut);
    UTIL1_strcpy(buf, sizeof(buf), (unsigned char*)”0x”);
    UTIL1_strcatNum32Hex(buf, sizeof(buf), *((uint32_t*)MIN_APP_FLASH_ADDRESS));
    UTIL1_strcat(buf, sizeof(buf), (unsigned char*)” 0x”);
    UTIL1_strcatNum32Hex(buf, sizeof(buf), *((uint32_t*)MIN_APP_FLASH_ADDRESS+4));
    UTIL1_strcat(buf, sizeof(buf), (unsigned char*)”\r\n”);
    CLS1_SendStr(buf, io->stdOut);
    }
    I was going through your code in GITHUB, and now I am confused What does this above code snippet would do ?
    Can you explain the job done by this code ?

    Like

    • Hello,
      what this code does is listing the flash areas used with the bootloader. So it would show something like this:
      App Flash : 0x00004000..0x0001FFFF
      @0x00004000: 0xFFFFFFFF 0xFFFFFFFF
      as outlined in this article.

      Liked by 1 person

  13. Dear Erich,
    I am a beginner. This whole boot loader code I found in Github. Thanks for making it available to us. I have one doubt. Whenever we create a project in KDS (any IDE for that matter) there will be following files created under SOURCES sub-folder
    1.Events.c
    2.Events.h
    3.Main.c
    Now in the SOURCES sub-folder of your Project I found the following.
    1.Bootloader.c
    2.Bootloader.h
    3.Events.c
    4.Events.h
    5.Shell.c
    6.Shell.h
    7.sa_mtb.c

    Should I delete the main.c file and create 2 seperate source files and 2 seperate header files and name them as Bootloader.c, Shell.c, Bootloader.h, Shell.h respectively and then fill in the codes provided by you?
    What is the file “sa_mtb.c” for ? Is it something related to codewarrior ? I am using Kinetis Design Studio, So can I ignore it ?
    Thanks & Regards
    G.Ram

    Like

    • Hi G.Ram,
      a bootloader is definitely not an easy start for a beginner: it is actually something of the more complex things. Events.c/.h and main.c are created and mainted by Processor Expert. If you read the sources and comments, you will see where you are can do changes. You should not delete main.c, keep it as it is. sa_mtb.c is for the ‘Software Analysis with Micro Trace Buffer’. See as well https://mcuoneclipse.com/2012/12/28/migrating-kinetis-l-projects-from-beta-to-final-mcu-10-3/. Simply keep that file in your projects, and it is CodeWarrior related only (there is no such trace option in Kinetis Design Studio).

      Like

      • Hey Erich,
        Thanks for the reply sir. In future scope, you have quoted, ” Performing vector auto-relocation: the bootloader should detect the vector table at address 0x00 of the application file and automatically relocate it to another location in FLASH. That way I can debug the Application without change of the vector table.”
        Can you explain this ? Like how it is done in this project ? and What is that you are suggesting ?
        Thanks alot sir
        G.Ram

        Like

      • Usually I do the vector allocation in the linker file to the correct place, so the bootloader does not need this relocation. Otherwise simply implement that in the bootloader: check if you have objects at the default vector table location, starting at address zero. If so, copy the vector table to predefine location in FLASH. Of course that re-located location needs to be available.

        Liked by 1 person

    • Hi Ganesh,
      As a first comment: you are using the term ‘bugs’ for the problems you face porting that project to the Kinetis E series. Strictly speaking such things are not ‘bugs’ but porting errors while you are doing the port.
      I’m affraid that the Kientis E series is very different from the other Kinetis, so that porting task is not an easy one.
      Here are my hints for the problems you are facing:
      1. You need to check the manual of the device to find out what your page/flash sector size is (FLASH_PAGE_SIZE). This has nothing to do with your component settings.
      2. For the SIM code in BL_CheckBootloaderMode, you need to read the reference manual about all the SIM settings. You need to rewrite that function for your device. Alternatively you could check at the Processor Expert code how it does handle the clocking and muxing for your device.
      3. For the PDD macros, here again you would need to check your device manual how you turn on pull-ups on a push button (unless you use a different method to enter bootloader mode).

      I hope this helps.
      2.

      Like

      • Dear Erich,
        Thanks a lot for suggestions. But this reference manual of Kinetis E series is no where to be found. Can you suggest me the link ?

        Like

      • Dear Erich,
        In KDS, Project Explorer -> Static_Code -> PDD -> PORT_PDD.h … I found this for my project.
        /* —————————————————————————-
        — SetPinPullSelect
        —————————————————————————- */

        /**
        * @brief Sets pull type.
        * @param PeripheralBase Pointer to a peripheral registers structure (peripheral
        * base address). You can use the constant defined in the registers
        * definition header file (_BASE_PTR) or the constant defined in
        * the peripheral initialization component header file
        * (_DEVICE).
        * @param PinIndex Pin index inside the port. This parameter is of index type.
        * @param Type Pull type. This parameter is of “Constants for pull type
        * selection” type.
        * @return Returns a value of void type.
        * @remarks The macro accesses the following registers: PCR[PinIndex].
        * @par Example:
        * @code
        * PORT_PDD_SetPinPullSelect(_BASE_PTR, periphID,
        * PORT_PDD_PULL_DOWN);
        * @endcode
        */
        #define PORT_PDD_SetPinPullSelect(PeripheralBase, PinIndex, Type) ( \
        PORT_PCR_REG(PeripheralBase,(PinIndex)) = \
        (uint32_t)(( \
        (uint32_t)(( \
        PORT_PCR_REG(PeripheralBase,(PinIndex))) & (( \
        (uint32_t)(~(uint32_t)PORT_PCR_PS_MASK)) & ( \
        (uint32_t)(~(uint32_t)PORT_PCR_ISF_MASK))))) | ( \
        (uint32_t)(Type))) \
        )

        /* —————————————————————————-
        — SetPinPullEnable
        —————————————————————————- */

        /**
        * @brief Sets pull type.
        * @param PeripheralBase Pointer to a peripheral registers structure (peripheral
        * base address). You can use the constant defined in the registers
        * definition header file (_BASE_PTR) or the constant defined in
        * the peripheral initialization component header file
        * (_DEVICE).
        * @param PinIndex Pin index inside the port. This parameter is of index type.
        * @param State Requested state of pull enable. This parameter is of “Constants
        * for pull enabling/disabling” type.
        * @return Returns a value of void type.
        * @remarks The macro accesses the following registers: PCR[PinIndex].
        * @par Example:
        * @code
        * PORT_PDD_SetPinPullEnable(_BASE_PTR, periphID,
        * PORT_PDD_PULL_DISABLE);
        * @endcode
        */
        #define PORT_PDD_SetPinPullEnable(PeripheralBase, PinIndex, State) ( \
        PORT_PCR_REG(PeripheralBase,(PinIndex)) = \
        (uint32_t)(( \
        (uint32_t)(( \
        PORT_PCR_REG(PeripheralBase,(PinIndex))) & (( \
        (uint32_t)(~(uint32_t)PORT_PCR_PE_MASK)) & ( \
        (uint32_t)(~(uint32_t)PORT_PCR_ISF_MASK))))) | ( \
        (uint32_t)(State))) \
        )

        My code:
        PORT_PDD_SetPinPullSelect(PORTB_BASE_PTR, 1, PORT_PDD_PULL_UP);
        PORT_PDD_SetPinPullEnable(PORTB_BASE_PTR, 1, PORT_PDD_PULL_ENABLE);

        In your code you have used PTB8 as BTLD button. I am trying to use PTB1 as BTLD button.
        As per the PORT_PDD.h the syntax I am following is correct. But still it shows error 😦

        Like

      • Dear Erich, In continuation with the previous reply, the wrong was on my part. Sorry. I forgot to read the first few lines of the code in PORT_PDD.h
        Only these controllers in Kinetis E series supports the statements.
        !defined(MCU_MKE02Z2) /* PORT */ && \
        !defined(MCU_MKE02Z4) /* PORT */ && \
        !defined(MCU_SKEAZN642) /* PORT */ && \
        !defined(MCU_MKE04Z1284) /* PORT */ && \
        !defined(MCU_MKE04Z4) /* PORT */ && \
        It says,
        #error encountered with text: PORT PDD library: No derivative is active. Place proper #include with PDD memory map before including PDD library.

        I couldn’t find anything with respect to this problem in reference manual too.

        1. Is there any header file other than #include PORT_PDD.h which will support this statements in my code.

        2. I configured the BL_SW (PTB1) as input in the processor component properties. So is it enough if we write code for enabling the Pull up ? (Though the code which configures PTB1 as input didn’t throw any error while building the project. I got the error only in the code statements pertaining to Pull up )

        Like

  14. Dear Erich,
    I promise this will be the last doubt I ll be troubling you with respect to Code. I have made few changes with regard to enabling Pull up and initializing Port Pin which didn’t result in error 🙂 . I want you to validate it. All my previous errors are cleared now, but I have got a new error on KIN software reset. I guess KE-02z is not supported by KIN.c 😦 . I have compiled my last doubts and screenshots in this link. Please take a look and help me .

    https://oscarganesh.wordpress.com/2016/04/22/probably-my-last-doubt-erich-as-for-as-code-is-concerned/

    Thanks Erich

    Like

  15. Dear Erich,
    Now the code is building fine. There is no errors thrown. But I have one doubt. Once the controller enters the Boot loader mode, what all it does ? Like when it enters application mode, it loads the srec application file for blinking the LED. Similarly when it enters the boot loader mode what it does ?

    Like

  16. Dear Erich,
    I flashed the Boot loader project into my board. It threw semihosting error. After that no code which am trying to run in the board is working. Not even a simple blinking of an LED code.
    https://oscarganesh.wordpress.com/2016/04/25/no-code-gets-executed-after-programming-the-board-with-my-boot-loader-project/
    Check this link. I have posted the errors I am getting. I am afraid my board got spoiled. Please help me like you always do.
    Thanks

    Like

      • Dear Erich, I don’t remember doing anything with regard to Vector Table.. All I have done is partitioning the flash. I did that as per the AN4775 document (Page number 9) available in the NXP site. Do you have any articles elucidating, how to configure the vector table?
        Thanks
        Ganesh

        Like

      • Hi Ganesh,
        I don’t have a specific tutorial/article about this topic.
        But your vector table for the bootloader (at 0x00000000) is different from the application vector table. You need to set the VTOR to point to the application vector table as I have done this in my bootloader.

        Erich

        Like

      • Hi Erich
        I can understand what is my problem from your reply but I don’t know how to to set the VTOR to point to the application vector table as I am new to this IDE and this controller. Can you give me more insights about this ?
        Thanks

        Like

      • Hi Erich,
        I have one doubt. In the Screenshot titled, “Boot loader Flash Area”, you have configured m_text (Memory area 2) with address 410 and size 3BF0. At the end of this article in the screenshot titled “Application Flash Area”, you have configured the m_text (Memory Area 2) with address 40C0 and size 1BF40. Have you over-written the m_text area from address 410 to 40C0 and size from 3BF0 to 1BF40.. I am confused here.. Have you over-written that or is it separate memory areas for boot loader and application. If its separate, how is it done ?
        Thanks
        G.Ram

        Like

  17. Hi Erich,
    I am trying to implement this on FRDM-K22F. I am using FAT FS to read the executable from the SD Card. The problem I am facing is as below.

    CPU MK22FN512VLH12 has no option to set the code that should be called before the PE_Initialization is called? Any alternative for this?

    Like

    • Hi Vishal,
      So you want to do a bootloader which uses a file from the SD card?
      In that case, you only need to check if you want to enter bootloader mode inside PE_Initialization. Then proceed to the bootloader main and load the file from the bootloader application code.

      I hope this helps,
      Erich

      Like

  18. Hi Erich,

    What else should I do to make a Kinetis SDK project run with this bootloader? I had 100% success using PE projects and following all the above steps from this post, but failed on trying to upload KSDK projects… Tips, related posts, and why not, the complete solution are very much appreciated!

    Thanks in advance.
    William

    Like

    • Hi William,
      is your problem that the bootloader works, but you cannot load KSDK projects? I don’t see any reason why it would not work for SDK projects? But you need to make sure that the SDK project is using a different vector table location than the the one of the bootloader (at address zero).
      I hope this helps,
      Erich

      Like

      • I adapted this bootloader project for a FRDM-K64F, and I am sure the problem is not the modifications itself. I’m going to try to explain what I did so far to make it work.

        1) Adapted the project for FRDM-K64F using pretty much the same steps from this post, but changing UART pins and the defines
        MIN_APP_FLASH_ADDRESS to 0x8000;
        MAX_APP_FLASH_ADDRESS to 0xFFFFF;
        APP_FLASH_VECTOR_START to 0x8000;
        APP_FLASH_VECTOR_SIZE to 0x400.
        These values are like that due to the minimal erasable region of K64 which has a size of 0x8000.

        2) Created a simple blink led KSDK project following instructions from this link (https://community.freescale.com/docs/DOC-103429);

        3) Changed the RAM/ROM areas as shown in the image below:

        4) As i didn’t find the checkbox for “Flash Configuration Field” in CPU->properties, I opened the file startup_MK64F12.s and erased the lines where was written the following:
        /* Flash Configuration */
        .section .FlashConfig, “a”
        .long 0xFFFFFFFF
        .long 0xFFFFFFFF
        .long 0xFFFFFFFF
        .long 0xFFFFFFFE
        (Procedure suggested as shown in page 12 of this document: https://community.freescale.com/servlet/JiveServlet/download/256669-1-307644/How%20to%20adapt%20KDS%20applications%20for%20KBOOT.pdf)

        5) Generated the .S19 file, downloaded to the board and right after jumping to the application address, nothing else happens…

        I believe I’m quite close to the solution and there is a little detail that I didn’t get yet. Also, there was a strange behavior in this project because I couldn’t debug it properly. KDS was unable to start debugging from the main function address, it didn’t even set the breakpoint in the beginning.

        So, what is the missing trick then?

        Like

      • Hi William,
        I don’t spot any obvious mistake. Did you run the bootloader with the debugger? You should see how it jumps into the application code. Maybe something is missing there?
        Erich

        Like

      • Well, after testing my adapted bootloader with a simple KSDK application, I have some conclusions:

        1) In fact, it is possible to run a KSDK project after the bootloader jump. The project I was testing is a simple blink led. But there is something very particular when I try to put extra code in my project. In this same working project, i just tried to put two toggling leds and the project was no longer able to run…

        2) Depending on the size of the S19 file, bootloader calls HardFault handler when it tries to record addresses at the end of the file…

        If you have a FRDM-K64F in hands, and would like to help me in this issue, the related project files are in the link below. Bootloader project opens in CW and Blink_test opens in KDS. Also, there is a small terminal that I made to rush flash progress where terminal waits ack message from bootloader to send the next line. So that it’s not needed to put a 1ms delay between bytes sent.

        https://www.dropbox.com/sh/58c24jor9rm5z9g/AABuLRNPF9NmRpsHGafxvo51a?dl=0

        Hope you can help me. Thanks in advance.
        William.

        Like

      • Hi William,
        I don’t have a K64F board with me (I’m travelling right now). I try to have a look at your files next week when I’m back in the office.

        Like

      • Hi William,
        finally I have found some time to look at your files, and I had taken with me a FRDM-K64F board while travelling. But when I tried your project, I see that you are using CodeWarrior, not KDS? I don’t have CodeWarrior installed on my machine right now as the notebook has been migrated to Windows 10. It will take me some more time to try this out on CodeWarrior.

        Like

      • Hi William,
        I just see that your bootloader project is set up to a RAM target by default? Is this really the case for you on CodeWarrior (I loaded it into KDS).
        Erich

        Like

      • Hi Erich!

        If I knew you would discontinue using codewarrior for your projects, i would have migrated the whole BL project to KDS, but I just adapted the project available on your GItHub. Anyway, about the question, in CW the project apparently appears to be set up to flash target. This is what i see…

        And please, tell me if it would be better for you to migrate this project to KDS. I can make it quickly.

        Like

      • I still have a few CodeWarrior projects, but they are for maintenance only. I have moved my ARM development to GNU and KDS nearly completely. So if you have that project for KDS, that would be easier for me for sure.
        Erich

        Like

    • Hi Erich,

      I Just finished porting bootloader project to KDS, but things are getting worse…
      The previous working blink leds that I put together in my dropbox folder (blink_test) is no longer running after loading srec file, and another project without ksdk (blink_test_no_ksdk) generates a srec file which is calling the hardfault handler during flash process. I believe the bootloader is well ported to KDS, you can check that out too.

      Just waiting for good (or bad) news!

      Like

      • Ok Erich. Just checked your modifications. I wasn’t having problems on bootloader sequence, but i’ll follow your changes.

        I see that our friend Nate is facing the same problems. Well, let’s wait and see what can be done.

        Thank you!

        Like

      • I got it nearly working. I face hard faults if the flash block address is not 8byte aligned. I have it ‘fixed’ in the S19 file for now, but I need to check what the exact problem is. If the flash blocks in the S19 file are 8byte aligned, no problem.
        I have it running with the Terminal.exe as in the blog post, as your terminal program crashes on my machine.

        Like

      • Nice to know that. I Suspected it could be the addresses misaligned, but I couldn’t know why. Do you know what is the reason for the tool to generate the S19 file like that? It is going to need a workaround in bootloader code to deal with it.

        Like

      • Oh God, you had the solution for all these problems in this post…

        https://mcuoneclipse.com/2015/09/23/aligning-s19-records-to-64-bit-boundaries/

        I’m so sorry for taking your time. If i knew it could be specifically related to the s19 file, I wouldn’t ask you so many question, and even asked you to see any projects. Now, that K64F bootloader project you commited needs a workaround to make misaligned s19 files work. If you still don’t have time to work on “third-parties” projects, i’ll try to submit a fix.

        Thank you very much for everything!

        P.S.: As i wrote that little terminal only for myself, i didn’t test it in other machines, but it’s very useful for large s19 files. So i’m gonna test it in other computers and OS to track bugs and exceptions.

        Like

      • Ah, you already found it 🙂
        I admit that there could be more diagnostic information in the bootloader about failure points like this (I just added one additional one on the project on GitHub). I have used that way of bootloader for some slow OTA (over the air) updates where slow connection is not a problem (or a fact). What is not ideal right now that it flashes for every S19 line: having longer S19 files helps to avoid that. But I might consider to extend the bootloader to use a larger RAM buffer (e.g. 4 or 8 KByte). Will see if I can find time for this.

        Like

      • Hi William,
        I have now extended the K64F project on GitHub with buffer handling, and it works that way fine (at least with my preliminary tests). I only have found that using the Segger USB CDC firmware was loosing some characters. Switching to the P&E OpenSDA firmware solved that problem.
        I have added a blinky test program on GitHub in that K64F folder too.

        Like

  19. Hi Erich,
    I have one doubt. In the Screenshot titled, “Boot loader Flash Area”, you have configured m_text (Memory area 2) with address 410 and size 3BF0. At the end of this article in the screenshot titled “Application Flash Area”, you have configured the m_text (Memory Area 2) with address 40C0 and size 1BF40. Have you over-written the m_text area from address 410 to 40C0 and size from 3BF0 to 1BF40.. I am confused here.. Have you over-written that or is it separate memory areas for boot loader and application. If its separate, how is it done ?
    Thanks
    G.Ram

    Like

    • I have reduced the m_text area to the size of 0x3FB0. This is only to make sure that the application flash area starting at 0x4000 is not occupied by the bootloader.

      Like

      • Dear Erich,
        My doubt was, At the beginning of the project, m_text area parameters are address 410 and size 3BF0 , at the end of the project m_text area parameters are address 40C0 and size 1BF40.
        From your reply I understand like this.
        So just for protecting the 4KB flash you are configuring m_text parameters to be 410 & 3BF0. Once the flash area for boot loader code is protected. You are allocating memory for application code (which is 40C0 + 1BF40) right ?
        Thanks
        G.Ram

        Like

      • Hi Ganesh,
        you really need to hook up a scope/logic analyzer to your Rx and Tx lines and check them. The numbers in the terminal program won’t help you much if anything at all.
        Erich

        Like

      • Hi Ganesh,
        you need to put your application where you have specified it in your bootloader: so if your bootloader fits below 0x1000 and you have specified that your application shall be at 0x1000, then that’s ok. But I think your bootloader might be something larger than 4096 bytes, so you need to adjust the memory range accordingly.

        Like

      • Dear Erich,
        I forgot that my serial connection is RS 485. So I need to toggle it everytime I send and receive (Half Duplex).
        For Rx
        GPIO_PDD_ClearPortDataOutputMask(GPIOA_BASE_PTR, GPIO_PDD_PIN_21);
        For Tx
        GPIO_PDD_SetPortDataOutputMask(GPIOA_BASE_PTR, GPIO_PDD_PIN_21);

        In which all places of the code should I include these lines Erich ?
        And in terminal, since there is no RS 232 involved, is it enough If Xon/Xoff handshaking alone is selected ?

        Like

      • Hi Ganesh,
        I have not used half duplex, so I guess you have to do this somewhere in the communication layer.
        As for Xon/Xoff: I had mixed sucess with this, and it did not work well for me.
        Better to slow down the data traffic.
        Erich

        Like

      • Hey Ganesh,
        Hi Erich Sir,
        I am also using a half duplex connection only. I tried this code and got desired results

        for(;;) { GPIO_PDD_TogglePortDataOutputMask(GPIOA_BASE_PTR, GPIO_PDD_PIN_21);
        CLS1_SendStr(“Hello World!\r\n”, CLS1_GetStdio()->stdOut);
        WAIT1_Waitms(1000);
        CLS1_SendStr(“Welcome Bala!\r\n”, CLS1_GetStdio()->stdOut);
        }

        But I am unsuccessful when I try this code. It builds without any errors. It gets debugged inside the board without any errors. But when I press the Resume button, there is nothing in the Terminal Application.

        static void ReadText(void) {
        uint8_t buffer[32], ch, i;
        for(;;) {
        GPIO_PDD_TogglePortDataOutputMask(GPIOA_BASE_PTR, GPIO_PDD_PIN_21);
        CLS1_SendStr(“Enter some text: “, CLS1_GetStdio()->stdOut);
        buffer[0] = ‘\0′;
        i = 0;
        do {
        if (CLS1_KeyPressed()) {
        GPIO_PDD_TogglePortDataOutputMask(GPIOA_BASE_PTR, GPIO_PDD_PIN_21);
        CLS1_ReadChar(&ch); /* read the character */
        if (ch!=’\0’) { /* received a character */
        buffer[i++] = ch; /* store in buffer */
        if (i>=sizeof(buffer)) { /* reached end of buffer? */
        buffer[i] = ‘\0′; /* terminate string */
        break; /* leave loop */
        }
        if (ch==’\n’) { /* line end? */
        buffer[i] = ‘\0’; /* terminate string */
        break; /* leave loop */
        }
        }
        }
        } while(1);
        GPIO_PDD_TogglePortDataOutputMask(GPIOA_BASE_PTR, GPIO_PDD_PIN_21);
        CLS1_SendStr(“You entered: “, CLS1_GetStdio()->stdOut);
        CLS1_SendStr(buffer, CLS1_GetStdio()->stdOut);
        CLS1_SendStr(“\r\n”, CLS1_GetStdio()->stdOut);
        }
        int main(void)
        {
        PE_low_level_init();
        }

        Did you have any success Ganesh ?
        Erich, do you have any suggestion for this ?
        Thanks Ganesh and Sir
        Looking forward to your replies sirs.
        Bala

        Like

  20. Hi sir,
    This is Bala. This article serves as the bible for a beginner who tries to design a boot loader. Kudos to your effort. I have few doubts sir. I am interested in designing boot loader for a Freescale’s KE-02Z controller.
    1. Can this code be run in win_hc08sprog (https://community.freescale.com/thread/311041) ?
    2. Will the same logic work if I use a switch instead of a push button as BTLD button ?
    Thanks sir.
    Looking forward to hear from you
    Bala

    Like

    • Hi Bala,
      1. the win_hcs08prog is using a custom protocol, so you have to have this application running on the host. That’s exactly the reason why I wrote that serial bootloader which only needs a terminal program, and not a special application on the host. Bottom line: you cannot use the win_hcs08sprog for this bootloader.
      2. the same logic works for any microcontroller, and any means of way to entering the bootloader. It can be any push button or pin, or any other way to signal to the bootloader that it needs to enter the bootloader mode.

      I hope this helps,
      Erich

      Liked by 1 person

      • Hi Sir,
        Thanks a lot for your reply. Sir My last doubt. There is no main.c file in your project in GITHUB. With all due respect, How will the code run without a main() function ?
        Correct me if am wrong, because I have never seen a code without main() function.
        Thanks Sir
        Looking forward to your reply sir
        Bala

        Like

      • Hey Sir,
        Sorry I thought it is some Processor Expert generated file. I am very sorry. My Boot loader code should be within 0x0000 to 0x1000 that is 4KB, But My Boot loader code size is
        text data bss dec hex filename
        8112 36 4068 12216 2fb8 Bootloader.elf
        EVEN AFTER ENABLING THE OPTIMIZATION OPTION IN TOOL SETTINGS.
        I am using KDS version 2. Can I reduce the code to less than 4KB. ? 😦
        Thanks sir.
        Looking forward for your reply sir.
        Bala

        Like

      • Hi Bala,
        well, reducing the from 8K to 4K for sure is not a simple thing. You would have to cut off features and functions to get there.
        For example you would have to write your own flash programming library. That should reduce your code size. Or use a very minimal startup code.
        Have a look at the linker .map file what is using the most space in your bootloader and try to optimize it.

        Like

      • Hi Sir,
        I am just a beginner. So I don’t know if I can write my own flash programming library, or can modify my startup code. The only idea which I currently have in my mind is to change the boot loader memory allocation. At present I am trying to keep my boot loader code within 0x0000 to 0x1000 (4KB), I have to modify it to, 0x0000 to 0x2000 (8KB). And yea, again I have to change all the application code memory area.
        Correct me if I am wrong sir.
        Thanks alot sir.
        Bala

        Like

  21. Hello Erich, I’ve been doing work on a serial bootloader for a K64F board, using a few lines out of your example, in this case,
    startup = ((uint32_t*)APP_FLASH_VECTOR_START)[1]; and
    ((void(*)(void))startup)();
    I have ran into some strange issues, for instance, after loading the file and verifying all checksums for validity, the code is ran and immediately jumps to the unhandled interrupt breakpoint, 0xFF. this seems strange in that I don’t use the boot-loader, and instead run with the interrupt vector at 0x0000000, i do not encounter any errors. it only happens after changing the “to be loaded” codes interrupt vector up and attempting to load it. Any thoughts on what could be causing my issue? i did attempt to relocate the vector table with SCB_VTOR= (uint32_t)0x40000; at the address i store the “to be loaded” code, but I do not know if i did it correctly. For reference I have the vector start defined as this
    #define APP_FLASH_VECTOR_START 0x40000

    -Thanks for the help
    Nate Hinshaw

    Like

      • Through further testing, i can tell that the application im loading in gets to the end of the while loop that contains its main running actions. Once it gets there, it seems to ignore that the loop is a while(1), and ends the loop, followed by the unhandled interrupt. is there something else that I need to do to properly jump to my application?

        Like

      • No, nothing special needed. Could it be that it is not the code running you are debugging? I would check and step the assembly code if it makes sense.

        Like

  22. I fixed the issue I was previously having by making a new project with mostly the same code in it. I did overhaul the reading in of S19 files, but that was mostly to add a handshake between my flashing program and the board, with an echo back once the flash task was complete. Thanks for the help Erich, Your blog has been incredibly helpful

    Like

  23. I am now running into the same hard fault, but for code that shouldn’t be causing a crash.

    Flashing
    S30D000457EC000000000114000096
    followed by
    S329000457F4EC57040000A0002008000000F45704000005FF1F0000000000000000000000000000000006
    causes a hard fault on the side of the boot-loader. Memory maps are attached.
    working memory map http://dumptext.com/ltPfs83q
    hard fault memory map http://dumptext.com/MS9S6jM4

    Those locations in memory appear to be for the __Data_ROM and the __m_data_1FFF0000_ROMStart locations

    Is there something I am unfamiliar with that is causing this issue? Any help you could give would be greatly appreciated

    Like

  24. Hi Erich,

    Is there a way to debug the application (with the relocated vector table, etc) when a bootloader isn’t present? Say my application starts from address 0x8000, how can I get KDS to debug the application?

    Thanks, Kevin

    Like

    • Hi Kevin,
      It depends where your vector table is. Out of reset, it is at address 0x0000’0000. Are you saying that your application vector table is at 0x0000’8000? As for debugging, it all depends if your debug symbols are loaded in the debugger, and if they are at the right place/address of your code. I have not used relocatable code (yet) (if this is what you are asking for?).
      I hope this helps,
      Erich

      Like

  25. Hello Eric sir,
    I am using FRDM k64f board, I have configured project as the above blog.
    But I am getting address 0x00(dword addr == 0) in following function:-

    static bool BL_ValidAppAddress(dword addr) {
    return ((addr>=MIN_APP_FLASH_ADDRESS) && (addr failed errors ….

    May I know the exact values of address and size to be write in RAM/ROM area in Build option section….

    I also downloaded the project from github…. and tested but no success…

    Thank you…
    Kishan

    Like

    • Hi Kishan,
      if you get an address of zero in your application, then it probably means you have the vector table at address zero? This won’t work as the bootloader vector table is at that location, that’s why BL_ValidAppAdddress() is used to check this. You need to move your application vector table to the valid range. Have a look at the project in https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/CodeWarrior/FRDM-KL25Z/BL_Blink (but this is for CodeWarrior, btw).

      Like

      • Hello sir,
        I am sorry that may be I am talking rubbish…. but how do I make vector table address to 0x4000

        and second thing at starting in BL_CheckForUserApp(); function
        if (startup!=-1 && !BL_CheckBootloaderMode()) function… this step is skipped by my controller while debugging….
        as
        /*(startup = 0xffffffff)
        APP_FLASH_VECTOR_START = 0x40000*/

        void BL_CheckForUserApp(void) {
        uint32_t startup; /* assuming 32bit function pointers */

        startup = ((uint32_t*)APP_FLASH_VECTOR_START)[1]; /* this is the reset vector (__startup function) */

        /* at this stage startup becomes = 0xffffffff */

        if (startup!=-1 && !BL_CheckBootloaderMode()) { /* we do have a valid application vector? -1/0xfffffff would mean flash erased */
        ((void(*)(void))startup)(); /* Jump to application startup code */
        }
        }

        so controller is not checking weather BL_SW is pressed or not….

        Thank you…

        Like

      • Hi Kishan,
        have a look at the project link I have sent you: it is very easy that way and using Processor Expert, there is a setting in the CPU component.
        The second question is related to that: that code checks the presence of the relocated vector table plus checks if the application is in bootloader mode or not.

        Like

      • Hello sir Thanks for reply….:)

        Now Actually I am debugging the code as from your link given in github….
        But now I am getting address 0x400 instead of 0x40000…
        and at 0x400 it shows invalid flash address
        Invalid flash address: 1024!

        In mempry map from 0x400 to 0x410 is for Flash_config…
        I think controller try program from address 0x400…

        my config in program as follow..

        #define MIN_APP_FLASH_ADDRESS 0x40000 /* start of application flash area */ //0x40000
        #define MAX_APP_FLASH_ADDRESS 0x5FFFF /* end of application flash */

        #define APP_FLASH_VECTOR_START 0x40000 /* application vector table in flash *///0x40000
        #define APP_FLASH_VECTOR_SIZE 0x400 /* size of vector table */ // 0xc0

        In my application program memory map is from
        0x40000to0x40197 :- vector table adress and
        0x40198 to 0x5FFFF as flash address …

        What to do for address 0x40000…???
        please make me correct if I am wrong anywhere…

        Sorry for any inconvenience….

        Thank you…
        Kishan..

        Like

      • Hello Eric Sir,

        I successfully uploaded s19 file via bootloader!!!…

        But in my case Process took very much time to upload BLINK s19 file (Around 5 minutes)….

        Is process is really slow or I am doing it wrong way……
        Settings on terminal is as shown in blog…. (only Baud rate is 115200)

        Also while uploading file before done message comes it will displays message as :

        Erase sector at 0x40000
        Program sector at 0x40000

        done
        CMD>.
        (Which is not in your blog images)

        After that BLINK program runs successfully….

        Thanking you….

        Like

    • Hello Erich Sir,

      Today I tried Kinetis bootloader files and I successfully run that boot loader using “freedom_bootloader.bin” binary file. It will give flash FSL bootloader at USB K64f-J22 connector on FRDM board.. By using “KinetisFlashTool” upload .bin file to controller. It is running successfully….

      Thanks for your help and your valuable time….!!!!

      Regards,
      Kishan

      Like

  26. Hi Erich, I’m attempting to pass the contents of a user application “bin” file over a serial port, 512 bytes at a time as part of a bootloader application. How can I use the IntFlash component and functions within this example to write these 512 byte blocks to flash? Is there a device-specific requirement as to the size of the blocks I can write all at once? I have all the code in which captures these 512 bytes of data, I’m just unsure of how to write them to flash. Thanks.

    Like

  27. Is there any way to specify the endian-ness of the bytes loaded into the FTFL registers? For example, I’m writing my user program to flash as a bin file – when I come to jump to the user application, the bytes are reversed from the contents of the bin file.

    Like

    • Ok, thanks for confirming. I thought there may have been an option within the component to specify endianness – however having had some sleep, I’ve since discovered that this isn’t the issue. The issue is that occasionally, when the bin file is created, the values from location 0x10000 are all zero and I think it is to do with my linker configuration. Sometimes this is not the case but mostly, it is.

      Like

      • I’ve since realised that when I change the location of the m_interrupts section and the m_text sections (to 0x10000 and 0x10410 respectively) that the m_cfmprotrom location doesn’t change when the linker file is regenerated by PE. If I disable the re-generation of the linker file and then manually change the m_cfmprotrom location to 0x10400 then rebuild the application, the resulting bin file no longer contains data for addresses 0x00 to 0xFFFF, just data for 0x10000 onwards whereas before I changed the m_cfmprotrom I was getting everything including zeros in the SP and PC locations.

        Like

  28. Hi Erich, I’ve now managed to get past all of the hurdles and can actually program a “bin” file in – correctly – over USB CDC. However – and its an annoying however. When I step through my bootloader to the point where it comes to jump to the user application address at location 0x10004 (I can confirm that the location contained at this address is 0x11FF1 (__thumb_startup) from my user application map file), execution shoots off to some random location. If I run the user application in the debugger though, it executes as expected from the same address (if I breakpoint on __thumb_startup). Any suggestions as to what could be going on? Thanks

    Like

      • Hi Erich, I didn’t actually try with assembly stepping. I just checked that the address loaded into the “jump” variable was of the correct location (which it was) and just jumped – I can check using this method though. One thing that’s been on my mind is interrupts – I don’t actually disable them before I jump so I’m wondering whether this is causing an issue, especially if the interrupt table is overwritten while interrupts are enabled.

        Like

      • Yes, good point: for the interrupts, the vector table has to be valid. So you should disable the interrupts before jumping to the new startup code.
        As long as the vector table is fine, you should not see any issue. But it would be good to disable interrupts before jumping to the new startup code (actually they should be already disabled in the bootloader startup code, right?)
        I would really do assembly stepping into the jump code to see what is going on.

        Like

      • Interrupts are enabled for a few peripherals in the bootloader (like the USB interrupt, I2C interrupt). I do want to relocate my vector table in user application space so I’m hopeful that an interrupt is causing this weird behaviour otherwise I’m completely at a loss. I’ll try the assembly stepping after I’ve disabled the interrupts. Thanks for your help

        Like

      • I’ve just checked the assembly in the instruction stepping and my jump is done via a “ldr r3, [r7, #4]” and “blx r3” which loads the correct address into r3 and successfully jumps to it. One thing I’m struggling with now is interrupts in user application space. For example, using the GenericI2C component gets stuck on the “while (!GI2C1_deviceData.dataTransmittedFlag);” so its clear that the I2C interrupt isn’t being fired. Previously when working with bootloaders in IAR, I just performed a jump to the user application and then interrupts, etc, just worked.

        Like

      • The Cpu.c takes care of the vector table relocation and I’ve checked (by breakpointing) that when SCB->VTOR is re-assigned, that it points to the correct location and I’ve also checked that the I2C ISR is pointing to the right place in user application space. I’m baffled!

        Like

      • In both, but this depends on the stage of each. During startup of the bootloader, interrupts shall be disabled.
        Then they can be enabled during loading the image. But when jumping to the target application, I do disable them so the application startup code runs with interrupt disabled. The application startup code then will enable the interrupts (for the application).

        Like

      • In the bootloader, interrupts are enabled so that the I2C interrupt can fire (an i2c device is polled during the bootloader sequence). Prior to jumping to the application, I need to disable global interrupts or odd things happen when trying to jump and jumping is unsuccessful. When in the user application, I re-enable interrupts (__asm(“CPSIE i”) following PE_low_level_init but I never see the I2C interrupt fire (breakpoint is never reached in the ISR)

        Like

      • Hi Kevin,
        after PE_Low_Level_Init(), are interrupts enabled? If not using an RTOS, they should be enabled at that point. If using an RTOS, they get enabled when you start the scheduler.

        Like

      • Hi Erich, straight after PE_low_level_init I’m calling __asm(“CPSIE i”) to enable interrupts

        Like

      • I suggest that you check with the debugger if the I bit in the PRIMASK is really cleared when you halt the user application.
        If it the I bit is cleared, then it could be that maybe the interrupts for the I2C are not enabled?

        Like

      • I’ve taken everything back to basics and also removed the PE element of the application. My bootloader is now a small application which uses the SysTick interrupt to toggle an LED. After 10 seconds, a jump is attempted to a user application. When the bootloader starts, I enable interrupts and just before the jump, I disable them. In the user application, I again use the SysTick timer to toggle the same LED but I change the tick period so the LED flashes faster. As soon as the user app is entered, I can see PRIMASK is “1” and when I re-enable interrupts, it goes back to “0” – all this seems to work perfectly so I need to go back through my original code and try to figure out what I’m missing. I need to also try to get another interrupt working so I might try using the PIT timer in my user app.

        Like

  29. Ok, I’m getting closer (I think). If I don’t enable interrupts in my main application but instead, if I step over the PE_low_level_init function and then, in the “registers” view, change PRIMASK from 0x1 to 0x0 and it run, the Cpu_ivINT_FTM1() interrupt is then hit and a breakpoint is triggered. However, the CPU is in the middle of a GI2C1_ReadAddress call so I’m figuring that the SCB->VTOR is not correctly aligned. Looking at the SCB->VTOR address, it is sat at 0x10000 which as expected so unless there is some serious alignment issue going on,

    Like

    • And if I don’t relocate my vector table in the linker config file (keeping it at 0x0000) then when I re-program, everything works perfectly.

      Like

      • Then I think something is wrong with that vector table? Can you try to have a 1-to-1 copy of your vector table from 0x0000 at 0x10000 (where you relocate it?).

        Like

    • So your PE_low_level_init() indeed enables interrupts at the end of that function. Is that what you intended? The VTOR must be aligned to a 1K or 4K boundary (I think), so this seems to be the case. Are you sure you have that relocated vector table correctly set up with all the entries, including initial PC and SP?

      Like

      • Hi Erich, problem solved. Vector table was correct and aligned properly, SP and PC were fine – the problem was me (as always). One interrupt was still enabled from the bootloader (funnily enough, it was FTM1) and now I’ve disabled it before the jump, everything works (everything, EVERYTHING :)). Thanks for all your help and sorry for my stupid questions :/

        Like

  30. Hello, Erich

    I tried to use your bootloader in FRDM-KL25Z, but it didn’t work. I realocated the memory in CPU bean Build Options, but I have not been successful to load my .s19 file. I don’t if this can be a problem, but as CodeWarrior keeps the Flash image file extension in .hex and only changes the contents to look like a .s19 file, I created a copy of .hex and just renamed the extension to “.s19”.
    Anyway, I tried with both files, and it failed with both.
    After loading “BL load s19”, it prints out:
    “Erasing application flash blocks done!”
    “Waiting for the s19 file”
    Then, I click on “Send File”, pointing to my .s19 file path and that’s what I receive back on the Terminal:
    “S0 address 0x00000000ERROR!”
    “Failed at address 0x00000400”
    “failed”
    “Erasing application falsh blocks…done!”
    “***Failed or unknown command: BL load s19”
    “***Type help to get a lista of available commands”
    “COM>***Failed or unknown command: S1134000003000209D480000C545000”

    And this repeats for all the .s19 file lines.

    My button is connected to PTD6. I changed this in Bootloader “Bit_IO” component.

    Can you help us please?

    Like

    • Hello Marco,
      at the address 0x400 there is the flash configuration of the bootloader itself: your application S19 file shall not have such a configuration in it: you need to build your application to be loaded without the flash configuration.

      Like

  31. Ok. Now I understand that I have to use objcopy command for generating .s19 file acordingly, but I still don´t understand how to use this in CodeWarrior. Your tutorial explains how to do it in Eclipse Keppler. I tried it in CodeWarrior, but it didn’t work.

    Like

    • Hi Marco,
      actually, this tutorial was written originally for CodeWarrior :-). Have a look at the BL_Blink project (https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/CodeWarrior/FRDM-KL25Z/BL_Blink) which creates such the S19 file. It uses the objcopy to generate the S19 file. For disabling the flash configuration, have a look in that project at the CPU component (Internal Peripherals > Flash Configuration Field : Disabled).
      I hope this helps,
      Erich

      Like

      • Hi, Erich

        I don’t remember seeing a note about this Flash Configuration Field setting on this tutorial and realize now this is a default setting in CPU bean. This setting was crucial to have the bootloader recognizing my .s19 file and programming the MCU correctly.

        Actually, “objcopy command” was not necessary to convert .hex extension of Flash image file into .s19. I just used .hex file generated by Codewarrior (actually formatted in .srec standard) and did not even rename it. And everything is running perfectly now!

        Thank you very much for your help!

        Like

      • Hi Marco,
        I appologize, indeed I had not pointed that out in a very visible way, because I thought that this might be obvious, so I was wrong about this. Thanks for asking that question, so hopefully everyone else bumping into this will be able to read this now.
        Thanks again!

        Like

  32. Hi, Erich

    I’m trying to convert your FRDM-KL25Z bootloader into a FRDM-K22F bootloader for KDS. I could successfully move all the PE components settings from CW to KDS ( and just changed CPU to K22 and the pins used for led and button), as well as the additional files. No build errors. Now I face a new problem: KDS doesn’t have a configuration in CPU component that allows me to add user code before PE initialization. Do you know how can I do this in KDS?

    Thank you very much!

    Like

    • I found out, Erich! In “startup.c” file, there is a function called “__init_user” that is reserved for user code and it is called before Processor Expert initialization. It is up and running now!

      Like

  33. Hello, Erich

    We managed to convert your code to KDS for MK22FN512 (in other words to FRDM-K22F) and it worked! Now we are trying to convert your code for MK22FN1M0. We carefully followed the same steps as we did for MK22FN512, but after several attempts, we still couldn’t successfully load our code with the bootloader.

    We created a simpler code to ease the tests like toggle a port connected to a buzzer. The bootloader logs down all the .srec lines and tell us the programming is successful, but as we put it to run, it doesn’t work.

    We really don’t know where is the problem. I know it might be difficult to guess what is causing our failure, without our hardware and firmware. Could we send you our bootloader firmware so you can take a quick look on it? Maybe you can find something wrong that we’ve missed.

    Thanks and best regards,

    Marco Coelho

    Like

  34. Hello, Erich

    Actually, we had to change some definitions in “Bootloader.c” file regarding application’s Flash address range, Vector Table size, Erasable Unit Size, etc. The other settings are automatically regenerated by IntFlash bean and the other beans. The least we can erase in MK22FN1M0 are 32768 bytes blocks. So, we protect the first block from 0 to 0x7FFF. So, we allocate our application from 0x8000 on.

    As we enter bootloader, we can load our application’s .srec file with no flaws (at least, no errors come up). After bootloader loads our .srec into Flash, we enter “BL status” command and can see that Flash range is correct and contents in 0x8000 are different from 0xFFFFFFFF, which signals something was programmed there.

    Then, we enter BL restart command. Our application doesn’t run and bootloader itself dies. So, we can suppose that something corrupts all Flash memory and we lose everything, as bootloader jumps to the application.

    Any idea?

    Thanks and best regards,

    Marco Coelho

    Like

      • Is it possible to have access to application source code after bootloader jumps to it in debugger? How can we do this? It is weird that Flash bootloader area was also corrupted, although it was entirely protected against erase and programming (0 – 0x7FFF).

        Like

      • Hello, Erich

        We ran the bootloader with the debugger. The srec file loading was successful. But, if we enter “BL restart” command or do a power recycle (turn off and on the system), the application code doesn’t run. If we put a breakpoint in “BL_CheckForUserApp” function in the line:

        ((void(*)(void))startup)(); /* Jump to application startup code */

        We can see the code gets there and jumps to our application. From this point on, debugger doesn’t allow us to run the code anymore, obviously because it can’t find application source code.

        It is as if, after it jumps to application’s Flash, it corrupts all Flash memory, because we also completely lose access to bootloader.

        Any idea?

        Like

      • Hi Marco,
        it seems to me that your microcontroller is turning on some security features out of reset, making that memory area not accessible somewhow? Can you simulate a ‘restart’ with the debugger while bootloading your file? I mean debug the bootloader, let it program the application file, and then instead going through the BL restart (which will trigger a real reset), set the PC in the debugger to your bootloader startup code and step through the code to enter the application code. At least to verify that after bootloading the application binary is fine. If this is the case, and if it does not work after a reset, then really I think some protection feature is turned on after reset. I faced this kind of things with CRC settings on another microcontroller: it was using a CRC which was verified out of reset: the debugger wrote that correct CRC with programming the bootloader. But after loading the binary, the CRC did not match. I had to turn off that ‘CRC checking during device boot’ in the microcontroller.
        I hope this helps,
        Erich

        Like

      • Hello, Erich

        We have already tried to execute “BL restart” command after loading our s19 file, and stepping through line by line from bootloder startup point to the point where it jumps to application code. It runs all the code perfectly.

        Regarding Flash security settings, we checked this out. Bootloader Flash area (0 – 0x7FFF) security is disabled and in the case of application’s Flash are, Flash Configuration Field is disabled.

        Now, I intend to try with FRDM-K64F, since MK64FN1M0 Flash memory is exactly the same as in MK22FN1M0.

        Anyway, thank you for the tips!

        Like

  35. Hello, Erich

    I just tried on FRDM-K64K, but it didn’t work either. Also, I disabled Handshaking option in Terminal, but it doesn’t change a thing.

    Like

  36. I found out the reason for the errors I commented before.

    In FRDM_K64F_Bootloader, in Boootloder.c, memory settings were like this:

    //#define MIN_APP_FLASH_ADDRESS 0x40000
    //#define MAX_APP_FLASH_ADDRESS 0x5FFFF
    //#define APP_FLASH_VECTOR_START 0x40000
    //#define APP_FLASH_VECTOR_SIZE 0xc0

    I corrected to the right values in order to match with FRDM-K64_Bootloader_Test Flash configuration:

    #define MIN_APP_FLASH_ADDRESS 0x8000
    #define MAX_APP_FLASH_ADDRESS 0xFFFFF
    #define APP_FLASH_VECTOR_START 0x8000
    #define APP_FLASH_VECTOR_SIZE 0x198

    After this adjustment, I put it to run and it loaded FRDM-K64_Bootloader_Test .srec file successfully, and as I entered “BL status” command, it shows me there is something inside application’s Flash memory:

    App Flash: 0x00008000..0x000FFFFF
    @0x00008000: 0x20030000 0x00008BA1

    But, if I try to jump to application, by entering “BL restart” or pressing reset button on Freedom, nothing happens.

    Like

    • Hi Marco,
      it is hard to tell me what could be wrong without a reproducible case. Have you tried with my original example and example bootloader application I have put on GitHub?
      And why did you have to change the APP_FLASH_VECTOR_SIZE?

      Like

      • Hello, Erich

        My previous comments were based on attempts with your original example and example bootloader application you have put on GitHub.

        Thanks!

        Like

      • Ok, Erich

        I recognize I set Vector Size wrongly. The right value is 0x400. I corrected it, but the it keeps not working. Maybe you can reproduce the same failure on your side.

        Like

      • Hi Marco,
        I’m sorry for not replying sooner, that thread was burried in my pile of emails :-(.
        I have checked the project again, and I have to admit that the memory range on GitHub was at 0x5000 instead of 0x8000 from another test. I have fixed that and pushed the change to GitHub (https://github.com/ErichStyger/mcuoneclipse/commit/9b4268baf38c3870013972caf3c126509b91df06), and now it works on my side.
        One thing to note is that I have sometimes problems with the Segger USB CDC implementation (it seems to loose characters), but it works properly with the P&E USB CDC and firmware on the FRDM-K64F board.
        I hope this helps,
        Erich

        Like

  37. Hi Erich

    I have just downloaded you latest mcuoneclipse_master package and tried again. The same problem: Terminal shows that bootloader apparently program the application into the MCU, but it doesn’t start the application after a reset. Besides, it messes up the Flash memory, because if you put the application to run, you don’t have access to bootloader anymore.

    Just to inform you that I used both FRDM-K64F_Bootloader and FRDM-K64F_Bootloader_Test for KDS from your package in my test, just the way they are. I didn’t change anything. I couldn’t catch the problem by debugging, it happens exactly at the time it jumps to application.

    Like

      • Ok, Erich

        It is good to know that you could finally reproduce the same problem as me.

        As soon as you solve this problem with your bootloader code and launch a new corrected version, please let me know.

        Best regards!

        Like

      • Hi Marco,
        I’m travelling right now, and I have ‘bricked’ my FRDM-K64F somehow and I need a Segger J-Link or P&E Multilink to regain access to the chip as OpenSDA fails, and I don’t have these with me. I have to check it when I’m back that the office next week, and of course I will report back my findings. Still scratching my head why this happens, as this was workign fine before 😦

        Like

      • Hello, Erich

        It is a coincidence! I also have bricked my FRDM-K64F after some attempts. I was in holidays during those two last weeks and didn’t have a Multilink or USBDM at home, but now I’m back to office and I can try to recover the kit.

        Like

      • Hi Marco,
        I was able to recover one board with the Segger J-Link. For the other I had to use the P&E Emergency Recover utility. I’m not clear yet what has caused the problem, I hope I can investigate it today or tomorrow.

        Like

      • Hi, Erich

        Good to hear that you were able to recover your boards. I was not that lucky on my side.

        I reprogrammed MK20 with MBED bootloader .s19 file that is available within your mcuoneclipse-master package and then I put FRDM-K64F into bootloader mode and reloaded it with P&E OpenSDA firmware again.

        I checked in Windows Control Panel and apparently OpenSDA is working perfectly. Then I made a chip detection test with USBDM kit and I got a message “ARM target failed to power up”. That smells bad! To me, it looks like MK64 got into Flash security mode permanently and I can’t have access to Flash anymore.

        Probably, I’ll have to replace the MK64 mounted in Freedom with a new one.

        That is the only FRDM-K64F I have here at this moment 😦

        Like

      • Hi Marco,
        I think more that the reset pin is somehow disabled.
        Try the P&E Kinetis Recovery Tool (I think you have a P&E Multilink?): http://www.pemicro.com/support/download_processor.cfm?type=5 (requires login/registration into P&E site).
        Have Segger or P&E (not mbed) firmware loaded on the K20 OpenSDA.
        Run that that tool with the debug probe attached to the K64F SWD header, you might need to power cycle the board several times until the reset LED remains red.
        Then download a ‘good’ application to the K64F using the K20 OpenSDA connection.
        That worked on my side.
        Good luck!

        Like

      • Should I power up the FRDM-K64F by OpenSDA port or the other (application) USB port?

        Like

      • It seems that is not my case, Erich

        I just run Kinetis Recovery Utility on my side with both Universal Multilink probe and USB cable connected to OpenSDA port.

        The tool shows that both were detected. The last message is that it is continuosly attempting to halt processor and asks me to power recycle my board until the operation is successful. Although I have pressed reset button several and several times, it remains the same, but LED doesn’t remain red as I release reset button.

        If I try to download an application to K64 with Multilink probe attached to K64 SWD header, it fails.

        So, I guess it really is a issue with K64 MCU Flash.

        Like

      • you need to power cycle (remove power/USB cable) and plug it in again. Pressing reset is not enough. What happens is that the P&E Multilink pulls the reset line low all the time you try to power cycle the board. In the hope that when the microcontroller comes up, it hits the tiny window to halt the CPU. I had cases where I needed to power cycle the board about 60-70 times.

        Like

      • Hi Marco,
        finally I spent some hours on that issue (which I still do not fully understand). For now I have disabled the interrupts/timer in the example projects, and now so far it is working. I have uploaded my S19 file as reference with the push here: https://github.com/ErichStyger/mcuoneclipse/commit/9fcf5640ea8ac4032b529ff4d7fdbb0ba2533cc7
        I suspect is that I see some strange caching problem after programming the flash memory: what I read in the application from flash (e.g. from the vector table) does not match what I read with the debugger. Strange.

        Like

      • Hi, Erich

        Thank you very much for your attention so far.

        It really is very strange and it requires deep investigation. It is insane to think that the timer could be preventing the bootloader from writing the firmware correctly into target MCU!

        I noticed that you made the following changes in Bootloader.c file:

        -#define MAX_APP_FLASH_ADDRESS 0x1FFFF /* end of application flash */
        +#define MAX_APP_FLASH_ADDRESS 0xAFFF /* end of application flash */

        Have you noticed any problem related to the end Flash application address?

        Thanks and best regards!

        Marco Coelho

        Like

  38. Pingback: “No source available”, or how to Debug Multiple Binaries with GDB and Eclipse | MCU on Eclipse

  39. Hi Erich,

    I´d like to know if the issue you were arguing with Marco Aurelio (porting the example to K64) was solved. In fact I´m the one who request that to him and originally I got the same problem but with a K22 (MK22FN1M0VLL12).

    Like

  40. I think probably must be something related to the flash region areas or its register and offsets on this architecture (1MB of flash), because both K22 and K64 we are using are very similar at this point and produce the same problem.

    If I had another Kinetis NXP development here I´d try with a 256k or 2MB Flash CPU, but unfortunately I don´t. Did you do that before?

    Like

      • Hi Erich,
        In my application I want to activate the bootloader with a RFID TAG.
        Because of the USB Stack, NFC Library I would like to use a Kinetis KL with min. 256kB Flash to have some buffer for the future. I use KDS3.2 and would like to use KSDK2x (Project just begins). I would like to use the example code for the MKL25 bootloader, but unfortunately I have not Codewarrior. I would like to adapt it to the KL27 with KSDK2.0. It would be great if you could help me, maybe you have a KDS Version of it?

        Thank you
        Jürgen

        Like

      • Hi Jürgen,
        there is a port of that project available for the K64f (https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/KDS/FRDM-K64F120M/FRDM_K64F_Bootloader), but I (and others) are facing strange problems with the flash programming on K64 and K22 (still not resolved). You might have a look at this project.
        As for using the SDK v2: keep in mind that this bootloader project is with Processor Expert, and the KSDK v2 does not support Processor Expert. So you could generate the code (say with the K64F project), but then you have to change it to work with the SDK V2 (e.g. providing your own flash programming code,etc).

        Like

  41. Hi Erich,

    Thank you for your reply. For me the most challenging is the massive source code overhead from NXP. I really prefer your solutions, they are simple and thought-out.
    THe KL27x has a ROM bootloader, but the reason why I think about a Flash based solution is, that there will be a point in the future, where I want to transfer the binaries AES128 encrypted.
    NPX provides the Kinestis bootloader in Version 2, which supports crypto transfer, unfortunately there are no code examples for the KL27x (designated for ROM Bootloader), but examples for the KL25 exists.
    The built in Bootloader of the KL27 series provides all necessary parts except crypto transfer. I think the hardware modifcations in firmware is easier to do from KL25 to KL27 as the one from K64 to KL27.
    I have seen that there are very much examples for the KL25 MCU. The hardware adaption for some KL25 projects to KL27 will be a first step for me, later I will do it with the NXP KL25 bootloader examples. I hope there are no massive errors hidden.

    If I wouldn’t need the Flash size to be future safe, I would use the KL25.
    Thank you

    Jürgen

    Like

  42. Hi Jürgen,

    Did you manage to port this demo to KL27 with Processor Expert? I (and Erich) didn´t in a 1MB of flash (K22 and K64 respectively). I mean, the project itself seems to work fine, but after booting it doesn´t run the application. I´d like to know if with a 256kB you will get the same problem.

    Like

    • Hi Erich,

      Thanks for sharing the information. In fact, for the K64F there is no HSRUN, but for the MK22FN1M0VLL12 there is. In that case what is the best clock settings (core, system, bus clock, etc.) to make this work?

      Like

      • I have not tried it with the MK22, but to my knowledge the HSRUN is clock configuration setting. So you could reduce the speed/change the settings for the bootloader so it does not use HSRUN? The application then later on can switch to HSRUN if needed, but the bootloader does not need to run at the highest speed.

        Like

  43. Erich, I was trying to port this demo to FRDM-K22 and everything was going well until I got stuck at this point: for the MK22FN512XXX12 I don´t have the “User Initialization” option on build options (Component options – CPU). Is there a way to activate it or something? I´m using KDS 3.2.0 for this job.

    Like

    • I solved this problem here, Marco Aurelio from Siletec help me and it´s all working now! From my porting (to FRDM-K22 and with KDS) I needed to call the BL_CheckForUserApp(); inside __init_user(void) function and include the “Bootloader.h” at the startup.c file. Do you want me to send you my project to you?

      Like

      • Ok, I´m doing that (putting the project to on GitHub) while I write this. I need to install GitHub yet…

        For my application I also need to expand this demo (Using a memory stick to load the appliation file (USB MSD Host)) and to do that can I ask you for some help? Like, where do I start? Do I need the FreeRTOS to read the s19 file? Finally, any tips for this job will be very helpful ; )

        Like

      • Hi Marcio,
        I would say that a USB MSD bootloader is probably not what you want. It puts a lot of dependency on the host (Windows, Linux, Mac, etc) and increases the size of the bootloader.
        But you don’t have to use an RTOS like FreeRTOS for this, although you could.
        Have you looked at the bootloader provided by NXP? Because my serial bootloader is really a simple and small one. If you are looking for more functionality, you probably better use the one provided by the NXP vendor.

        Erich

        Like

  44. Erich, what I want it to load the s19 file using your project example (Processor Expert feature) from a USB memory stick.

    Like

  45. I think I can create my own “BL_LoadS19” to Flash the memory, but I have some doubts about it (I`m newbie): It´s only flashing an array line by line from the decoded srec file? What care should I take? It´ is possible to encrypt to avoid flashing from a spurios source?

    Regards,

    Márcio.

    Like

    • Hi Marcio,
      while the S19 files is read in line-by-line, the loader is using a buffer to collect multiple lines and then program them all together for a flash page.
      And yes, you can encrypt the file or secure it in any way you want. Just be aware that this will require extra computation power and RAM/FLASH space.

      Like

  46. Pingback: Getting Started: ROM Bootloader on the NXP FRDM-KL03Z Board | MCU on Eclipse

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s