?? flash.c
字號:
/******************************************************************************
*
* $RCSfile: $
* $Revision: $
*
* This module provides interface routines to the LPC ARM Flash IAP.
* Copyright 2004, 2005 R O SoftWare
* No guarantees, warrantees, or promises, implied or otherwise.
* May be used for hobby or commercial purposes provided copyright
* notice remains intact.
*
*****************************************************************************/
#include <string.h>
#include "lpc.h"
#include "flash.h"
#include "armISR.h"
#define CCLK (60000000) // CPU Clock Speed
#ifndef MIN
#define MIN(n,m) (((n) < (m)) ? (n) : (m))
#endif
#define IAP_LOCATION 0x7FFFFFF1ul
static int lastSector;
static unsigned long flashParams[5];
/******************************************************************************
*
* Function Name: callIAP()
*
* Description:
* This function loads the address of flashParams[] into r0 & r1
* then calls the LPC's IAP (Thumb mode) code.
*
* Calling Sequence:
* void
*
* Returns:
* void
*
* NOTES:
* - We don't make this an inline function because the call to the
* IAP code is made from assembly language therefore the compiler
* doesn't realize other registers are possibly being altered.
* - pFP is in the source list of the asm so its assignment to the
* address of flashParams[] is not optimized away.
* - 'lr' is not assigned prior to 'bx' so the IAP code will return
* directly to this functions caller
*
*****************************************************************************/
static void callIAP(void) __attribute((naked));
static void callIAP(void)
{
// fast way to get the address of flashParams[] directly into r0
register void *pFP asm("r0") = flashParams;
asm volatile(" mov r1, r0\n" // copy &flashParams[] into r1
" bx %[iapLocation]" // 'bx' because IAP is Thumb mode
:
: "r" (pFP), [iapLocation] "r" (IAP_LOCATION)
: "r1" );
}
/******************************************************************************
*
* Function Name: flashBlank()
*
* Description:
* This function checks if the range of specified sectors is erased.
*
* Calling Sequence:
* startSector - first sector to be erased
* endSector - last sector to be erased
*
* Returns:
* 0 - success, else error code
*
*****************************************************************************/
int flashBlank(int startSector, int endSector)
{
flashParams[0] = 53; // blank check
flashParams[1] = startSector; // start sector
flashParams[2] = endSector; // end sector
callIAP();
return (int)flashParams[0];
}
/******************************************************************************
*
* Function Name: flashErase()
*
* Description:
* This function erases the range of specified sectors
*
* Calling Sequence:
* startSector - first sector to be erased
* endSector - last sector to be erased
*
* Returns:
* 0 - success, else error code
*
*****************************************************************************/
int flashErase(int startSector, int endSector)
{
unsigned long cpsr;
unsigned char memmap;
cpsr = disableINTs(); // disable all interrupts
memmap = MEMMAP; // get current memory map
MEMMAP = MEMMAP_FLASH; // map User Flash into low 64 bytes
flashParams[0] = 50; // prepare sector(s)
flashParams[1] = startSector; // start sector
flashParams[2] = endSector; // end sector
callIAP();
if (flashParams[0] == CMD_SUCCESS)
{
flashParams[0] = 52; // erase sector(s)
flashParams[1] = startSector; // start sector
flashParams[2] = endSector; // end sector
flashParams[3] = CCLK/1000; // cpu clock freq in KHz
callIAP();
}
MEMMAP = memmap & 0x03; // restore the memory map
restoreINTs(cpsr); // restore all interrupts
return (int)flashParams[0];
}
/******************************************************************************
*
* Function Name: flashWrite()
*
* Description:
* This function writes byteCount bytes of data from the src location
* to the dst location in flash.
*
* Calling Sequence:
* *dst - location in flash at which to start writing
* *src - location from which to get data (word boundary)
* byteCount - number of bytes to write
*
* Returns:
* 0 - success, else error code
*
* NOTE: When programming data into a sector that is already partially
* programmed, all new data MUST be programmed into previously
* unprogrammed 16-byte (128-bit) blocks. This requirement is NOT
* currently checked or enforced by this routine. See msgs by Philps
* Tech Support in the LPC2100 mailing list on Yahoo for more details.
*
*****************************************************************************/
int flashWrite(void *dst, void *src, unsigned byteCount)
{
unsigned char memmap;
unsigned long cpsr, count;
unsigned long buffer[512/sizeof (long)];
if ((lastSector == 0) &&
(flashInit() == LPCUNKN))
return BUSY;
while (byteCount)
{
cpsr = disableINTs(); // disable all interrupts
memmap = MEMMAP; // get current memory map
MEMMAP = MEMMAP_FLASH; // map User Flash into low 64 bytes
// prepare all sectors for programing
flashParams[0] = 50; // prepare sectors
flashParams[1] = 0; // start sector
flashParams[2] = lastSector; // last sector
callIAP();
if (flashParams[0] != CMD_SUCCESS)
{
MEMMAP = memmap & 0x03; // restore the memory map
restoreINTs(cpsr); // restore all interrupts
return flashParams[0];
}
// check if dst is on 512 byte boundary
if ((unsigned long)dst & 0x1FF)
{
// no, copy 512 bytes from flash into buffer
memcpy(buffer, (void *)((unsigned long)dst & ~0x1FF), 512);
// copy src into buffer
count = MIN(byteCount, (512 - ((unsigned long)dst & 0x1FF)));
memcpy((char *)buffer + ((unsigned long)dst & 0x1FF), src, count);
flashParams[0] = 51; // copy RAM to Flash
flashParams[1] = (unsigned long)dst & ~0x1FF; // destination
flashParams[2] = (unsigned long)buffer; // source
flashParams[3] = 512; // byte count
flashParams[4] = CCLK/1000; // CCLK in KHz
callIAP();
MEMMAP = memmap & 0x03; // restore the memory map
restoreINTs(cpsr); // restore all interrupts
if (flashParams[0] != CMD_SUCCESS)
return (int)flashParams[0];
dst = (char *)dst + count;
src = (char *)src + count;
byteCount -= count;
continue; // restart the loop to prepare sectors again
}
// dst is now aligned on a 512 byte boundary
// find the biggest chunk we can program at a time
if (byteCount >= 8192)
count = 8192;
else if (byteCount >= 4096)
count = 4096;
else if (byteCount >= 1024)
count = 1024;
else if (byteCount >= 512)
count = 512;
else
count = byteCount;
if (count < 512)
{
memcpy(buffer, dst, 512); // copy current flash contents into buffer
memcpy(buffer, src, count); // update buffer with the new contents
flashParams[2] = (unsigned long)buffer; // source
flashParams[3] = 512; // byte count
}
else
{
flashParams[2] = (unsigned long)src;
flashParams[3] = count; // byte count
}
flashParams[0] = 51; // copy RAM to Flash
flashParams[1] = (unsigned long)dst; // destination
flashParams[4] = CCLK/1000; // CCLK in KHz
callIAP();
MEMMAP = memmap & 0x03; // restore the memory map
restoreINTs(cpsr); // restore all interrupts
if (flashParams[0] != CMD_SUCCESS)
return (int)flashParams[0];
dst = (char *)dst + count;
src = (char *)src + count;
byteCount -= count;
}
return CMD_SUCCESS;
}
/******************************************************************************
*
* Function Name: flashInit()
*
* Description:
* This function tests if the LPC has 128K or 256K of flash and
* returns the result.
*
* Calling Sequence:
* void
*
* Returns:
* LPC128K, LPC256K, or LPCUNKN (on error)
*
*****************************************************************************/
int flashInit(void)
{
lastSector = 0; // clear last usable sector #
switch (flashBlank(16, 16)) // check last sector of 256K parts
{
case CMD_SUCCESS:
case SECTOR_NOT_BLANK:
lastSector = 16; // store last usable sector #
return LPC256K;
case INVALID_SECTOR:
break;
default:
return LPCUNKN;
}
switch (flashBlank(14, 14)) // check last sector of 128K parts
{
case CMD_SUCCESS:
case SECTOR_NOT_BLANK:
lastSector = 14; // store last usable sector #
return LPC128K;
default:
break;
}
return LPCUNKN;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -