⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 24c16nvram.c

📁 au1500开发的应用程序
💻 C
字号:
/* 24c16NvRam.c - 24c16 EEPROM NVRAM driver */

/* Copyright 2002-2004 Founder Communications, Inc. */

/*
modification history
--------------------
01a,11apr05, fhchen  written
*/

/*
DESCRIPTION

This file provides routines to read/write on board 24C16 EEPROM, and implement
sysNvRamSet/sysNvRamGet.

On V100R001 CPE board, GPIO205 is connected to SDA, GPIO206 connected to SCL,
GPIO208 connected to WP.

NOTE:
- Only byte write and random read supported.
- Timing is critical, use a 2-channel oscilloscope to view SDA and SCL.

*/

/* includes */

#include <vxWorks.h>
#include "24c16NvRam.h"
#include "sysGpio.h"
#include "config.h"

#ifdef INCLUDE_EEPROM

/* forward declaration */

LOCAL void i2cDelayNs(UINT32 ns);
LOCAL void i2cDelayUs(UINT32 us);
LOCAL void i2cDelayMs(UINT32 ms);

/* delay macro */

#define I2C_DELAY_NS(n)         i2cDelayNs(n)
#define I2C_DELAY_US(n)         i2cDelayUs(n) 
#define I2C_DELAY_MS(n)         i2cDelayMs(n)

/* gpio op macro */

#define I2C_SET_SDA(level)      (sysGpioWrite(AT24C16_PORT, AT24C16_I2C_SDA, level))
#define I2C_SET_SCL(level)      (sysGpioWrite(AT24C16_PORT, AT24C16_I2C_SCL, level))
#define I2C_GET_SDA(level)      (level = sysGpioRead(AT24C16_PORT, AT24C16_I2C_SDA)) 

/* send op macro */

#define I2C_SEND_START          i2cSendStart
#define I2C_SEND_STOP           i2cSendStop
#define I2C_SEND_NOACK          i2cSendNoAck

#define I2C_SEND_BIT(level)                     \
            {                                   \
                                                \
            /* 1 */                             \
                                                \
            I2C_SET_SCL(LOGIC_LOW);             \
            I2C_DELAY_US(1);                    \
                                                \
            I2C_SET_SDA(level);                 \
            I2C_DELAY_US(AT24C16_DELAY);        \
                                                \
            /* 2 */                             \
                                                \
            I2C_SET_SCL(LOGIC_HIGH);            \
            I2C_DELAY_US(AT24C16_DELAY);        \
           }

#define I2C_SEND_BYTE(byteVal)  i2cSendByte(byteVal)

/* receive op macro */

#define I2C_RECV_ACK            i2cRecvAck

#define I2C_RECV_BIT(level)                     \
            {                                   \
                                                \
            /* 1 */                             \
                                                \
            I2C_SET_SCL(LOGIC_HIGH);            \
                                                \
            I2C_GET_SDA(level);                 \
            I2C_DELAY_US(AT24C16_DELAY);        \
                                                \
            /* 2 */                             \
                                                \
            I2C_SET_SCL(LOGIC_LOW);             \
            I2C_DELAY_US(AT24C16_DELAY);        \
            }

#define I2C_RECV_BYTE           i2cRecvByte

/***********************************************************************
*
* i2cDelayNs - delay specified ns*10 nano-second
*
* Delay 10ns routine needed to get correct timing of I2C
*
* RETURNS: N/A
*/

LOCAL void i2cDelayNs
(
    UINT32 ns                                /* 10ns to delay */
    )
    {
#if defined(DELAY_10NS)
    DELAY_10NS(ns);
#endif 
    }

/***********************************************************************
*
* i2cDelayUs - delay specified us
*
* Delay us routine needed to get correct timing of I2C
*
* RETURNS: N/A
*/

LOCAL void i2cDelayUs
(
    UINT32 us                                /* us to delay */
    )
    {
#if defined(DELAY_US)
    DELAY_US(us);
#endif 
    }

/***********************************************************************
*
* i2cDelayMs - delay specified ms
*
* Delay ms routine needed to get correct timing of I2C
*
* RETURNS: N/A
*/

LOCAL void i2cDelayMs
(
    UINT32 ms                                /* us to delay */
    )
    {
#if defined(DELAY_MS)
    DELAY_MS(ms);
#endif 
    }

/***********************************************************************
*
* i2cSendStart - send I2C start condition
*
* This routine generate a I2C start condition, which is defined as: SDA
* change from high to low while SCL is high.
*
* RETURNS: N/A
*/

LOCAL void i2cSendStart(void)
    {

    /* 1 */
    
    I2C_SET_SCL(LOGIC_LOW);
    I2C_DELAY_US(AT24C16_DELAY); 

    I2C_SET_SDA(LOGIC_HIGH);
    
    /* 2 */

    I2C_SET_SCL(LOGIC_HIGH);

    /* pull SDA high to low here */

    I2C_DELAY_US(1);
    I2C_SET_SDA(LOGIC_LOW);
    
    I2C_DELAY_US(AT24C16_DELAY); 
    
    /* 3 */

    I2C_SET_SCL(LOGIC_LOW);
    I2C_DELAY_US(AT24C16_DELAY); 
    }

/***********************************************************************
*
* i2cSendStop - send I2C stop condition
*
* This routine generate a I2C stop condition, which is defined as: SDA
* change from low to high while SCL is high.
*
* RETURNS: N/A
*/

LOCAL void i2cSendStop(void)
    {

    /* 1 */

    I2C_SET_SCL(LOGIC_LOW);
    I2C_DELAY_US(AT24C16_DELAY);

    I2C_SET_SDA(LOGIC_LOW);

    /* 2 */

    I2C_SET_SCL(LOGIC_HIGH);

    /* pull SDA low to high here */

    I2C_DELAY_US(1);
    I2C_SET_SDA(LOGIC_HIGH);
    
    I2C_DELAY_US(AT24C16_DELAY);

    /* post */

    I2C_SET_SCL(LOGIC_HIGH);
    I2C_SET_SDA(LOGIC_HIGH);    
    }

/***********************************************************************
*
* i2cSendNoAck - send I2C No Ack
*
* This routine generate a I2C No Ack, which is defined as: SDA
* is high while SCL is in high.
*
* RETURNS: N/A
*/

LOCAL void i2cSendNoAck(void)
    {

    /* 1 */

    I2C_SET_SCL(LOGIC_LOW);
    I2C_SET_SDA(LOGIC_LOW);
    I2C_DELAY_US(1);
    I2C_SET_SDA(LOGIC_HIGH);
    I2C_DELAY_US(1);

    /* 2 */

    I2C_SET_SCL(LOGIC_HIGH);
    I2C_DELAY_US(AT24C16_DELAY);

    /* 3 */

    I2C_SET_SCL(LOGIC_LOW);
    I2C_DELAY_US(1);
    I2C_SET_SDA(LOGIC_LOW);
    I2C_DELAY_US(1);
    }

/***********************************************************************
*
* i2cSendByte - send 8 bits on SDA
*
* This routine send 8 bits via SDA, whatever it is, data or adress etc.
*
* RETURNS: N/A
*/

LOCAL void i2cSendByte(unsigned char byteVal)
    {
    unsigned char i = 8;
    unsigned char bitVal;

    /* send data */
    
    for(i = 8; i > 0; i--)
        {
        bitVal = (byteVal >> (i - 1)) & 0x1;
        I2C_SEND_BIT(bitVal);
        }

    /* post. !wave is not so good here! REFINE IT */

    I2C_SET_SCL(LOGIC_LOW);
    I2C_DELAY_US(1);
    I2C_SET_SDA(LOGIC_LOW);
    }

/***********************************************************************
*
* i2cRecvAck - receive I2C Ack
*
* This routine receive an I2C Ack, which is defined as: SDA
* is low while SCL is in high.
*
* RETURNS: OK or ERROR if it is not an ACK
*/

LOCAL STATUS i2cRecvAck(void)
    {
    int level;

    /* pre: set SDA as input */

    I2C_GET_SDA(level);

    /* 1 */
    
    I2C_SET_SCL(LOGIC_LOW);
    I2C_DELAY_US(AT24C16_DELAY); 

    /* 2 */

    I2C_SET_SCL(LOGIC_HIGH);
    I2C_DELAY_US(1); 
    I2C_GET_SDA(level);
    I2C_DELAY_US(AT24C16_DELAY);

    /* post */

    I2C_SET_SCL(LOGIC_LOW);
    I2C_SET_SDA(LOGIC_LOW);                  /* set SDA as output */
    I2C_DELAY_US(1);                         /* needed? */
    
    return ((LOGIC_HIGH == level) ? ERROR : OK);
    }

/***********************************************************************
*
* i2cRecvByte - receive 8 bits on SDA
*
* This routine receive 8 bits on SDA.
*
* RETURNS: OK or ERROR if it is not an ACK
*/

LOCAL char i2cRecvByte(void)
    {
    unsigned char i = 8;
    unsigned char bitVal = 0;
    char byteVal = 0;
    
    /* pre */

    I2C_SET_SCL(LOGIC_LOW);

    /* get data */

    for(i = 8; i > 0; i--)
        {
        I2C_RECV_BIT(bitVal);
        byteVal |= ((bitVal == LOGIC_HIGH) ? 0x1 : 0x0);

        if(i != 1)
            byteVal <<= 1;
        }

    return byteVal;
    }

/***********************************************************************
*
* at24c16Init - initialize resources used by this driver
*
* This routine set SDA and SCL to low, and disable protection.
*
* RETURNS: N/A
*/

void at24c16Init(void)
    {
    I2C_SET_SDA(LOGIC_LOW);
    I2C_SET_SCL(LOGIC_LOW);
    at24c16UnProtect();
    }

/***********************************************************************
*
* at24c16UnProtect - disable protection
*
* This routine set WP pin to GND(low) to enable read and write.
*
* RETURNS: N/A
*/

void at24c16UnProtect(void)
    {
    sysGpioWrite(AT24C16_PORT, AT24C16_PIN_PROTECT, AT24C16_LOGIC_UNPROTECT);
    }

/***********************************************************************
*
* at24c16ReadByte - read a byte
*
* This routine read a byte from 24c16 using Random Read Mode.
*
* RETURNS: OK or ERROR
*/

STATUS at24c16ReadByte
(
    int address,                             /* address to read */
    char * pByte                             /* byte just read */
    )
    {
    /* I2C device address, upper 3 bit address of 24c16 and R/W */

    char tempRead = ((AT24C16_I2C_ADDRESS << 4) |
                      (char)((address & 0x0700) >> 7) |
                      AT24C16_I2C_READ);

    char tempWrite = ((AT24C16_I2C_ADDRESS << 4) |
                      (char)((address & 0x0700) >> 7) |
                      AT24C16_I2C_WRITE);    

    if((address < 0) || (address > AT24C16_MAX_SIZE) || (NULL == pByte))
       return ERROR;

    /*
     * initiate a dummy write cycle
     */

    /* send start condition */

    I2C_SEND_START();

   /* send preamble and recv ack */

    I2C_SEND_BYTE(tempWrite), I2C_RECV_ACK();

    /* send lower 8 bit address and recv ack */

    I2C_SEND_BYTE(address & 0xFF), I2C_RECV_ACK();
   
    /*
     * initiate a real read cycle
     */

    /* send start condition */

    I2C_SEND_START();

    /* send preamble and recv ack */

    I2C_SEND_BYTE(tempRead), I2C_RECV_ACK();

    /* recv the byte */

    *pByte = I2C_RECV_BYTE();

    /* send NOACK */

    I2C_SEND_NOACK();

    /* send stop condition */

    I2C_SEND_STOP();

    return OK;
    }

/***********************************************************************
*
* at24c16WriteByte - write a byte
*
* This routine write a byte to 24c16 using Byte Write mode.
*
* RETURNS: OK or ERROR
*/

STATUS at24c16WriteByte
(
    int address,                             /* address to write */
    char byteVal                             /* byte to write  */
    )
    {

    /* I2C device address, upper 3 bit address of 24c16 and R/W */

    char temp = ((AT24C16_I2C_ADDRESS << 4) |
                  (char)((address & 0x0700) >> 7) |
                 AT24C16_I2C_WRITE);
    
    if((address < 0) || (address > AT24C16_MAX_SIZE))
        return ERROR;

    /* send start condition */

    I2C_SEND_START();

    /* send preamble and recv ack */

    I2C_SEND_BYTE(temp), I2C_RECV_ACK();

    /* send lower 8 bit address and recv ack */

    I2C_SEND_BYTE(address & 0xFF), I2C_RECV_ACK();

    /* send data to be written and recv ack */

    I2C_SEND_BYTE(byteVal), I2C_RECV_ACK();

    /* send stop condition */

    I2C_SEND_STOP();

    /* delay for Twr */

    I2C_DELAY_MS(AT24C16_Twr);

    return OK;
    }

/***********************************************************************
*
* at24c16Erase - erase 24c16
*
* This routine erase 24c16 using the specified character.
*
* RETURNS: OK or ERROR
*/

STATUS at24c16Erase(char byteVal)
    {
    int address;

    for(address = 0; address < AT24C16_MAX_SIZE; address++)
        {
        at24c16WriteByte(address, byteVal);
        }

    return OK;
    }

#if (NV_RAM_SIZE != NONE)

/*******************************************************************************
*
* sysNvRamSet - write to non-volatile RAM
*
* This routine copies a specified string into non-volatile RAM.
*
* RETURNS: OK, or ERROR if access is outside the non-volatile RAM range.
*
* SEE ALSO: sysNvRamGet()
*/

STATUS sysNvRamSet
    (
    char *string,     /* string to be copied into non-volatile RAM */
    int strLen,       /* maximum number of bytes to copy           */
    int offset        /* byte offset into non-volatile RAM         */
    )
    {

    char data;
    char temp;
    
    offset += NV_BOOT_OFFSET;   /* boot line begins at <offset> = 0 */

    if ((offset < 0) || (strLen < 0) || ((offset + strLen) > NV_RAM_SIZE))
        return ERROR;

    while (strLen--)
	{
	data = *string;

	at24c16WriteByte(offset, data);

	/* verify data */

        at24c16ReadByte(offset, &temp);

	if (temp!= (UCHAR)data)
	    {
            return ERROR;
	    }

	string++, offset++;
	}

    return OK;
    }

/******************************************************************************
*
* sysNvRamGet - get the contents of non-volatile RAM
*
* This routine copies the contents of non-volatile memory into a specified
* string.  The string is terminated with an EOS.
*
* RETURNS: OK, or ERROR if access is outside the non-volatile RAM range.
*
* SEE ALSO: sysNvRamSet()
*/

STATUS sysNvRamGet
    (
    char *string,    /* where to copy non-volatile RAM    */
    int strLen,      /* maximum number of bytes to copy   */
    int offset       /* byte offset into non-volatile RAM */
    )
    {
    offset += NV_BOOT_OFFSET;   /* boot line begins at <offset> = 0 */

    if ((offset < 0) || (strLen < 0) || ((offset + strLen) > NV_RAM_SIZE))
        return (ERROR);

    while (strLen--)
	{
	at24c16ReadByte(offset, string);
	string++, offset++;
	}
    *string = EOS;

    return (OK);
    }

#endif  /* NV_RAM_SIZE != NONE */

#endif  /* INCLUDE_EEPROM */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -