LPC1768 IAP Fix (#4993)

use IAP routines for the flash HAL implementation
pull/5174/merge
Chris Snow 2017-09-22 11:30:43 +01:00 committed by Martin Kojtal
parent 26f9144c45
commit e2c42bb0a0
3 changed files with 160 additions and 42 deletions

View File

@ -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 <stdlib.h>
#include <string.h>
// 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

View File

@ -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

View File

@ -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"],