rt-thread/bsp/lpc408x/Libraries/Drivers/source/lpc_eeprom.c

268 lines
10 KiB
C

/**********************************************************************
* $Id$ lpc_eeprom.c 2011-06-02
*//**
* @file lpc_eeprom.c
* @brief Contains all functions support for EEPROM firmware library on
* LPC
* @version 1.0
* @date 02. June. 2011
* @author NXP MCU SW Application Team
*
* Copyright(C) 2011, 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.
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors'
* relevant copyright in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
**********************************************************************/
/* Peripheral group ----------------------------------------------------------- */
/** @addtogroup EEPROM
* @{
*/
#ifdef __BUILD_WITH_EXAMPLE__
#include "lpc_libcfg.h"
#else
#include "lpc_libcfg_default.h"
#endif /* __BUILD_WITH_EXAMPLE__ */
#ifdef _EEPROM
/* Includes ------------------------------------------------------------------- */
#include "lpc_eeprom.h"
#include "lpc_clkpwr.h"
/* Public Functions ----------------------------------------------------------- */
/*********************************************************************//**
* @brief Initial EEPROM
* @param[in] None
* @return None
**********************************************************************/
void EEPROM_Init(void)
{
uint32_t val, cclk;
LPC_EEPROM->PWRDWN = 0x0;
/* EEPROM is automate turn on after reset */
/* Setting clock:
* EEPROM required a 375kHz. This clock is generated by dividing the
* system bus clock.
*/
cclk = CLKPWR_GetCLK(CLKPWR_CLKTYPE_CPU);
val = (cclk/375000)-1;
LPC_EEPROM->CLKDIV = val;
/* Setting wait state */
val = ((((cclk / 1000000) * 15) / 1000) + 1);
val |= (((((cclk / 1000000) * 55) / 1000) + 1) << 8);
val |= (((((cclk / 1000000) * 35) / 1000) + 1) << 16);
LPC_EEPROM->WSTATE = val;
}
/*********************************************************************//**
* @brief Write data to EEPROM at specific address
* @param[in] page_offset offset of data in page register(0 - 63)
* page_address page address (0-62)
* mode Write mode, should be:
* - MODE_8_BIT : write 8 bit mode
* - MODE_16_BIT : write 16 bit mode
* - MODE_32_BIT : write 32 bit mode
* data buffer that contain data that will be written to buffer
* count number written data
* @return None
* @note This function actually write data into EEPROM memory and automatically
* write into next page if current page is overflowed
**********************************************************************/
void EEPROM_Write(uint16_t page_offset, uint16_t page_address, void* data, EEPROM_Mode_Type mode, uint32_t count)
{
uint32_t i;
uint8_t *tmp8 = (uint8_t *)data;
uint16_t *tmp16 = (uint16_t *)data;
uint32_t *tmp32 = (uint32_t *)data;
LPC_EEPROM->INT_CLR_STATUS = ((1 << EEPROM_ENDOF_RW)|(1 << EEPROM_ENDOF_PROG));
//check page_offset
if(mode == MODE_16_BIT){
if((page_offset & 0x01)!=0) while(1);
}
else if(mode == MODE_32_BIT){
if((page_offset & 0x03)!=0) while(1);
}
LPC_EEPROM->ADDR = EEPROM_PAGE_OFFSET(page_offset);
for(i=0;i<count;i++)
{
//update data to page register
if(mode == MODE_8_BIT){
LPC_EEPROM->CMD = EEPROM_CMD_8_BIT_WRITE;
LPC_EEPROM -> WDATA = *tmp8;
tmp8++;
page_offset +=1;
}
else if(mode == MODE_16_BIT){
LPC_EEPROM->CMD = EEPROM_CMD_16_BIT_WRITE;
LPC_EEPROM -> WDATA = *tmp16;
tmp16++;
page_offset +=2;
}
else{
LPC_EEPROM->CMD = EEPROM_CMD_32_BIT_WRITE;
LPC_EEPROM -> WDATA = *tmp32;
tmp32++;
page_offset +=4;
}
while(!((LPC_EEPROM->INT_STATUS >> EEPROM_ENDOF_RW)&0x01));
LPC_EEPROM->INT_CLR_STATUS = (1 << EEPROM_ENDOF_RW);
if((page_offset >= EEPROM_PAGE_SIZE)|(i==count-1)){
//update to EEPROM memory
LPC_EEPROM->INT_CLR_STATUS = (0x1 << EEPROM_ENDOF_PROG);
LPC_EEPROM->ADDR = EEPROM_PAGE_ADRESS(page_address);
LPC_EEPROM->CMD = EEPROM_CMD_ERASE_PRG_PAGE;
while(!((LPC_EEPROM->INT_STATUS >> EEPROM_ENDOF_PROG)&0x01));
LPC_EEPROM->INT_CLR_STATUS = (1 << EEPROM_ENDOF_PROG);
}
if(page_offset >= EEPROM_PAGE_SIZE)
{
page_offset = 0;
page_address +=1;
LPC_EEPROM->ADDR =0;
if(page_address > EEPROM_PAGE_NUM - 1) page_address = 0;
}
}
}
/*********************************************************************//**
* @brief Read data to EEPROM at specific address
* @param[in]
* data buffer that contain data that will be written to buffer
* mode Read mode, should be:
* - MODE_8_BIT : read 8 bit mode
* - MODE_16_BIT : read 16 bit mode
* - MODE_32_BIT : read 32 bit mode
* count number read data (bytes)
* @return data buffer that contain data that will be read to buffer
**********************************************************************/
void EEPROM_Read(uint16_t page_offset, uint16_t page_address, void* data, EEPROM_Mode_Type mode, uint32_t count)
{
uint32_t i;
uint8_t *tmp8 = (uint8_t *)data;
uint16_t *tmp16 = (uint16_t *)data;
uint32_t *tmp32 = (uint32_t *)data;
LPC_EEPROM->INT_CLR_STATUS = ((1 << EEPROM_ENDOF_RW)|(1 << EEPROM_ENDOF_PROG));
LPC_EEPROM->ADDR = EEPROM_PAGE_ADRESS(page_address)|EEPROM_PAGE_OFFSET(page_offset);
if(mode == MODE_8_BIT)
LPC_EEPROM->CMD = EEPROM_CMD_8_BIT_READ|EEPROM_CMD_RDPREFETCH;
else if(mode == MODE_16_BIT){
LPC_EEPROM->CMD = EEPROM_CMD_16_BIT_READ|EEPROM_CMD_RDPREFETCH;
//check page_offset
if((page_offset &0x01)!=0)
return;
}
else{
LPC_EEPROM->CMD = EEPROM_CMD_32_BIT_READ|EEPROM_CMD_RDPREFETCH;
//page_offset must be a multiple of 0x04
if((page_offset & 0x03)!=0)
return;
}
//read and store data in buffer
for(i=0;i<count;i++){
if(mode == MODE_8_BIT){
*tmp8 = (uint8_t)(LPC_EEPROM -> RDATA);
tmp8++;
page_offset +=1;
}
else if (mode == MODE_16_BIT)
{
*tmp16 = (uint16_t)(LPC_EEPROM -> RDATA);
tmp16++;
page_offset +=2;
}
else{
*tmp32 = (uint32_t)(LPC_EEPROM ->RDATA);
tmp32++;
page_offset +=4;
}
while(!((LPC_EEPROM->INT_STATUS >> EEPROM_ENDOF_RW)&0x01));
LPC_EEPROM->INT_CLR_STATUS = (1 << EEPROM_ENDOF_RW);
if((page_offset >= EEPROM_PAGE_SIZE) && (i < count - 1)) {
page_offset = 0;
page_address++;
LPC_EEPROM->ADDR = EEPROM_PAGE_ADRESS(page_address)|EEPROM_PAGE_OFFSET(page_offset);
if(mode == MODE_8_BIT)
LPC_EEPROM->CMD = EEPROM_CMD_8_BIT_READ|EEPROM_CMD_RDPREFETCH;
else if(mode == MODE_16_BIT)
LPC_EEPROM->CMD = EEPROM_CMD_16_BIT_READ|EEPROM_CMD_RDPREFETCH;
else
LPC_EEPROM->CMD = EEPROM_CMD_32_BIT_READ|EEPROM_CMD_RDPREFETCH;
}
}
}
/*********************************************************************//**
* @brief Erase a page at the specific address
* @param[in] address EEPROM page address (0-62)
* @return data buffer that contain data that will be read to buffer
**********************************************************************/
void EEPROM_Erase(uint16_t page_address)
{
uint32_t i;
uint32_t count = EEPROM_PAGE_SIZE/4;
LPC_EEPROM->INT_CLR_STATUS = ((1 << EEPROM_ENDOF_RW)|(1 << EEPROM_ENDOF_PROG));
//clear page register
LPC_EEPROM->ADDR = EEPROM_PAGE_OFFSET(0);
LPC_EEPROM->CMD = EEPROM_CMD_32_BIT_WRITE;
for(i=0;i<count;i++)
{
LPC_EEPROM->WDATA = 0;
while(!((LPC_EEPROM->INT_STATUS >> EEPROM_ENDOF_RW)&0x01));
LPC_EEPROM->INT_CLR_STATUS = (1 << EEPROM_ENDOF_RW);
}
LPC_EEPROM->INT_CLR_STATUS = (0x1 << EEPROM_ENDOF_PROG);
LPC_EEPROM->ADDR = EEPROM_PAGE_ADRESS(page_address);
LPC_EEPROM->CMD = EEPROM_CMD_ERASE_PRG_PAGE;
while(!((LPC_EEPROM->INT_STATUS >> EEPROM_ENDOF_PROG)&0x01));
LPC_EEPROM->INT_CLR_STATUS = (1 << EEPROM_ENDOF_PROG);
}
/*********************************************************************//**
* @brief Enable/Disable EEPROM power down mdoe
* @param[in] NewState PowerDown mode state, should be:
* - ENABLE: Enable power down mode
* - DISABLE: Disable power down mode
* @return None
**********************************************************************/
void EEPROM_PowerDown(FunctionalState NewState)
{
if(NewState == ENABLE)
LPC_EEPROM->PWRDWN = 0x1;
else
LPC_EEPROM->PWRDWN = 0x0;
}
#endif /*_EEPROM*/
/**
* @}
*/
/* --------------------------------- End Of File ------------------------------ */