While working on a bootloader for a Kinetis KE06 I obviously ran in to the task of having to write the internal flash memory of the microcontroller. Freescale's driver is over 1500 lines of code, exposes every single bit of the flash controller so the simple operation of erasing a sector and writing to it requires many function calls. I wrote my own driver that is less than 200 lines of code and has everything needed to make a bootloader.
To implement a bootloader (or any kind of permanent storage) basically two functions are required - write data and erase sector (the smallest "chunk" of flash that can be individually erased). Why there is no read operation? Because on all ARM microcontrollers flash is mapped to main memory space so reading is simply a pointer dereference.
For example: to read something from address 0x500 you could write:
The driver has just 3 public functions and requires very little configuration. First flash_init() has to be called. It initializes the flash controller. This function requires a proper FCLKDIV value that depends on clock speed of the MCU. If it is too low or too high the chip can be permanently damaged! Check the reference manual for exact values.
All function calls are blocking, ie. don't return until the flash controller is done. Thanks to its architecture Cortex-M can execute code from any part of the address space. Usually it is the flash sometimes execution from RAM is helpful. How can the CPU execute code from flash memory while the flash controller is busy with something? It can't! This leads to some serious implications - while flash is being updated or erased - the CPU can not execute code from it. The exact behavior depends on the microcontroller. Fortunately the Kinetis E has a "stalling" function and can simply halt while flash is busy. This is enabled in flash_execute_cmd. Of course the CPU will not process interrupts or do anything else at that time. It is not a problem for a bootloader but may be a problem if using the flash for configuration storage of the main application.
Another option of the driver is FLASH_APPLICATION_BASE. This defines the lowest address that the driver is allowed to erase. Usually the bootloader is placed at the beginning of flash memory and is executed first by the MCU. The bootloader later starts the application. If the bootloader is damaged, then the device is bricked. This option prevents such problems.
1 2 3 4 5 6 7 8 91011
#pragma once#include <stdint.h>voidflash_init(void);voidflash_erase_sector(uint32_taddress);voidflash_write(uint32_ttarget_address,constuint32_t*data,uint32_tlength_words);#define FLASH_SECTOR_SIZE 512#define FLASH_WRITE_WORD_SIZE_BYTES 8#define FLASH_APPLICATION_BASE 20480 //first 20KB of flash is occupied by the bootloader