📄 eeprom_i2c.c
字号:
/***********************************************************************
* $Workfile: eeprom_i2c.c $
* $Revision: 1.2 $
* $Author: NambiarA $
* $Date: Dec 30 2004 14:05:30 $
*
* Project: LH79524 EEPROM test
*
* Description: This file contains the basic eeprom tests where the
* I2C interface is a 7 bit Master. These tests contain
* all code required to interface with an external EEPROM.
*
* This test write/read/compare with exactly one sector of
* the EEPROM. If there is a boot sector in the EEPROM,
* it will be destroyed.
*
* This test assumes the presence of a terminal emulator
* connected to the first com port in order to display
* the results of the test.
*
* Local Includes:
*
* Revision History:
* $Log:: $
*
* Rev 1.2 Dec 30 2004 14:05:30 NambiarA
* Modified send_eeprom_address for Multimaster Mode operation
*
* Rev 1.1 Oct 14 2004 17:52:36 TilburyC
* Fixed problem with reading eeprom at 400kbpS
*
* Rev 1.0 Oct 13 2004 16:58:52 TilburyC
* Initial revision.
*
*
***********************************************************************
*
* Copyright (c) 2004 Sharp Microelectronics of the Americas
*
* All rights reserved
*
* SHARP MICROELECTRONICS OF THE AMERICAS MAKES NO REPRESENTATION
* OR WARRANTIES WITH RESPECT TO THE PERFORMANCE OF THIS SOFTWARE,
* AND SPECIFICALLY DISCLAIMS ANY RESPONSIBILITY FOR ANY DAMAGES,
* SPECIAL OR CONSEQUENTIAL, CONNECTED WITH THE USE OF THIS SOFTWARE.
*
* SHARP MICROELECTRONICS OF THE AMERICAS PROVIDES THIS SOFTWARE SOLELY
* FOR THE PURPOSE OF SOFTWARE DEVELOPMENT INCORPORATING THE USE OF A
* SHARP MICROCONTROLLER OR SYSTEM-ON-CHIP PRODUCT. USE OF THIS SOURCE
* FILE IMPLIES ACCEPTANCE OF THESE CONDITIONS.
*
**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include "sdk79524_board.h"
#include "lh79524_iocon.h"
#include "lh79524_gpio.h"
#include "lh79524_int_driver.h"
#include "eeprom_i2c.h"
#include "console.h"
#define I2C_EEPROM_ADDR 0xA0
static INT_32 dev_i2c;
/**********************************************************************
*
* Function: init_i2c()
*
* Purpose:
* Initialize the i2c interface for read and write using
* interrupts.
*
* Processing:
* See comments below.
*
* Parameters: None
*
* Outputs:
* I2C configuration, VIC configuration, and IOCON regs.
*
* Returns:
* 0 upon success, otherwise retuns a non zero value that
* indicates an error has happened.
*
* Notes:
* 1. This funciton must be called before any I2C function.
* 2. This function depends on having the VIC interface already
* open
*
*********************************************************************/
INT_32 init_i2c(void)
{
PFV handler;
/* open the I2C port with default parameters. Sets it to 7
bit master at the slow speed */
if((dev_i2c = i2c_open(I2C_BASE, 0)) == 0)
return _ERROR;
i2c_ioctl(dev_i2c, I2C_IOCTL_GET_ISR, (INT_32)&handler);
i2c_ioctl(dev_i2c, I2C_IOCTL_ENA_INTERRUPT, 0);
/* instantiate the interrupt handler */
create_irq_interrupt(VIC_I2C, VIC_VECT_1, handler);
/* Configure IOCON pin multiplexing for I2C operation */
/* clear the configuration bits in case the were being used for
something else */
IOCON->mux_ctl_4 &= IOCON_MUX_MASK(IOCON_RES4_PA7_CTCAP2B_CTCMP2B_SCL);
IOCON->mux_ctl_4 &= IOCON_MUX_MASK(IOCON_RES4_PA6_CTCAP2A_CTCMP2A_SDA);
/* set configuration the bits */
IOCON->mux_ctl_4 |= IOCON_MUX4_SCL;
IOCON->mux_ctl_4 |= IOCON_MUX4_SDA;
/* clear the resistor control bits, setting them for floating
behavior */
IOCON->res_ctl_4 &= IOCON_MUX_MASK(IOCON_RES4_PA7_CTCAP2B_CTCMP2B_SCL);
IOCON->res_ctl_4 &= IOCON_MUX_MASK(IOCON_RES4_PA6_CTCAP2A_CTCMP2A_SDA);
return _NO_ERROR;
}
/**********************************************************************
*
* Function: init_eeprom()
*
* Purpose:
* Initialize the i2c interface for read and write using
* interrupts. Then init the eeprom and get it ready for
* read and write operations.
*
* Processing:
* See comments below.
*
* Parameters:
* speed - If speed is 0, then use low speed (100kbpS) otherwise,
* use the high speed (400kbpS).
*
* Outputs:
* I2C configuration, VIC configuration, and IOCON regs.
*
* Returns:
* 0 upon success, otherwise retuns a non zero value that
* indicates an error has happened.
*
* Notes:
* 1. This funciton must be called before any I2C function.
* 2. This function depends on having the VIC interface already
* open
*
*********************************************************************/
INT_32 init_eeprom(void)
{
/* set up the i2c interface */
if(init_i2c() != _NO_ERROR)
return _ERROR;
return _NO_ERROR;
}
/**********************************************************************
*
* Function: read_eeprom_buffer()
*
* Purpose:
* Read a buffer full of data from the EEPROM.
*
* Processing:
* See comments below
*
* Parameters:
* buffer - location to put the data into
* buflen - maximum number of bytes that can be written
* into the buffer
* Outputs:
* none
*
* Returns:
* The number of bytes actually read from the EEPROM. If there
* was an error, then return a negative number.
*
* Notes:
* none
*
*********************************************************************/
INT_32 read_eeprom_buffer(INT_32 addr, CHAR *buffer, INT_32 buflen)
{
int idx;
/* wait for the I2C bus to be idle */
if(i2c_ioctl(dev_i2c, I2C_IOCTL_WAIT_IDLE, 0) == _ERROR)
{
while(1);
return -1;
}
/* send the address of the EEPROM with the write bit cleared */
//if(i2c_write(dev_i2c, I2C_EEPROM_ADDR) != 1)
if(send_eeprom_address() == _ERROR)
{
while(1);
return -1;
}
/* send the first word address (MSBs of address) */
if(i2c_write(dev_i2c, (addr >> 8), 0) != 1)
{
while(1);
return -1;
}
/* send the second word address (LSBs of address) Set the Stop so
the direction can be reversed */
if(i2c_write(dev_i2c, (addr & 0xFF), I2C_RESTART) != 1)
{
while(1);
return -1;
}
/* send the address of the EEPROM with the read bit set */
if(i2c_write(dev_i2c, I2C_EEPROM_ADDR | 0x01, I2C_READ) != 1)
{
while(1);
return -1;
}
/* read the entire buffer */
for(idx = 0; idx < buflen - 1; idx++)
{
if(i2c_read(dev_i2c, (CHAR *)&buffer[idx], I2C_READ) != 1)
{
while(1);
return -1;
}
}
/* set the stop state after the last byte */
if(i2c_read(dev_i2c, (CHAR *)&buffer[idx++], I2C_READ|I2C_STOP) != 1)
{
while(1);
return -1;
}
return idx;
}
/**********************************************************************
*
* Function: write_eeprom_buffer()
*
* Purpose:
* Write a buffer full of data to the EEPROM.
*
* Processing:
* See comments below
*
* Parameters:
* buffer - location to take the data from
* buflen - number of bytes that are in the buffer.
*
* Outputs:
* none
*
* Returns:
* The number of bytes actually written to the EEPROM. If there
* was an error, then return a negative number.
*
* Notes:
* none
*
*********************************************************************/
INT_32 write_eeprom_buffer(INT_32 addr, CHAR *buffer, INT_32 buflen)
{
INT_32 idx;
/* wait for the I2C bus to be idle */
if(i2c_ioctl(dev_i2c, I2C_IOCTL_WAIT_IDLE, 0) == _ERROR)
{
while(1);
return -1;
}
/* send the address of the EEPROM with the write bit cleared */
if(send_eeprom_address() == _ERROR)
{
while(1);
return -1;
}
/* send the first word address (MSBs of address) */
if(i2c_write(dev_i2c, (addr >> 8), 0) != 1)
{
while(1);
return -1;
}
/* send the second word address (LSBs of address) */
if(i2c_write(dev_i2c, (addr & 0xFF), 0) != 1)
{
while(1);
return -1;
}
/* write the burst of bytes, one-at-a-time */
for(idx = 0; idx < buflen-1; idx++)
{
if(i2c_write(dev_i2c, buffer[idx], 0) != 1)
{
while(1);
return -1;
}
}
/* send the last byte to write with the stop bit set */
if(i2c_write(dev_i2c, buffer[idx++], I2C_STOP) != 1)
{
while(1);
return -1;
}
return idx;
}
/**********************************************************************
*
* Function: read_eeprom_byte()
*
* Purpose:
* Read a byte of data from the EEPROM.
*
* Processing:
* See comments below
*
* Parameters:
* addr - location in the eeprom to read from
* buffer - location to put the data into
*
* Outputs:
* none
*
* Returns:
* 1 upon success. If there was an error, then return a
* negative number.
*
* Notes:
* none
*
*********************************************************************/
INT_32 read_eeprom_byte(INT_32 addr, CHAR *buffer)
{
/* wait for the I2C bus to be idle */
if(i2c_ioctl(dev_i2c, I2C_IOCTL_WAIT_IDLE, 0) == _ERROR)
{
while(1);
return -1;
}
/* send the address of the EEPROM with the write bit cleared */
if(send_eeprom_address() == _ERROR)
{
while(1);
return -1;
}
/* send the first word address (MSBs of address) */
if(i2c_write(dev_i2c, (addr >> 8), 0) != 1)
{
while(1);
return -1;
}
/* send the second word address (LSBs of address) Set the Stop so
the direction can be reversed */
if(i2c_write(dev_i2c, (addr & 0xFF), I2C_RESTART) != 1)
{
while(1);
return -1;
}
/* send the address of the EEPROM with the read bit set */
if(i2c_write(dev_i2c, I2C_EEPROM_ADDR | 0x01, I2C_READ) != 1)
{
while(1);
return -1;
}
if(i2c_read(dev_i2c, buffer, I2C_STOP|I2C_READ) != 1)
{
while(1);
return -1;
}
return 1;
}
/**********************************************************************
*
* Function: write_eeprom_byte()
*
* Purpose:
* Write a byte of data to the EEPROM.
*
* Processing:
* See comments below
*
* Parameters:
* addr - location in the eeprom to write to
* buffer - the data to write
*
* Outputs:
* none
*
* Returns:
* 1 upon success. If there was an error, then return a
* negative number.
*
* Notes:
* none
*
*********************************************************************/
INT_32 write_eeprom_byte(INT_32 addr, CHAR buffer)
{
/* wait for the I2C bus to be idle */
if(i2c_ioctl(dev_i2c, I2C_IOCTL_WAIT_IDLE, 0) == _ERROR)
{
while(1);
return -1;
}
/* send the address of the EEPROM with the write bit cleared */
if(send_eeprom_address() == _ERROR)
{
while(1);
return -1;
}
/* send the first word address (MSBs of address) */
if(i2c_write(dev_i2c, (addr >> 8), 0) != 1)
{
while(1);
return -1;
}
/* send the second word address (LSBs of address) */
if(i2c_write(dev_i2c, (addr & 0xFF), 0) != 1)
{
while(1);
return -1;
}
/* send the byte to write with the stop bit set */
if(i2c_write(dev_i2c, buffer, I2C_STOP) != 1)
{
while(1);
return -1;
}
return 1;
}
/**********************************************************************
*
* Function: send_eeprom_address()
*
* Purpose:
* Send the eeprom address, waiting for the eeprom to not be
* busy.
*
* Processing:
* Send a fake address to the eeprom. If it is busy, then it
* will NACK the address. That will be discovered by looking
* for a new TX_ABORT from the interface. If the fake address
* is sent without recieving a TX_ABORT in response, then the
* real address is sent and processing continues.
*
* Parameters:
* none
*
* Outputs:
* none
*
* Returns:
* _NO_ERROR if the EEPROM address was sent successfully. If the
* address could not be sent, then return _ERROR.
*
* Notes:
* If there is a catastrophic problem, this function will loop
* forever.
*
*********************************************************************/
INT_32 send_eeprom_address(void)
{
UNS_32 old_aborts, new_aborts;
do
{
/* find out the current number of TX aborts */
i2c_ioctl(dev_i2c, I2C_IOCTL_GET_TXABORTS, (UNS_32)&old_aborts);
/*it is quite possible that we might get an error
so we check for aborts*/
i2c_write(dev_i2c, I2C_EEPROM_ADDR, I2C_STOP);
/* TX aborts are asserted after the interface is idle. */
if(i2c_ioctl(dev_i2c, I2C_IOCTL_WAIT_IDLE, 0) == _NO_ERROR)
{
/* find if a new TX abort was asserted */
i2c_ioctl(dev_i2c, I2C_IOCTL_GET_TXABORTS, (UNS_32)&new_aborts);
}
else
{
/* the isterface cannot go to idle state */
while(1);
return _ERROR;
}
/* while there are new tx aborts being generated */
} while(old_aborts != new_aborts);
/* send the real address */
if(i2c_write(dev_i2c, I2C_EEPROM_ADDR, 0) != 1)
{
/* the real address could not be written */
while(1);
return _ERROR;
}
return _NO_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -