VxWroks I2C Drivers 文档

Wind River Documentation > VxWorks, 6.9 > BSPs and Drivers > VxBus Device Driver Developer's Guide, 6.9 > Device Driver Porting > I2C Drivers
________________________________________
       
9.2  Overview
VxBus I2C drivers are used to provide a common I2C read/write interface (vxbI2cDevRead( ) and vxbI2cDevWrite( )) between the hardware I2C controller and the various I2C interface devices. However, each I2C controller has a different way to access the device. For example, the Freesacle I2C controllers comply with the I2C timing order strictlyand can separate into several parts according to the I2C timing sequence such as start, read, write, restart, ack, and stop cycle. However, some controllers do this in a completely different way. In these cases, the software should fill several registers first and then the hardware can start the bus transaction, which cannot be split to the I2C timing order strictly.
In VxWorks, I2C drivers support two controller types based on the hardware implementation:
•    Software accessing that complies with the I2C timing sequence standard.
•    Software accessing that does not comply with the I2C timing sequence standard.
For the first type of controller, the general read/write interface is implemented in the library, which reduces redundant code. The controller driver only needs to implement the basic start/write/read/stop functionality. The I2C controller simulated with GPIO can also be used with this model.
For the second type of controller, which is not compatible with the I2C timing sequence, the general read/write interface must be implemented in the controller driver, and the read/write interface in the library must call the driver directly.

9.3  VxBus Driver Methods
All I2C drivers written in accordance with the VxBus model publish a single driver method {vxbI2cControlGet }( ). Within a I2C controller driver, the {vxbI2cControlGet }( ) method is implemented using a driver-provided routine with the following prototype:
 
 
LOCAL VXB_I2C_BUS_CTRL * xxxI2cCtrlGet
    (
    VXB_DEVICE_ID pDev
    )
The VXB_DEVICE_ID parameter describes the specific I2C controller instance within the system.
Within func{vxbI2cControlGet }( ), the driver fills in the contents of the VXB_I2C_BUS_CTRL structure to describe the capabilities of the requested I2C controller. The fields of the structure are listed in this section, along with a description of each field's use.
For the type definition for VXB_I2C_BUS_CTRL, refer to the following header file:
     installDir/vxworks-6.x/target/h/hwif/vxbus/vxbI2cLib.h
The following function pointers are described in 9.7 Implementing Driver Service Routines:
•    STATUS (*VXB_I2C_LOCK_BUS_FUNC)
•    STATUS (*VXB_I2C_START_FUNC)
•    STATUS (*VXB_I2C_READ_FUNC)
•    STATUS (*VXB_I2C_WRITE_FUNC)
•    STATUS (*VXB_I2C_STOP_FUNC)
•    STATUS (*VXB_I2C_UNLOCK_BUS_FUNC)
•    STATUS (*VXB_I2C_DEV_READ)
•    STATUS (*VXB_I2C_DEV_WRITE)
After the driver's func{vxbI2cControlGet }( ) routine is called, the various supported I2C devices associated with the controller driver are available for allocation.
Not all of the above routines need to be implemented in a single driver. As previously mentioned, depending on the type of I2C controller, only the first six service routines or the last two service routines should be implemented.
 

9.4  Header Files
All I2C drivers written in accordance with the VxBus model need to include a single header file to provide the data types required for the driver:
     #include <hwif/vxbus/vxbI2cLib.h>
 
 
 
 

9.6  Initialization
I2C drivers perform their initialization during VxBus initialization as described in the following sections.
Phase 1
During VxBus initialization phase 1 (devInstanceInit( )), I2C controller drivers initialize all of their internal data structures, and perform any required initialization of the I2C controller hardware. Then, the I2C device is created and connected within the bus by calling the i2cBusAnnouoceDevices( ).
The following is a sample of the I2C controller driver for the devInstanceInit( ) routine:
 
 
    LOCAL void xxI2cInstInit
        (
        VXB_DEVICE_ID   pDev
        )
        {
        /* initialize all of their internal data structures and hardware */
     
            ......
     
        /* announce that there's an I2C bus */
     
        vxbBusAnnounce (pDev, VXB_BUSID_I2C);
     
        i2cBusAnnounceDevices (pDev);
     
        return;
        }
Phase 2
During VxBus initialization phase 2 (devInstanceInit2( )), I2C controller drivers should create semaphores (typically two) for future use.
In the typical case, the first semaphore is a mutex semaphore that is used to protect a shared resource. Consider the case where there are two I2C devices that want to access the same bus controller. In this situation, one must be held until the other is done accessing the bus controller.
The second semaphone is used to keep sync between the ISR and the task. In this case, you take (using semTake( )) the binary sync semaphone when the one byte transfer is done. Then, you wait until a hardware interrupt occurs and then give (using semGive( )) the semaphone in an ISR context in order to tell the task that the transfer is complete.
Phase 3
During VxBus initialization phase 3 (devInstanceConnect( )), I2C controller drivers connect their driver-specific ISRs to any interrupt source.
 
 
 
 


9.5  BSP Configuration
When VxBus I2C drivers are used, the BSP should be configured to include INCLUDE_I2C_BUS and the specified I2C controller driver.
To configure individual I2C controller drivers, there are two resource names used: i2cDev and i2cDevNum.
The i2cDev resource points to the beginning of a table containing information about each I2C device within the controller. The table consists of records of the struct i2cDevInputs type.
For example:
 
 
    typedef struct i2cDevInputs
     {
     char * deviceName;
     UINT8 deviceAddr;
     UINT32 flag;
     } I2C_DEV_INPUTS;
The i2cDevInputs structure contains three fields:
deviceName
     Indicates the name of the I2C device.
deviceAddr
     Indicates the address of the I2C device from 1 to 0x7f.
flag
     This field holds a bit-significant value that describes the capabilities of the I2c device. This value is constructed by performing a logical OR operation on the appropriate values from the following #define values found in vxbI2cLib.h:
 
I2C_RDONLY    0x01    /* read only flag */
I2C_WORDADDR    0x02    /* word address flag */
I2C_BYTE_WR_ONLY    0x04    /* byte write only */
I2C_BYTE_RD_ONLY    0x08    /* byte read only */
I2C_RD_EXT_ACK    0x10    /* need a extra ACK when the address is word address */
The following is a sample of the hwconf.c record for the I2C system:
 
 
struct i2cDevInputs i2c0DevTbl[] = {
 
/*
 * Address  Part Number  Size         Description
 * -------- ------------------------------------------------------------------
 * 0x50    24C64       64K-bit   Stores RCW and PBLOADER data.
 * 0x55    24C02        2K-bit   Stores ngPIXIS accessed configuration data.
 * 0x56    24C64       64K-bit   Stores ngPIXIS GMSA program code.
 * 0x57    24C02        2K-bit   Stores board specific data, including MAC
 *                                  addresses, serial number/errata, etc.
 */
    /* add component  DRV_I2C_EEPROM */
 
    { "eeprom_at24c64",  0x50,    I2C_RDONLY | I2C_WORDADDR},
    { "eeprom_at24c02",  0x55,    I2C_RDONLY},
    { "eeprom_at24c64",  0x56,    I2C_RDONLY | I2C_WORDADDR},
    { "eeprom_at24c02",  0x57,    0},
 
    /* add component  DRV_I2C_RTC */
 
    { "rtc_ds3232",      0x68,    0},
 
    /* add component DRV_I2C_GENERIC_DEV */
 
    { "gpio_pca9557",    0x18,    I2C_BYTE_WR_ONLY | I2C_BYTE_RD_ONLY},
 
};
 
const struct hcfResource i2c0Resources[] = {
    { "regBase",    HCF_RES_ADDR,   { (void *)(I2C_BUS_BASE) } },
    { "clkFreq",    HCF_RES_ADDR,   { (void *)sysPlbClkFreqGet } },
    { "busSpeed",   HCF_RES_INT,    { (void *)400000 } },
    { "polling",    HCF_RES_INT,    { (void *)TRUE} },
    { "i2cDev",     HCF_RES_ADDR,   { (void *)&i2c0DevTbl} },
    { "i2cDevNum",  HCF_RES_INT,    { (void *)NELEMENTS(i2c0DevTbl)}},
};
#   define i2c0Num NELEMENTS(i2c0Resources)
As for every resource table, the hcfDeviceList[ ] table must have an entry for the specific resource table:
 
 
{ "fslI2c",     0, VXB_BUSID_PLB,   0,  i2c0Num,        i2c0Resources },
 
    NOTE: Here the "fslI2c" represents the Freescale I2C controller driver, the macro DRV_I2CBUS_FSL must be defined in config.h or your project. Meanwhile, the "i2c0DevTbl" table lists the I2C devices connected on this bus, the relevant I2C device driver must also be defined in your image. For EEPROM, the macro DRV_I2C_EEPROM must be defined in config.h or your project.

9.7  Implementing Driver Service Routines
Once a driver is registered with VxBus and a call is made to the driver's func{vxbI2cControlGet }( ) routine, all subsequent interaction between the system and the driver occurs through the routines whose pointers are returned within the VXB_I2C_BUS_CTRL data structure.
In the routine-specific sections that follow, each of the service routines that can be supported by an I2C driver are described. The controller driver only needs to implement one group, depending on the needs of your controller.
For controllers where software accessing complies with the standard I2C timing sequence, the controller driver must implement the following routines:
•    (*VXB_I2C_LOCK_BUS_FUNC)( )
•    (*VXB_I2C_UNLOCK_BUS_FUNC)( ) 
•    Y(*VXB_I2C_START_FUNC)( )
•    (*VXB_I2C_STOP_FUNC)( )
•    (*VXB_I2C_READ_FUNC)( )
•    (*VXB_I2C_WRITE_FUNC)( )
Note that in these routines, the VxBus instance specified by pDev represents the I2C controller.
In this case, the following routines can be set to NULL:
•    (*VXB_I2C_DEV_READ)( )
•    (*VXB_I2C_DEV_WRITE)( )
For controllers where the software accessing does not comply with the standard I2C timing sequence, the controller driver must implement the following routines:
•    (*VXB_I2C_DEV_READ)( )
•    (*VXB_I2C_DEV_WRITE)( )
Note that in the these service routines, pDev represents the I2C device instance, not the controller instance.
In this case, the following routines can be set to NULL:
•    (*VXB_I2C_LOCK_BUS_FUNC)( )
•    (*VXB_I2C_UNLOCK_BUS_FUNC)( ) 
•    Y(*VXB_I2C_START_FUNC)( )
•    (*VXB_I2C_STOP_FUNC)( )
•    (*VXB_I2C_READ_FUNC)( )
•    (*VXB_I2C_WRITE_FUNC)( )
 
    NOTE: If all of the routines described in the following sections (eight total) are implemented by the controller driver, the public vxbI2cDevRead( ) and vxbI2cDevWrite( ) routines will use (*VXB_I2C_DEV_READ)( ) and (*VXB_I2C_DEV_WRITE)( ).
      
(*VXB_I2C_LOCK_BUS_FUNC)( )
The (*VXB_I2C_LOCK_BUS_FUNC)( ) routine is used to lock the specific I2C bus within a running VxWorks system.
The prototype for this routine is as follows:
 
 
    STATUS (*VXB_I2C_LOCK_BUS_FUNC)
    (
        VXB_DEVICE_ID pInst,    /* IN */
    );
This routine uses a mutual semaphore to lock the bus, allowing for only one device to be accessed on a single bus at the same time.
(*VXB_I2C_UNLOCK_BUS_FUNC)( )
The (*VXB_I2C_UNLOCK_BUS_FUNC)( ) routine is used to release the specific I2C bus within a running VxWorks system.
The prototype for this routine is as follows:
 
 
    STATUS (*VXB_I2C_UNLOCK_BUS_FUNC)
    (
        VXB_DEVICE_ID pInst,    /* IN – specific I2c controller instance */
    );
This routine releases the mutual semaphore to unlock the bus.
(*VXB_I2C_START_FUNC)( )
The (*VXB_I2C_START_FUNC)( ) routine issues an I2C start command to the given controller.
The prototype for this routine is as follows:
 
 
    STATUS (*VXB_I2C_START_FUNC)
    
         VXB_DEVICE_ID pInst,     /* IN */|
         BOOL          restart    /* IN */
     );
This routine starts the I2C transaction. If the parameter restart is set to TRUE, the repeat start is actived.
(*VXB_I2C_STOP_FUNC)( )
The (*VXB_I2C_STOP_FUNC)( ) routine terminates the current transaction and releases the bus. This routine should be the last routine called for any transaction.
The prototype for this routine is as follows:
 
 
    STATUS (*VXB_I2C_STOP_FUNC)
    (
        VXB_DEVICE_ID pInst     /* IN */
    );
(*VXB_I2C_READ_FUNC)( )
The (*VXB_I2C_READ_FUNC)( ) routine reads the number of bytes (specified by the parameter, length) from the I2C device and stores them in a buffer specified by the pBuf parameter. The read begins at an offset--specified by the previous write cycle--earlier in the transaction.
The prototype for this routine is as follows:
 
 
    STATUS (*VXB_I2C_READ_FUNC)
    (
        VXB_DEVICE_ID pDev,
        UINT8 *       pBuf,
        UINT32        length
    );
     
(*VXB_I2C_WRITE_FUNC)( )
The (*VXB_I2C_WRITE_FUNC)( ) routine writes a number of bytes (specified by the parameter, length) to the I2C device from the buffer specified by the pBuf parameter. The write begins at an offset specified previously in the transaction. The argument regType is used to distinguish that the data, address, and command registers are not the same. The argument ack represents whether the ACK signal is received or not.
For the type definition for I2C_REG_TYPES, refer to the following header file:
     installDir/vxworks-6.x/target/h/hwif/vxbus/vxbI2cLib.h
The type definition is as follows:
 
 
    typedef enum
        {
        DEV_TYPE = 0,                       /* device */
        ADDR_TYPE = 1,                      /* address */
        DATA_TYPE = 2                       /* data */
        } I2C_REG_TYPES;
The prototype for this routine is as follows:
 
 
    STATUS (*VXB_I2C_WRITE_FUNC)
    (
        VXB_DEVICE_ID pDev,
        UINT8 *       pBuf,
        UINT32        length,
        I2C_REG_TYPES regType,
        BOOL          ack
    );
(*VXB_I2C_DEV_READ)( )
The (*VXB_I2C_DEV_READ)( ) routine issues the entire I2C read operation. It reads a number of bytes (specified by the parameter, length) from the I2C device and stores them in the buffer specified by pDataBuf. The read begins at an offset specified by startAddr. The instance, pDevice, represents the accessed I2C device. The parameter devAddr represents the device address.
The difference between (*VXB_I2C_READ_FUNC)( ) and (*VXB_I2C_DEV_READ)( ) is that the (*VXB_I2C_READ_FUNC)( ) routine only implements reading data from the I2C device. However, the (*VXB_I2C_DEV_READ)( ) routine implements the entire read operation, including writing the device address, the start transaction, and the read data and stop transactions.
The prototype for the (*VXB_I2C_DEV_READ)( ) routine is as follows:
 
 
    STATUS (*VXB_I2C_DEV_READ)
    (
        VXB_DEVICE_ID   pDevice,
        UINT8           devAddr,
        UINT32          startAddr,
        UINT8 *         pDataBuf,
        UINT32          length
    );
(*VXB_I2C_DEV_WRITE)( )
The (*VXB_I2C_DEV_WRITE)( ) routine issues the entire I2C write operation. It writes a number of bytes (specified by the parameter, length) to the I2C device from the buffer specified by pDataBuf. The write begins at an offset specified by startAddr. The instance, pDevice, represents the accessed I2C device. The parameter devAddr represents the device address.
 
 
    The prototype for this routine is as follows:
    STATUS (*VXB_I2C_DEV_WRITE)
    (
        VXB_DEVICE_ID   pDevice,
        UINT8           devAddr,
        UINT32          startAddr,
        UINT8 *         pDataBuf,
        UINT32          length
    );
 
 
 

9.8  Device Driver
The I2C library supplies the vxbI2cDevRead( ) and vxbI2cDevWrite( ) routines to access all kinds of I2C devices. The prototype for these routines are as follows:
 
 
    STATUS vxbI2cDevRead
        (
        VXB_DEVICE_ID  pDev,
        UINT32                    startAddr,
        UINT8 *                   pDataBuf,
        UINT32                    length
        );
and
 
 
    STATUS vxbI2cDevWrite
     (
     VXB_DEVICE_ID  pDev,
     UINT32                   startAddr,
     UINT8 *                  pDataBuf,
     UINT32                   length
     );
The VXB_DEVICE_ID parameter pDev describes the accessed I2C device instance within the system, not the controller device instance.
Currently, VxBus supports the I2C interface for the EEPROM and RTC devices. The corresponding components are DRV_I2C_EEPROM and DRV_I2C_RTC, respectively. For more information on these interfaces, refer to the EEPROM and RTC driver code.
There are two ways to get the device instance; use vxbInstByNameFind(char*, unit) or call vxBusShow( ) on the target shell, if possible. The I2C device name should be the same as that in the i2cDevTable list in hwconf.c (see 9.5 BSP Configuration).
For example, if you have the following in the i2cDevTable:
 
 
    { "eeprom_at24c64", 0x50, I2C_RDONLY | I2C_WORDADDR},
     To get the eeprom_at24c64 device instance, call:
    vxbInstByNameFind("eeprom_at24c64 ",0)
If you have the following:
 
 
    { "eeprom_at24c02", 0x55, I2C_RDONLY},
     To get the eeprom_at24c02 device instance, call:
    vxbInstByNameFind("eeprom_at24c02",1)
If you have the following:
 
 
    { "eeprom_at24c64", 0x56, I2C_RDONLY | I2C_WORDADDR},
     To get the eeprom_at24c64 device instance, call:
    vxbInstByNameFind("eeprom_at24c64",2)
If you have the following:
 
 
    { "eeprom_at24c02", 0x57, 0},
     To get the eeprom_at24c02 device instance, call:
    vxbInstByNameFind("eeprom_at24c02",3)
 
    NOTE: In the above examples, you can use the I2C EEPROM VxBus driver when the DRV_I2C_EEPROM component is included. For more information, see installDir/vxworks-6.x/target/src/hwif/i2c/vxbI2cEeprom.c.
      
If you have the following:
 
 
    /* add component DRV_I2C_RTC */
    { "rtc_ds3232", 0x68, 0},
     To get the rtc_ds3232 device instance, call:
    vxbInstByNameFind("rtc_ds3232",0)
 
    NOTE: The I2C RTC VxBus driver is used when the component DRV_I2C_RTC is included. For more information, see installDir/vxworks-6.x/target/src/hwif/i2c/vxbI2cRtc.c.
      
If you have the following:
 
 
    /* add component DRV_I2C_GENERIC_DEV */
    { "gpio_pca9557", 0x18, I2C_BYTE_WR_ONLY | I2C_BYTE_RD_ONLY},
     To get the gpio_pca9557 device instance, call:
    vxbInstByNameFind("gpio_pca9557",0)
 
    NOTE: If you want to access an I2C device other than the EEPROM or RTC device, you can write a new VxBus driver for the device or add the component DRV_I2C_GENERIC_DEV to your project. Otherwise, the device will be shown in the orphan devices list.
      
9.8.1  Generic I2C Devices
To access other I2C devices in a simple way, such as with the GPIO device, a generic I2C device driver is provided. The generic I2C driver is included by adding DRV_I2C_GENERIC_DEV component. This component registers a dummy I2C device with VxBus. The I2C device will select this driver when there are no other proper drivers available for the device, which ensures that a VxBus instance is created. Once the instance is created, the vxbI2cDevRead( ) and vxbI2cDevWrite( ) routines are used to access the I2C device.


 
 
 
 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值