PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)
Dependents: YATTT sd_map_test cPong SnowDemo ... more
PokittoLib
Library for programming Pokitto hardware
How to Use
- Import this library to online compiler (see button "import" on the right hand side
- DO NOT import mbed-src anymore, a better version is now included inside PokittoLib
- Change My_settings.h according to your project
- Start coding!
POKITTO_HW/iap.cpp
- Committer:
- Pokitto
- Date:
- 2018-01-05
- Revision:
- 28:958b71c4b92a
- Parent:
- 20:fa6899411a24
File content as of revision 28:958b71c4b92a:
#include <stdio.h> #include <stdint.h> #include <iap.h> #include "LPC11U6x.h" #include "PokittoDisk.h" #define TICKRATE_HZ (10) /* 10 ticks per second */ /* SystemTick Counter */ static volatile uint32_t sysTick; /* LPC1347 IAP entry address */ #define IAP_LOCATION 0x1fff1ff1 #define last_sector_flash 0x00038000 //0x0000F000 #define IAP_LAST_SECTOR 28 /* Page number 896 - 1023, 0x00038000 - 0x0003FFFF */ #define IAP_NUM_BYTES_TO_WRITE 256 #define WRITECOUNT (IAP_NUM_BYTES_TO_WRITE / 4) /* when data array is in uint32_t */ #define IAP_PREWRRITE_CMD 50 /* Prepare sector for write operation command */ #define IAP_WRISECTOR_CMD 51 #define IAP_ERSSECTOR_CMD 52 #define IAP_REPID_CMD 54 /* IAP command variables */ static unsigned int command[5], result[4]; /* IAP entry function */ typedef int (*IAP)(unsigned int[], unsigned int[]); IAP iap_entry = (IAP) IAP_LOCATION; int CopyPageToFlash (uint32_t address, uint8_t* data) { IAP iap_call = (IAP) IAP_LOCATION; uint32_t writecount=0; __disable_irq(); unsigned int sector, page; bool firstpage=false, erasepage=false; //DEBUG// //for (int i=0;i<256;i++) data[i]=0xBB; /* Calculate sector based on address */ if (address < 0x18000) sector = address/0x1000; // sectors go in 4 k's else if (address >= 0x38000) sector = 28; else if (address >= 0x30000) sector = 27; else if (address >= 0x28000) sector = 26; else if (address >= 0x20000) sector = 25; else sector = 24; /* Check is it the first page in the sector */ if (sector<24) { if (address == sector * 0x1000) firstpage = true; } else { if (address == (sector-24)*0x4000 + 0x18000) firstpage = true; } /* Prepare the sector for writing */ command[0] = IAP_PREWRRITE_CMD; /* Prepare to write/erase command code */ command[1] = sector; /* Start Sector Number */ command[2] = sector; /* End Sector Number */ iap_call(command, result); if (result[0]) return 1; /* wipe pages when writing the loader */ if (address==0x39000) { erasepage=true; } /* do sector erase only when writing first page of given sector */ if (firstpage) { /* Erase the last sector */ command[0] = IAP_ERSSECTOR_CMD; /* Erase command code*/ command[1] = sector; /* Start Sector Number */ command[2] = sector; /* End Sector Number */ command[3] = SystemCoreClock / 1000UL; /* Core clock frequency in kHz */ iap_call(command, result); if (result[0]) return 1; /* Prepare to write/erase the last sector, needs to be done again because succesful erase re-locks sectors */ command[0] = IAP_PREWRRITE_CMD; /* Prepare to write/erase command code */ command[1] = sector; /* Start Sector Number */ command[2] = sector; /* Start Sector Number */ iap_call(command, result); if (result[0]) return 1; } /* page erase for bootloader area */ if (erasepage) { command[0] = 59; //erase page command command[1] = 896; command[2] = 1023; command[3] = SystemCoreClock / 1000UL; /* Core clock frequency in kHz */ iap_call(command, result); if (result[0]) return 1; /* Prepare to write/erase the last sector, needs to be done again because succesful erase re-locks sectors */ command[0] = IAP_PREWRRITE_CMD; /* Prepare to write/erase command code */ command[1] = sector; /* Start Sector Number */ command[2] = sector; /* Start Sector Number */ iap_call(command, result); if (result[0]) return 1; } /* Write data to the sectors */ command[0] = IAP_WRISECTOR_CMD; /* Write command code */ command[1] = (uint32_t) (uint32_t*) address; /* Destination Flash Address */ command[2] = (uint32_t) data; /* Source RAM Address */ command[3] = 0x100; /* Number of Bytes to be written */ command[4] = SystemCoreClock / 1000; /* System clock frequency */ iap_call(command, result); if (result[0]) return 1; /* Re-enable interrupt mode */ __enable_irq(); return 0; /*succesful write*/ } __attribute__((section(".IAP_Code"))) int HelloFromIAP() { static uint32_t array_data[WRITECOUNT]; int i; /* Initialize the array data to be written to FLASH */ for (i = 0; i < WRITECOUNT; i++) { array_data[i] = 0xB007AB1E; } IAP iap_call = (IAP) IAP_LOCATION; uint8_t teahupoo; //readEEPROM(0,&teahupoo,1); teahupoo++; //writeEEPROM(0,&teahupoo,1); /** open file **/ pokInitSD(); char fn[20]; char* now; now = (char*)last_sector_flash; switch (now[0]) { case 0xAA: fn[0]='B';fn[1]='B';fn[2]='.';fn[3]='B';fn[4]='I';fn[5]='N';fn[6]='\0';break; case 0xBB: fn[0]='C';fn[1]='C';fn[2]='.';fn[3]='B';fn[4]='I';fn[5]='N';fn[6]='\0';break; default: fn[0]='A';fn[1]='A';fn[2]='.';fn[3]='B';fn[4]='I';fn[5]='N';fn[6]='\0'; } if(fileOpen(fn,FILE_MODE_BINARY)) { return 1; } else { for (i = 0; i < WRITECOUNT; i++) { fileReadBytes((uint8_t*)&array_data[i],4); } } /** write sector in flash **/ /* Read Part Identification Number*/ command[0] = IAP_REPID_CMD; /* Read ID command code */ iap_call(command, result); __disable_irq(); /* Prepare to write/erase the last sector */ command[0] = IAP_PREWRRITE_CMD; /* Prepare to write/erase command code */ command[1] = IAP_LAST_SECTOR; /* Start Sector Number */ command[2] = IAP_LAST_SECTOR; /* End Sector Number */ iap_call(command, result); /* Erase the last sector */ command[0] = IAP_ERSSECTOR_CMD; /* Erase command code*/ command[1] = IAP_LAST_SECTOR; /* Start Sector Number */ command[2] = IAP_LAST_SECTOR; /* Start Sector Number */ command[3] = SystemCoreClock / 1000UL; /* Core clock frequency in kHz */ iap_call(command, result); /* Prepare to write/erase the last sector */ command[0] = IAP_PREWRRITE_CMD; /* Prepare to write/erase command code */ command[1] = IAP_LAST_SECTOR; /* Start Sector Number */ command[2] = IAP_LAST_SECTOR; /* Start Sector Number */ iap_call(command, result); /* Write to the last sector */ command[0] = IAP_WRISECTOR_CMD; /* Write command code */ command[1] = (uint32_t) last_sector_flash; /* Destination Flash Address */ command[2] = (uint32_t) &array_data; /* Source RAM Address */ command[3] = IAP_NUM_BYTES_TO_WRITE; /* Number of Bytes to be written */ command[4] = SystemCoreClock / 1000; /* System clock frequency */ iap_call(command, result); /* Re-enable interrupt mode */ __enable_irq(); SCB->AIRCR = 0x05FA0004; //issue system reset while(1); //should never come here return teahupoo; } void IAPstacksave() { /*need to save 32 top bytes of RAM to RAM1*/ #define RAM1_0 (*((volatile unsigned long *) 0x20000000)) #define RAM1_1 (*((volatile unsigned long *) 0x20000004)) #define RAM1_2 (*((volatile unsigned long *) 0x20000008)) #define RAM1_3 (*((volatile unsigned long *) 0x2000000C)) #define RAM1_4 (*((volatile unsigned long *) 0x20000010)) #define RAM1_5 (*((volatile unsigned long *) 0x20000014)) #define RAM1_6 (*((volatile unsigned long *) 0x20000018)) #define RAM1_7 (*((volatile unsigned long *) 0x2000001C)) uint32_t *saveloc = (uint32_t*)(0x10002000-0x20); // RAM top - 32 bytes RAM1_0 = *saveloc++; RAM1_1 = *saveloc++; RAM1_2 = *saveloc++; RAM1_3 = *saveloc++; RAM1_4 = *saveloc++; RAM1_5 = *saveloc++; RAM1_6 = *saveloc++; RAM1_7 = *saveloc; } char iaptest() { static uint32_t array_data[WRITECOUNT]; int i; /* Initialize the array data to be written to FLASH */ for (i = 0; i < WRITECOUNT; i++) { array_data[i] = 0x11223340 + i; } /* Read Part Identification Number*/ command[0] = IAP_REPID_CMD; /* Read ID command code */ iap_entry(command, result); /* Reinvoke ISP mode so that reprogamming of Flash possible */ __disable_irq(); command[0] = IAP_REPID_CMD; iap_entry(command, result); /* Prepare to write/erase the last sector */ command[0] = IAP_PREWRRITE_CMD; /* Prepare to write/erase command code */ command[1] = IAP_LAST_SECTOR; /* Start Sector Number */ command[2] = IAP_LAST_SECTOR; /* End Sector Number */ iap_entry(command, result); /* Erase the last sector */ command[0] = IAP_ERSSECTOR_CMD; /* Erase command code*/ command[1] = IAP_LAST_SECTOR; /* Start Sector Number */ command[2] = IAP_LAST_SECTOR; /* Start Sector Number */ iap_entry(command, result); /* Prepare to write/erase the last sector */ command[0] = IAP_PREWRRITE_CMD; /* Prepare to write/erase command code */ command[1] = IAP_LAST_SECTOR; /* Start Sector Number */ command[2] = IAP_LAST_SECTOR; /* Start Sector Number */ iap_entry(command, result); /* Write to the last sector */ command[0] = IAP_WRISECTOR_CMD; /* Write command code */ command[1] = (uint32_t) last_sector_flash; /* Destination Flash Address */ command[2] = (uint32_t) &array_data; /* Source RAM Address */ command[3] = IAP_NUM_BYTES_TO_WRITE; /* Number of Bytes to be written */ command[4] = SystemCoreClock / 1000; /* System clock frequency */ iap_entry(command, result); /* Re-enable interrupt mode */ __enable_irq(); //while (1) { // __WFI(); //} return 0; } //1) EEprom Write // //Command code: 61 //Param0: eeprom address (byte, half-word or word aligned) //Param1: RAM address (byte, half-word or word aligned) //Param2: Number of bytes to be written ( Byte, Half-words write are ok) //Param3: System Clock Frequency (CCLK) in kHz // //Return Code CMD_SUCCESS | SRC_ADDR_NOT_MAPPED | DST_ADDR_NOT_MAPPED __attribute__((section(".IAP_Code"))) void writeEEPROM( uint16_t* eeAddress, uint8_t* buffAddress, uint32_t byteCount ) { unsigned int command[5], result[4]; command[0] = 61; command[1] = (uint32_t) eeAddress; command[2] = (uint32_t) buffAddress; command[3] = byteCount; command[4] = SystemCoreClock/1000; /* Invoke IAP call...*/ #if (EEPROM_PROFILE!=0) LPC_CT32B0->TCR = 1; __disable_irq(); iap_entry(command, result); __enable_irq(); LPC_CT32B0->TCR = 0; #else __disable_irq(); iap_entry(command, result); __enable_irq(); #endif if (0 != result[0]) { //Trap error while(1); } return; } //2) EEprom Read //Command code: 62 //Param0: eeprom address (byte, half-word or word aligned) //Param1: RAM address (byte, half-word or word aligned) //Param2: Number of bytes to be read ( Byte, Half-words read are ok) //Param3: System Clock Frequency (CCLK) in kHz // //Return Code CMD_SUCCESS | SRC_ADDR_NOT_MAPPED | DST_ADDR_NOT_MAPPED __attribute__((section(".IAP_Code"))) void readEEPROM( uint16_t* eeAddress, uint8_t* buffAddress, uint32_t byteCount ) { unsigned int command[5], result[4]; command[0] = 62; command[1] = (uint32_t) eeAddress; command[2] = (uint32_t) buffAddress; command[3] = byteCount; command[4] = SystemCoreClock/1000; /* Invoke IAP call...*/ __disable_irq(); iap_entry( command, result); __enable_irq(); if (0 != result[0]) { //Trap error while(1); } return; } __attribute__((section(".IAP_Code"))) void IAPreadPartId( uint8_t* eeAddress, uint8_t* buffAddress, uint32_t byteCount ) { unsigned int command[5], result[4]; command[0] = 62; command[1] = (uint32_t) eeAddress; command[2] = (uint32_t) buffAddress; command[3] = byteCount; command[4] = SystemCoreClock/1000; /* Invoke IAP call...*/ __disable_irq(); iap_entry( command, result); __enable_irq(); if (0 != result[0]) { //Trap error while(1); } return; } uint8_t eeprom_read_byte(uint16_t* index) { uint8_t val; readEEPROM(index,&val,1); return val; } void eeprom_write_byte(uint16_t*index , uint8_t val) { writeEEPROM(index,&val,1); } /***************************************************************************** * $Id$ * * Project: NXP LPC11U6x In Application Programming * * Description: Provides access to In-Application Programming (IAP) routines * contained within the bootROM sector of LPC11U6x devices. * * Copyright(C) 2010, NXP Semiconductor * All rights reserved. * ***************************************************************************** * Software that is described herein is for illustrative purposes only * which provides customers with programming information regarding the * products. This software is supplied "AS IS" without any warranties. * NXP Semiconductors assumes no responsibility or liability for the * use of the software, conveys no license or title under any patent, * copyright, or mask work right to the product. NXP Semiconductors * reserves the right to make changes in the software without * notification. NXP Semiconductors also make no representation or * warranty that such application will be suitable for the specified * use without further testing or modification. *****************************************************************************/ /* IAP Command Definitions */ #define IAP_CMD_PREPARE_SECTORS 50 #define IAP_CMD_COPY_RAM_TO_FLASH 51 #define IAP_CMD_ERASE_SECTORS 52 #define IAP_CMD_BLANK_CHECK_SECTORS 53 #define IAP_CMD_READ_PART_ID 54 #define IAP_CMD_READ_BOOT_ROM_VERSION 55 #define IAP_CMD_COMPARE 56 #define IAP_CMD_REINVOKE_ISP 57 #define IAP_CMD_READ_UID 58 #define IAP_CMD_ERASE_PAGE 59 //new /* IAP boot ROM location and access function */ #define IAP_ROM_LOCATION 0x1FFF1FF1UL //#define IAP_EXECUTE_CMD(a, b) ((void (*)())(IAP_ROM_LOCATION))(a, b) __attribute__((section(".IAP_Code"))) void IAP_EXECUTE_CMD(uint32_t* a, uint32_t* b) { void (*user_code_entry)(uint32_t*,uint32_t*); uint32_t *p; p = (uint32_t *)IAP_ROM_LOCATION; user_code_entry = (void (*)(uint32_t*,uint32_t*))(*p); user_code_entry(a, b); } /***************************************************************************** ** Function name: u32IAP_PrepareSectors ** ** Description: Prepares sector(s) for erasing or write operations. This ** command must be executed before executing the "Copy RAM to ** Flash" or "Erase Sector(s)" commands. ** ** Parameters: u32StartSector - Number of first sector to prepare. ** u32EndSector - Number of last sector to prepare. ** ** Returned value: Status code returned by IAP ROM function. ** ******************************************************************************/ __attribute__((section(".IAP_Code"))) uint32_t u32IAP_PrepareSectors(uint32_t u32StartSector, uint32_t u32EndSector) { uint32_t u32Status; uint32_t au32Result[3]; uint32_t au32Command[5]; if (u32EndSector < u32StartSector) { u32Status = IAP_STA_INVALD_PARAM; } else { au32Command[0] = IAP_CMD_PREPARE_SECTORS; au32Command[1] = u32StartSector; au32Command[2] = u32EndSector; __disable_irq(); IAP_EXECUTE_CMD(au32Command, au32Result); __enable_irq(); u32Status = au32Result[0]; } return u32Status; } /***************************************************************************** ** Function name: u32IAP_CopyRAMToFlash ** ** Description: Program the flash memory with data stored in RAM. ** ** Parameters: u32DstAddr - Destination Flash address, should be a 256 ** byte boundary. ** u32SrcAddr - Source RAM address, should be a word boundary ** u32Len - Number of 8-bit bytes to write, must be a ** multiple of 256. * ** Returned value: Status code returned by IAP ROM function. ** ******************************************************************************/ __attribute__((section(".IAP_Code"))) uint32_t u32IAP_CopyRAMToFlash(uint32_t u32DstAddr, uint32_t u32SrcAddr, uint32_t u32Len) { uint32_t au32Result[3]; uint32_t au32Command[5]; au32Command[0] = IAP_CMD_COPY_RAM_TO_FLASH; au32Command[1] = u32DstAddr; au32Command[2] = u32SrcAddr; au32Command[3] = u32Len; au32Command[4] = SystemCoreClock / 1000UL; /* Core clock frequency in kHz */ IAP_EXECUTE_CMD(au32Command, au32Result); return au32Result[0]; } /***************************************************************************** ** Function name: u32IAP_EraseSectors ** ** Description: Erase a sector or multiple sectors of on-chip Flash memory. ** ** Parameters: u32StartSector - Number of first sector to erase. ** u32EndSector - Number of last sector to erase. * ** Returned value: Status code returned by IAP ROM function. ** ******************************************************************************/ __attribute__((section(".IAP_Code"))) uint32_t u32IAP_EraseSectors(uint32_t u32StartSector, uint32_t u32EndSector) { uint32_t u32Status; uint32_t au32Result[3]; uint32_t au32Command[5]; if (u32EndSector < u32StartSector) { u32Status = IAP_STA_INVALD_PARAM; } else { au32Command[0] = IAP_CMD_ERASE_SECTORS; au32Command[1] = u32StartSector; au32Command[2] = u32EndSector; au32Command[3] = SystemCoreClock / 1000UL; /* Core clock frequency in kHz */ IAP_EXECUTE_CMD(au32Command, au32Result); u32Status = au32Result[0]; } return u32Status; } /***************************************************************************** ** Function name: u32IAP_BlankCheckSectors ** ** Description: Blank check a sector or multiple sectors of on-chip flash ** memory. ** ** Parameters: u32StartSector - Number of first sector to check. ** u32EndSector - Number of last sector to check. ** pu32Result[0] - Offset of the first non blank word location ** if the Status Code is IAP_STA_SECTOR_NOT_BLANK. ** pu32Result[1] - Contents of non blank word location. ** ** Returned value: Status code returned by IAP ROM function. ** ******************************************************************************/ __attribute__((section(".IAP_Code"))) uint32_t u32IAP_BlankCheckSectors(uint32_t u32StartSector, uint32_t u32EndSector, uint32_t *pu32Result) { uint32_t u32Status; uint32_t au32Result[3]; uint32_t au32Command[5]; if (u32EndSector < u32StartSector) { u32Status = IAP_STA_INVALD_PARAM; } else { au32Command[0] = IAP_CMD_BLANK_CHECK_SECTORS; au32Command[1] = u32StartSector; au32Command[2] = u32EndSector; IAP_EXECUTE_CMD(au32Command, au32Result); if (au32Result[0] == IAP_STA_SECTOR_NOT_BLANK) { *pu32Result = au32Result[0]; *(pu32Result + 1) = au32Result[1]; } u32Status = au32Result[0]; } return u32Status; } /***************************************************************************** ** Function name: u32IAP_ReadPartID ** ** Description: Read the part identification number. ** ** Parameters: pu32PartID - Pointer to storage for part ID number. * ** Returned value: Status code returned by IAP ROM function. ** ******************************************************************************/ __attribute__((section(".IAP_Code"))) uint32_t u32IAP_ReadPartID(uint32_t *pu32PartID) { uint32_t au32Result[3]; uint32_t au32Command[5]; au32Command[0] = IAP_CMD_READ_PART_ID; __disable_irq(); IAP_EXECUTE_CMD(au32Command, au32Result); __enable_irq(); *pu32PartID = au32Result[1]; return au32Result[0]; } /***************************************************************************** ** Function name: u32IAP_ReadBootVersion ** ** Description: Read the boot code version number. ** ** Parameters: pu32Major - Major version number in ASCII format. ** pu32Minor - Minor version number in ASCII format. ** ** Returned value: Status code returned by IAP ROM function. ** ******************************************************************************/ __attribute__((section(".IAP_Code"))) uint32_t u32IAP_ReadBootVersion(uint32_t *pu32Major, uint32_t *pu32Minor) //uint32_t u32IAP_ReadBootVersion(uint32_t *pu32Major) { uint32_t au32Result[3]; uint32_t au32Command[5]; au32Command[0] = IAP_CMD_READ_BOOT_ROM_VERSION; IAP_EXECUTE_CMD(au32Command, au32Result); *pu32Major = (au32Result[1] & 0x0000FF00UL) >> 8; *pu32Minor = au32Result[1] & 0x000000FFUL; return au32Result[0]; } /***************************************************************************** ** Function name: u32IAP_Compare ** ** Description: Compares the memory contents at two locations. ** ** Parameters: u32Len - Number of bytes to compare, must be a multiple of 4. ** pu32Offset - Offset of the first mismatch if the Status Code is COMPARE_ERROR ** ** Returned value: Status code returned by IAP ROM function. ** ******************************************************************************/ __attribute__((section(".IAP_Code"))) uint32_t u32IAP_Compare(uint32_t u32DstAddr, uint32_t u32SrcAddr, uint32_t u32Len, uint32_t *pu32Offset) { uint32_t au32Result[3]; uint32_t au32Command[5]; au32Command[0] = IAP_CMD_COMPARE; au32Command[1] = u32DstAddr; au32Command[2] = u32SrcAddr; au32Command[3] = u32Len; IAP_EXECUTE_CMD(au32Command, au32Result); if (au32Result[0] == IAP_STA_COMPARE_ERROR) { if (pu32Offset != 0) { *pu32Offset = au32Result[1]; } } return au32Result[0]; } /***************************************************************************** ** Function name: vIAP_ReinvokeISP ** ** Description: Invoke the bootloader in ISP mode. ** ** Parameters: None. * ** Returned value: None. ** ******************************************************************************/ __attribute__((section(".IAP_Code"))) void vIAP_ReinvokeISP(void) { uint32_t au32Result[3]; uint32_t au32Command[5]; au32Command[0] = IAP_CMD_REINVOKE_ISP; IAP_EXECUTE_CMD(au32Command, au32Result); } // read UID __attribute__((section(".IAP_Code"))) uint32_t u32IAP_ReadUID(uint32_t * pu32UID) { uint32_t au32Result[5]; uint32_t au32Command[5]; au32Command[0] = IAP_CMD_READ_UID; IAP_EXECUTE_CMD(au32Command, au32Result); // *pu32UID++ = au32Result[1]; // *pu32UID++ = au32Result[2]; // *pu32UID++ = au32Result[3]; // *pu32UID = au32Result[4]; *pu32UID = au32Result[1]; *pu32UID++ = au32Result[2]; *pu32UID++ = au32Result[3]; *pu32UID++ = au32Result[4]; return au32Result[0]; } //IAP erase Page 256B 64K have 0-255 pages, page0-15 in sector 0, 32K have 0-127 pages, 128k have 0-511 pages, __attribute__((section(".IAP_Code"))) uint32_t u32IAP_ErasePage(uint32_t u32StartPage, uint32_t u32EndPage) { uint32_t u32Status; uint32_t au32Result[3]; uint32_t au32Command[5]; if (u32EndPage < u32StartPage) { u32Status = IAP_STA_INVALD_PARAM; } else { au32Command[0] = IAP_CMD_ERASE_PAGE; au32Command[1] = u32StartPage; au32Command[2] = u32EndPage; au32Command[3] = SystemCoreClock / 1000UL; /* Core clock frequency in kHz */ IAP_EXECUTE_CMD(au32Command, au32Result); u32Status = au32Result[0]; } return u32Status; } /***************************************************************************** ** End Of File *****************************************************************************/