2006-04-19 17:16:49 +00:00
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Filename: eeprom.c
|
|
|
|
*
|
|
|
|
* Instantiation of eeprom routines
|
|
|
|
*
|
|
|
|
* Revision information:
|
|
|
|
*
|
|
|
|
* 28AUG2004 kb_admin initial creation - adapted from Atmel sources
|
|
|
|
* 12JAN2005 kb_admin fixed clock generation, write polling, init
|
|
|
|
*
|
|
|
|
* BEGIN_KBDD_BLOCK
|
|
|
|
* No warranty, expressed or implied, is included with this software. It is
|
|
|
|
* provided "AS IS" and no warranty of any kind including statutory or aspects
|
|
|
|
* relating to merchantability or fitness for any purpose is provided. All
|
|
|
|
* intellectual property rights of others is maintained with the respective
|
|
|
|
* owners. This software is not copyrighted and is intended for reference
|
|
|
|
* only.
|
|
|
|
* END_BLOCK
|
|
|
|
*
|
|
|
|
* $FreeBSD$
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
#include "at91rm9200_lowlevel.h"
|
|
|
|
#include "at91rm9200.h"
|
|
|
|
#include "lib.h"
|
|
|
|
|
|
|
|
/******************************* GLOBALS *************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/*********************** PRIVATE FUNCTIONS/DATA ******************************/
|
|
|
|
|
|
|
|
|
|
|
|
/* Use a macro to calculate the TWI clock generator value to save code space. */
|
|
|
|
#define AT91C_TWSI_CLOCK 100000
|
|
|
|
#define TWSI_EEPROM_ADDRESS 0x50
|
|
|
|
|
|
|
|
#define TWI_CLK_BASE_DIV ((AT91C_MASTER_CLOCK/(4*AT91C_TWSI_CLOCK)) - 2)
|
|
|
|
#define SET_TWI_CLOCK ((0x00010000) | (TWI_CLK_BASE_DIV) | (TWI_CLK_BASE_DIV << 8))
|
|
|
|
|
|
|
|
|
|
|
|
/*************************** GLOBAL FUNCTIONS ********************************/
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* .KB_C_FN_DEFINITION_START
|
|
|
|
* void InitEEPROM(void)
|
|
|
|
* This global function initializes the EEPROM interface (TWI). Intended
|
|
|
|
* to be called a single time.
|
|
|
|
* .KB_C_FN_DEFINITION_END
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
InitEEPROM(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
AT91PS_TWI twiPtr = (AT91PS_TWI)AT91C_BASE_TWI;
|
|
|
|
|
|
|
|
AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
|
|
|
|
AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC;
|
|
|
|
|
|
|
|
pPio->PIO_ASR = AT91C_PA25_TWD | AT91C_PA26_TWCK;
|
|
|
|
pPio->PIO_PDR = AT91C_PA25_TWD | AT91C_PA26_TWCK;
|
|
|
|
|
|
|
|
pPio->PIO_MDDR = ~AT91C_PA25_TWD;
|
|
|
|
pPio->PIO_MDER = AT91C_PA25_TWD;
|
|
|
|
|
|
|
|
pPMC->PMC_PCER = 1u << AT91C_ID_TWI;
|
|
|
|
|
|
|
|
twiPtr->TWI_IDR = 0xffffffffu;
|
|
|
|
twiPtr->TWI_CR = AT91C_TWI_SWRST;
|
|
|
|
twiPtr->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS;
|
|
|
|
|
|
|
|
twiPtr->TWI_CWGR = SET_TWI_CLOCK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* .KB_C_FN_DEFINITION_START
|
|
|
|
* void ReadEEPROM(unsigned ee_addr, char *data_addr, unsigned size)
|
|
|
|
* This global function reads data from the eeprom at ee_addr storing data
|
|
|
|
* to data_addr for size bytes. Assume the TWI has been initialized.
|
|
|
|
* This function does not utilize the page read mode to simplify the code.
|
|
|
|
* .KB_C_FN_DEFINITION_END
|
|
|
|
*/
|
2006-12-20 18:19:52 +00:00
|
|
|
int
|
2006-08-10 18:03:50 +00:00
|
|
|
ReadEEPROM(unsigned ee_off, char *data_addr, unsigned size)
|
2006-04-19 17:16:49 +00:00
|
|
|
{
|
|
|
|
const AT91PS_TWI twiPtr = AT91C_BASE_TWI;
|
|
|
|
unsigned int status;
|
2006-12-20 18:19:52 +00:00
|
|
|
unsigned int count;
|
2006-04-19 17:16:49 +00:00
|
|
|
|
|
|
|
status = twiPtr->TWI_SR;
|
|
|
|
status = twiPtr->TWI_RHR;
|
|
|
|
|
|
|
|
// Set the TWI Master Mode Register
|
|
|
|
twiPtr->TWI_MMR = (TWSI_EEPROM_ADDRESS << 16) |
|
|
|
|
AT91C_TWI_IADRSZ_2_BYTE | AT91C_TWI_MREAD;
|
|
|
|
|
|
|
|
// Set TWI Internal Address Register
|
2006-08-10 18:03:50 +00:00
|
|
|
twiPtr->TWI_IADR = ee_off;
|
2006-04-19 17:16:49 +00:00
|
|
|
|
|
|
|
// Start transfer
|
|
|
|
twiPtr->TWI_CR = AT91C_TWI_START;
|
|
|
|
|
|
|
|
status = twiPtr->TWI_SR;
|
|
|
|
|
|
|
|
while (size-- > 1){
|
|
|
|
// Wait RHR Holding register is full
|
2006-12-20 18:19:52 +00:00
|
|
|
count = 1000000;
|
|
|
|
while (!(twiPtr->TWI_SR & AT91C_TWI_RXRDY) && --count > 0)
|
2006-04-19 17:16:49 +00:00
|
|
|
continue;
|
2006-12-20 18:19:52 +00:00
|
|
|
if (count <= 0)
|
|
|
|
return -1;
|
2006-04-19 17:16:49 +00:00
|
|
|
|
|
|
|
// Read byte
|
|
|
|
*(data_addr++) = twiPtr->TWI_RHR;
|
|
|
|
}
|
|
|
|
|
|
|
|
twiPtr->TWI_CR = AT91C_TWI_STOP;
|
|
|
|
|
|
|
|
status = twiPtr->TWI_SR;
|
|
|
|
|
|
|
|
// Wait transfer is finished
|
|
|
|
while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Read last byte
|
|
|
|
*data_addr = twiPtr->TWI_RHR;
|
2006-12-20 18:19:52 +00:00
|
|
|
return 0;
|
2006-04-19 17:16:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* .KB_C_FN_DEFINITION_START
|
2006-08-10 18:03:50 +00:00
|
|
|
* void WriteEEPROM(unsigned ee_off, char *data_addr, unsigned size)
|
|
|
|
* This global function writes data to the eeprom at ee_off using data
|
2006-04-19 17:16:49 +00:00
|
|
|
* from data_addr for size bytes. Assume the TWI has been initialized.
|
|
|
|
* This function does not utilize the page write mode as the write time is
|
|
|
|
* much greater than the time required to access the device for byte-write
|
|
|
|
* functionality. This allows the function to be much simpler.
|
|
|
|
* .KB_C_FN_DEFINITION_END
|
|
|
|
*/
|
|
|
|
void
|
2006-08-10 18:03:50 +00:00
|
|
|
WriteEEPROM(unsigned ee_off, char *data_addr, unsigned size)
|
2006-04-19 17:16:49 +00:00
|
|
|
{
|
|
|
|
const AT91PS_TWI twiPtr = AT91C_BASE_TWI;
|
|
|
|
unsigned status;
|
|
|
|
char test_data;
|
|
|
|
|
|
|
|
while (size--) {
|
2006-08-10 18:03:50 +00:00
|
|
|
if (!(ee_off & 0x3f))
|
2006-04-19 17:16:49 +00:00
|
|
|
putchar('.');
|
|
|
|
|
|
|
|
// Set the TWI Master Mode Register
|
|
|
|
twiPtr->TWI_MMR = ((TWSI_EEPROM_ADDRESS << 16) |
|
|
|
|
AT91C_TWI_IADRSZ_2_BYTE) & ~AT91C_TWI_MREAD;
|
|
|
|
|
|
|
|
// Set TWI Internal Address Register
|
2006-08-10 18:03:50 +00:00
|
|
|
twiPtr->TWI_IADR = ee_off++;
|
2006-04-19 17:16:49 +00:00
|
|
|
|
|
|
|
status = twiPtr->TWI_SR;
|
|
|
|
|
|
|
|
twiPtr->TWI_THR = *(data_addr++);
|
|
|
|
|
|
|
|
twiPtr->TWI_CR = AT91C_TWI_START;
|
|
|
|
|
|
|
|
// Wait transfer is finished
|
|
|
|
while (!(twiPtr->TWI_SR & AT91C_TWI_TXRDY))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
twiPtr->TWI_CR = AT91C_TWI_STOP;
|
|
|
|
|
|
|
|
status = twiPtr->TWI_SR;
|
|
|
|
|
|
|
|
// Wait transfer is finished
|
|
|
|
while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// wait for write operation to complete
|
2006-08-10 18:03:50 +00:00
|
|
|
ReadEEPROM(ee_off, &test_data, 1);
|
2006-04-19 17:16:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
putchar('\r');
|
|
|
|
putchar('\n');
|
|
|
|
}
|