/* This function resets some microcontroller peripherals to reset
* hardware configuration to ensure that the USB In-System Programming module
* will work properly. It is normally called from reset and assumes some reset
* configuration settings for the MCU.
* Some of the peripheral configurations may be redundant in your specific
* project.
*/
void IAP_ReinvokeISP()
{
//Make sure USB clock is turned on before calling ISP
LPC_SYSCON->SYSAHBCLKCTRL |= 0x04000;
//Make sure 32-bit Timer 1 is turned on before calling ISP
LPC_SYSCON->SYSAHBCLKCTRL |= 0x00400;
//Make sure GPIO clock is turned on before calling ISP
LPC_SYSCON->SYSAHBCLKCTRL |= 0x00040;
//Make sure IO configuration clock is turned on before calling ISP
LPC_SYSCON->SYSAHBCLKCTRL |= 0x10000;
//Make sure AHB clock divider is 1:1
LPC_SYSCON->SYSAHBCLKDIV = 1;
//Prepare the command array
m_Command[0] = 57;
//Initialize the storage state machine
*((unsigned int *)(0x10000054)) = 0x0;
//Set stack pointer to ROM value (reset default)
//This must be the last piece of code executed before calling ISP,
//because most C expressions and function returns will fail after the stack pointer is changed.
__set_MSP(*((unsigned int *)0x00000000));
//Invoke IAP call...
IAP_Entry(m_Command, m_Result);
//Shouldn't return
while(1);
}
|
#include "mbed.h"
#include "IAP_LPC11UXX.h"
DigitalOut led1(LED1, 1);
int main()
{
led1 = !led1;
wait(0.5);
led1 = !led1;
wait(0.5);
led1 = !led1;
wait(0.5);
IAP_ReinvokeISP();
}
|
#ifndef IAP_LPC11UXX_H
#define IAP_LPC11UXX_H
#include "mbed.h"
//128-bit unique ID struct typedef
struct UID {
unsigned int word0; /**< Word 0 of 128-bit UID (bits 31 to 0) */
unsigned int word1; /**< Word 1 of 128-bit UID (bits 63 to 32) */
unsigned int word2; /**< Word 2 of 128-bit UID (bits 95 to 64) */
unsigned int word3; /**< Word 3 of 128-bit UID (bits 127 to 96) */
};
//IAP return code enumeration
enum IapReturnCode {
IAP_CMD_SUCCESS = 0,
IAP_INVALID_COMMAND,
IAP_SRC_ADDR_ERROR,
IAP_DST_ADDR_ERROR,
IAP_SRC_ADDR_NOT_MAPPED,
IAP_DST_ADDR_NOT_MAPPED,
IAP_COUNT_ERROR,
IAP_INVALID_SECTOR,
IAP_SECTOR_NOT_BLANK,
IAP_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION,
IAP_COMPARE_ERROR,
IAP_BUSY
};
//Function prototypes
IapReturnCode IAP_PrepareSectors(unsigned int sector_start, unsigned int sector_end);
IapReturnCode IAP_CopyRAMToFlash(void* ram_address, void* flash_address, unsigned int length);
IapReturnCode IAP_EraseSectors(unsigned int sector_start, unsigned int sector_end);
IapReturnCode IAP_BlankCheckSectors(unsigned int sector_start, unsigned int sector_end);
unsigned int IAP_ReadPartID();
unsigned short IAP_ReadBootCodeVersion();
IapReturnCode IAP_Compare(void* address1, void* address2, unsigned int bytes);
void IAP_ReinvokeISP();
UID IAP_ReadUID();
IapReturnCode IAP_ErasePage(unsigned int page_start, unsigned int page_end);
IapReturnCode IAP_WriteEEPROM(unsigned int ee_address, char* buffer, unsigned int length);
IapReturnCode IAP_ReadEEPROM(unsigned int ee_address, char* buffer, unsigned int length);
#endif
|
#include "IAP_LPC11UXX.h"
namespace
{
//This data must be global so it is not read from the stack
unsigned int m_Command[5], m_Result[5];
typedef void (*IAP)(unsigned int [], unsigned int []);
const IAP IAP_Entry = (IAP)0x1FFF1FF1;
}
static inline void _iap_CriticalEntry()
{
//Disable interrupts
__disable_irq();
//Safely perform IAP entry
IAP_Entry(m_Command, m_Result);
//Enable interrupts
__enable_irq();
}
IapReturnCode IAP_PrepareSectors(unsigned int sector_start, unsigned int sector_end)
{
//Prepare the command array
m_Command[0] = 50;
m_Command[1] = sector_start; //The start of the sector to be prepared
m_Command[2] = sector_end; //The end of the sector to be prepared
//Invoke critical IAP call...
_iap_CriticalEntry();
//Extract the result code
IapReturnCode ret = (IapReturnCode)m_Result[0];
//Return the result code
return ret;
}
IapReturnCode IAP_CopyRAMToFlash(void* ram_address, void* flash_address, unsigned int length)
{
//Prepare the command array
m_Command[0] = 51;
m_Command[1] = (unsigned int)flash_address; //Flash address where the contents are to be copied (it should be within 256bytes boundary)
m_Command[2] = (unsigned int)ram_address; //RAM address to be copied (it should be in word boundary)
m_Command[3] = length; //Number of data to be copied in bytes: 256, 512, 1024, or 4096
m_Command[4] = SystemCoreClock / 1000;
//Invoke critical IAP call...
_iap_CriticalEntry();
//Extract the result code
IapReturnCode ret = (IapReturnCode)m_Result[0];
//Return the result code
return ret;
}
IapReturnCode IAP_EraseSectors(unsigned int sector_start, unsigned int sector_end)
{
//Prepare the command array
m_Command[0] = 52;
m_Command[1] = sector_start; //The start of the sector to be erased
m_Command[2] = sector_end; //The end of the sector to be erased
m_Command[3] = SystemCoreClock / 1000; //System Clock Frequency (CCLK) in kHz
//Invoke critical IAP call...
_iap_CriticalEntry();
//Extract the result code
IapReturnCode ret = (IapReturnCode)m_Result[0];
//Return the result code
return ret;
}
IapReturnCode IAP_BlankCheckSectors(unsigned int sector_start, unsigned int sector_end)
{
//Prepare the command array
m_Command[0] = 53;
m_Command[1] = sector_start; //The start of the sector to be checked
m_Command[2] = sector_end; //The end of the sector to be checked
//Invoke critical IAP call...
_iap_CriticalEntry();
//Extract the result code
IapReturnCode ret = (IapReturnCode)m_Result[0];
//Return the result code
return ret;
}
unsigned int IAP_ReadPartID()
{
//Prepare the command array
m_Command[0] = 54;
//Invoke critical IAP call...
_iap_CriticalEntry();
//Extract the part ID
unsigned int ret = m_Result[1];
//Return the part ID
return ret;
}
unsigned short IAP_ReadBootCodeVersion()
{
//Prepare the command array
m_Command[0] = 55;
//Invoke critical IAP call...
_iap_CriticalEntry();
//Extract the boot code version
unsigned int ret = (unsigned short)m_Result[1];
//Return the boot code version
return ret;
}
IapReturnCode IAP_Compare(void* address1, void* address2, unsigned int bytes)
{
//Prepare the command array
m_Command[0] = 56;
m_Command[1] = (unsigned int)address1; //Starting flash or RAM address of data bytes to be compared. This address should be a word boundary.
m_Command[2] = (unsigned int)address2; //Starting flash or RAM address of data bytes to be compared. This address should be a word boundary.
m_Command[3] = bytes; //Number of bytes to be compared; should be a multiple of 4.
//Invoke critical IAP call...
_iap_CriticalEntry();
//Extract the result code
IapReturnCode ret = (IapReturnCode)m_Result[0];
//Return the result code
return ret;
}
/* This function resets some microcontroller peripherals to reset
* hardware configuration to ensure that the USB In-System Programming module
* will work properly. It is normally called from reset and assumes some reset
* configuration settings for the MCU.
* Some of the peripheral configurations may be redundant in your specific
* project.
*/
void IAP_ReinvokeISP()
{
//Make sure USB clock is turned on before calling ISP
LPC_SYSCON->SYSAHBCLKCTRL |= 0x04000;
//Make sure 32-bit Timer 1 is turned on before calling ISP
LPC_SYSCON->SYSAHBCLKCTRL |= 0x00400;
//Make sure GPIO clock is turned on before calling ISP
LPC_SYSCON->SYSAHBCLKCTRL |= 0x00040;
//Make sure IO configuration clock is turned on before calling ISP
LPC_SYSCON->SYSAHBCLKCTRL |= 0x10000;
//Make sure AHB clock divider is 1:1
LPC_SYSCON->SYSAHBCLKDIV = 1;
//Prepare the command array
m_Command[0] = 57;
//Initialize the storage state machine
*((unsigned int*)(0x10000054)) = 0x0;
//Set stack pointer to ROM value (reset default)
//This must be the last piece of code executed before calling ISP,
//because most C expressions and function returns will fail after the stack pointer is changed.
__set_MSP(*((unsigned int*)0x00000000));
//Invoke IAP call...
IAP_Entry(m_Command, m_Result);
}
UID IAP_ReadUID()
{
//Prepare the command array
m_Command[0] = 58;
//Invoke critical IAP call...
_iap_CriticalEntry();
//Extract the UID
UID ret = {
m_Result[1],
m_Result[2],
m_Result[3],
m_Result[4]
};
//Return the UID
return ret;
}
IapReturnCode IAP_ErasePage(unsigned int page_start, unsigned int page_end)
{
//Prepare the command array
m_Command[0] = 59;
m_Command[1] = page_start; //The start of the page to be erased
m_Command[2] = page_end; //The end of the page to be erased
m_Command[3] = SystemCoreClock / 1000; //System Clock Frequency (CCLK) in kHz
//Invoke critical IAP call...
_iap_CriticalEntry();
//Extract the result code
IapReturnCode ret = (IapReturnCode)m_Result[0];
//Return the result code
return ret;
}
IapReturnCode IAP_WriteEEPROM(unsigned int ee_address, char* buffer, unsigned int length)
{
//Prepare the command array
m_Command[0] = 61;
m_Command[1] = ee_address; //EEPROM address (byte, half-word or word aligned)
m_Command[2] = (unsigned int)buffer; //RAM address (byte, half-word or word aligned)
m_Command[3] = length; //Number of bytes to be written (byte, half-word writes are ok)
m_Command[4] = SystemCoreClock / 1000; //System Clock Frequency (CCLK) in kHz
//Invoke critical IAP call...
_iap_CriticalEntry();
//Extract the result code
IapReturnCode ret = (IapReturnCode)m_Result[0];
//Return the result code
return ret;
}
IapReturnCode IAP_ReadEEPROM(unsigned int ee_address, char* buffer, unsigned int length)
{
//Prepare the command array
m_Command[0] = 62;
m_Command[1] = ee_address; //EEPROM address (byte, half-word or word aligned)
m_Command[2] = (unsigned int)buffer; //RAM address (byte, half-word or word aligned)
m_Command[3] = length; //Number of bytes to be read (byte, half-word reads are ok)
m_Command[4] = SystemCoreClock / 1000; //System Clock Frequency (CCLK) in kHz
//Invoke critical IAP call...
_iap_CriticalEntry();
//Extract the result code
IapReturnCode ret = (IapReturnCode)m_Result[0];
//Return the result code
return ret;
}
|