Norimasa Okamoto / ROMSLOT
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ROMSLOT_LPC1768.cpp Source File

ROMSLOT_LPC1768.cpp

00001 // ROMSLOT_LPC1768.cpp 2016/4/9
00002 #if defined(TARGET_LPC1768)
00003 #include "ROMSLOT.h"
00004 
00005 static const uint32_t FLASH_SECTOR_BASE = 0x10000;
00006 static const uint32_t FLASH_SECTOR_SIZE = 0x8000; // 32 Kbytes
00007 
00008 #if defined(IAP_DEBUG)
00009 #define IAP_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0)
00010 #else
00011 #define IAP_DBG(...) while(0)
00012 #endif
00013 #define IAP_ASSERT(A) MBED_ASSERT(A)
00014 
00015 #define IAP_LOCATION 0x1fff1ff1
00016 typedef void (*IAP)(uint32_t* command, uint32_t* result);
00017 
00018 uint32_t iap(uint32_t cmd, uint32_t p0 = 0, uint32_t p1 = 0, uint32_t p2 = 0, uint32_t p3 = 0) {
00019     uint32_t command[5] = {cmd, p0, p1, p2, p3};
00020     uint32_t result[4];
00021     IAP iap_entry = (IAP)IAP_LOCATION;
00022     IAP_DBG("command: %x %x %x %x %x\n", command[0], command[1], command[2], command[3], command[4]);
00023     iap_entry(command, result);
00024     IAP_DBG("result: %x %x %x %x\n", result[0], result[1], result[2], result[3]);
00025     return result[0];
00026 }
00027 
00028 ROMSLOT::ROMSLOT() {
00029     base = FLASH_SECTOR_BASE;
00030 }
00031 
00032 uint32_t ROMSLOT::New(uint32_t size) {
00033     uint32_t addr = base;
00034     base += (size + FLASH_SECTOR_SIZE - 1) / FLASH_SECTOR_SIZE * FLASH_SECTOR_SIZE;
00035     return addr;
00036 }
00037 
00038 static bool is_base(uint32_t addr) {
00039     return addr % FLASH_SECTOR_SIZE == 0;
00040 }
00041 
00042 static uint32_t sector(uint32_t addr) {
00043     MBED_ASSERT(addr >= FLASH_SECTOR_BASE);
00044     uint32_t s = (addr - FLASH_SECTOR_BASE) / FLASH_SECTOR_SIZE + 16;
00045     return s;
00046 }
00047 
00048 bool ROMSLOT::Write(uint32_t addr, const uint8_t buf[], uint32_t size) {
00049     IAP_ASSERT(addr%256 == 0);
00050     IAP_ASSERT(size == 256);
00051     if (memcmp((uint8_t*)addr, buf, size) == 0) { // skip ?
00052         return true;
00053     }
00054     uint8_t temp[256];
00055     memcpy(temp, buf, sizeof(temp));
00056     IAP_ASSERT(addr >= 0x10000);
00057     uint32_t sectorNo = sector(addr);
00058     IAP_ASSERT(sectorNo >= 16);
00059     uint32_t cclk = SystemCoreClock / 1000;
00060     if (is_base(addr)) {
00061         if (iap(50, sectorNo, sectorNo) != 0) { // prepare
00062             return false;
00063         }
00064         if (iap(52, sectorNo, sectorNo, cclk) != 0) { // erase
00065             return false;
00066         }
00067     }
00068     if (iap(50, sectorNo, sectorNo) != 0) { // prepare
00069         return false;
00070     }
00071     if (iap(51, addr, (uint32_t)temp, size, cclk) != 0) { // Copy RAM to flash
00072         return false;
00073     }
00074     if (iap(56, addr, (uint32_t)temp, size) != 0) { // Compare
00075         return false;
00076     }
00077     return true;
00078 }
00079 #endif // TARGET_LPC1768
00080