From e2c42bb0a0fcade69d7d087a89b41bc9798eb9c0 Mon Sep 17 00:00:00 2001 From: Chris Snow Date: Fri, 22 Sep 2017 11:30:43 +0100 Subject: [PATCH] LPC1768 IAP Fix (#4993) use IAP routines for the flash HAL implementation --- .../TARGET_LPC176X/device/flash_api.c | 190 ++++++++++++++---- targets/TARGET_NXP/TARGET_LPC176X/objects.h | 4 + targets/targets.json | 8 +- 3 files changed, 160 insertions(+), 42 deletions(-) diff --git a/targets/TARGET_NXP/TARGET_LPC176X/device/flash_api.c b/targets/TARGET_NXP/TARGET_LPC176X/device/flash_api.c index 0b140350bf..40e72a92f3 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/device/flash_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/device/flash_api.c @@ -13,55 +13,169 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#if DEVICE_FLASH +#include "mbed_critical.h" #include "flash_api.h" -#include "platform/mbed_critical.h" +#include "mbed_assert.h" +#include "cmsis.h" +#include +#include -// This file is automatically generated +#define MEMMAP (*((volatile unsigned long *) 0x400FC040)) -#if DEVICE_FLASH +#define PLL0CON (*((volatile unsigned long *) 0x400FC080)) +#define PLL0CFG (*((volatile unsigned long *) 0x400FC084)) +#define PLL0STAT (*((volatile unsigned long *) 0x400FC088)) +#define PLL0FEED (*((volatile unsigned long *) 0x400FC08C)) +#define CCLKSEL (*((volatile unsigned long *) 0x400FC104)) +#define CLKSRCSEL (*((volatile unsigned long *) 0x400FC10C)) -#include "flash_data.h" +#define STACK_SIZE 64 // Stack Size -// This is a flash algo binary blob. It is PIC (position independent code) that should be stored in RAM -static uint32_t FLASH_ALGO[] = { - 0x28100b00, 0x210ed302, 0x00d0eb01, 0xf44f4770, 0xfbb1707a, 0x4933f0f0, 0x60084449, 0x20014932, - 0x20006408, 0x20004770, 0xe92d4770, 0xf7ff41f0, 0x4d2effe7, 0x444d4604, 0xe9c52032, 0xf1050400, - 0x4e2b0114, 0x4628460f, 0x47b060ac, 0xb9686968, 0xe9c52034, 0x48230400, 0x444860ac, 0x68004639, - 0x462860e8, 0x696847b0, 0xd0002800, 0xe8bd2001, 0xe92d81f0, 0x461441f0, 0xd10e0006, 0x0100e9d4, - 0xe9d44408, 0x44111202, 0x69214408, 0x69614408, 0x69a14408, 0x42404408, 0x463061e0, 0xffb0f7ff, - 0x21324d12, 0x4f12444d, 0x1000e9c5, 0x0114f105, 0x468860a8, 0x47b84628, 0xb9806968, 0xe9c52033, - 0xf44f0600, 0xe9c56080, 0x48064002, 0x44484641, 0x61286800, 0x47b84628, 0x28006968, 0x2001d0c7, - 0x0000e7c5, 0x00000004, 0x400fc000, 0x00000008, 0x1fff1ff1, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 -}; +#define SET_VALID_CODE 1 // Set Valid User Code Signature +/* IAP Call */ +typedef void (*IAP_Entry) (unsigned long *cmd, unsigned long *stat); +#define IAP_Call ((IAP_Entry) 0x1FFF1FF1) -static const flash_algo_t flash_algo_config = { - .init = 0xf, - .uninit = 0x27, - .erase_sector = 0x2b, - .program_page = 0x73, - .static_base = 0xf4, - .algo_blob = FLASH_ALGO -}; +typedef struct flash_s flash_t; +unsigned long CCLK; // CCLK in kHz -static const sector_info_t sectors_info[] = { - {0x0, 0x1000}, - {0x10000, 0x8000}, -}; +struct sIAP { // IAP Structure + unsigned long cmd;// Command + unsigned long par[4];// Parameters + unsigned long stat;// Status + unsigned long res[2];// Result +}IAP; -static const flash_target_config_t flash_target_config = { - .page_size = 0x400, - .flash_start = 0x0, - .flash_size = 0x80000, - .sectors = sectors_info, - .sector_info_count = sizeof(sectors_info) / sizeof(sector_info_t) -}; +/* + * Get Sector Number + * Parameter: address: Sector Address + * Return Value: Sector Number + */ -void flash_set_target_config(flash_t *obj) +unsigned long GetSecNum (unsigned long address) { - obj->flash_algo = &flash_algo_config; - obj->target_config = &flash_target_config; + unsigned long n; + + n = address >> 12; // 4kB Sector + if (n >= 0x10) { + n = 0x0E + (n >> 3); // 32kB Sector + } + + return (n); // Sector Number +} +int32_t flash_init(flash_t *obj) +{ + CCLK = SystemCoreClock / 1000; // CCLK value is in kHz, clk in Hz + + MEMMAP = 0x01;// User Flash Mode + + return (0); +} + +int32_t flash_free(flash_t *obj) +{ + return 0; +} + +int32_t flash_erase_sector(flash_t *obj, uint32_t address) +{ + unsigned long n; + + n = GetSecNum(address); // Get Sector Number + + IAP.cmd = 50;// Prepare Sector for Erase + IAP.par[0] = n;// Start Sector + IAP.par[1] = n;// End Sector + IAP_Call (&IAP.cmd, &IAP.stat);// Call IAP Command + if (IAP.stat) { + return (1); // Command Failed + } + + IAP.cmd = 52; // Erase Sector + IAP.par[0] = n;// Start Sector + IAP.par[1] = n;// End Sector + IAP.par[2] = CCLK;// CCLK in kHz + IAP_Call (&IAP.cmd, &IAP.stat);// Call IAP Command + if (IAP.stat) { + return (1); // Command Failed + } + + return (0); // Finished without Errors + +} + +/* IAP Call */ +typedef void (*IAP_Entry) (unsigned long *cmd, unsigned long *stat); +#define IAP_Call ((IAP_Entry) 0x1FFF1FF1) + +int32_t flash_program_page(flash_t *obj, uint32_t address, + const uint8_t *data, uint32_t size) +{ + unsigned long n; + uint8_t *alignedData = 0; + + n = GetSecNum(address); // Get Sector Number + + IAP.cmd = 50;// Prepare Sector for Write + IAP.par[0] = n;// Start Sector + IAP.par[1] = n;// End Sector + IAP_Call (&IAP.cmd, &IAP.stat);// Call IAP Command + if (IAP.stat) { + return (1); // Command Failed + } + + IAP.cmd = 51; // Copy RAM to Flash + IAP.par[0] = address;// Destination Flash Address + + if ((unsigned long)data%4==0) { // Word boundary + IAP.par[1] = (unsigned long)data;// Source RAM Address + } else { + alignedData = malloc(size); + memcpy(alignedData,data,size); + IAP.par[1] = (unsigned long)alignedData; // Source RAM Address + } + + IAP.par[2] = 1024; // Fixed Page Size + IAP.par[3] = CCLK;// CCLK in kHz + IAP_Call (&IAP.cmd, &IAP.stat);// Call IAP Command + + if(alignedData !=0) { // We allocated our own memory + free(alignedData); + } + + if (IAP.stat) { + return (1); // Command Failed + } + return (0); // Finished without Errors +} + +uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address) +{ + if (address < flash_get_start_address(obj) || address >= flash_get_start_address(obj) +flash_get_size(obj)) { + return MBED_FLASH_INVALID_SIZE; + } + if(GetSecNum(address)>=0x10) { + return 0x8000; + } else { + return 0x1000; + } +} + +uint32_t flash_get_page_size(const flash_t *obj) +{ + return 1024; +} + +uint32_t flash_get_start_address(const flash_t *obj) +{ + return LPC_FLASH_BASE; +} + +uint32_t flash_get_size(const flash_t *obj) +{ + return 0x80000; } #endif diff --git a/targets/TARGET_NXP/TARGET_LPC176X/objects.h b/targets/TARGET_NXP/TARGET_LPC176X/objects.h index ecbd354934..331ccc9ceb 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/objects.h +++ b/targets/TARGET_NXP/TARGET_LPC176X/objects.h @@ -71,6 +71,10 @@ struct spi_s { LPC_SSP_TypeDef *spi; }; +struct flash_s { + /* nothing to be stored for now */ + uint32_t dummy; +}; #ifdef __cplusplus } #endif diff --git a/targets/targets.json b/targets/targets.json index 452e29db01..b177fd82e2 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -238,7 +238,7 @@ "extra_labels": ["NXP", "LPC176X", "MBED_LPC1768"], "supported_toolchains": ["ARM", "uARM", "GCC_ARM", "GCC_CR", "IAR"], "detect_code": ["1010"], - "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOCALFILESYSTEM", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOCALFILESYSTEM", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], "release_versions": ["2", "5"], "features": ["LWIP"], "device_name": "LPC1768" @@ -250,7 +250,7 @@ "extra_labels": ["NXP", "LPC176X"], "macros": ["TARGET_LPC1768"], "inherits": ["LPCTarget"], - "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], "release_versions": ["2", "5"], "features": ["LWIP"], "device_name": "LPC1768" @@ -259,7 +259,7 @@ "supported_form_factors": ["ARDUINO"], "core": "Cortex-M3", "supported_toolchains": ["ARM", "uARM", "GCC_ARM", "GCC_CR", "IAR"], - "extra_labels": ["NXP", "LPC176X", "FLASH_CMSIS_ALGO"], + "extra_labels": ["NXP", "LPC176X"], "config": { "modem_is_on_board": { "help": "Value: Tells the build system that the modem is on-board as oppose to a plug-in shield/module.", @@ -283,7 +283,7 @@ "inherits": ["LPCTarget"], "core": "Cortex-M3", "supported_toolchains": ["ARM", "uARM", "GCC_ARM", "GCC_CR", "IAR"], - "extra_labels": ["NXP", "LPC176X", "XBED_LPC1768", "FLASH_CMSIS_ALGO"], + "extra_labels": ["NXP", "LPC176X", "XBED_LPC1768"], "macros": ["TARGET_LPC1768"], "detect_code": ["1010"], "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOCALFILESYSTEM", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH"],