123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- /******************************************************************//**
- * @file drv_iic.c
- * @brief Serial API of RT-Thread RTOS for EFM32
- * COPYRIGHT (C) 2011, RT-Thread Development Team
- * @author onelife
- * @version 0.4 beta
- **********************************************************************
- * @section License
- * The license and distribution terms for this file may be found in the file LICENSE in this
- * distribution or at http://www.rt-thread.org/license/LICENSE
- **********************************************************************
- * @section Change Logs
- * Date Author Notes
- * 2011-01-06 onelife Initial creation for EFM32
- *********************************************************************/
- /******************************************************************//**
- * @addtogroup efm32
- * @{
- *********************************************************************/
- /* Includes -------------------------------------------------------------------*/
- #include "board.h"
- #include "drv_iic.h"
- /* Private typedef -------------------------------------------------------------*/
- /* Private define --------------------------------------------------------------*/
- /* Private macro --------------------------------------------------------------*/
- /* Private variables ------------------------------------------------------------*/
- #ifdef RT_USING_IIC0
- #if (RT_USING_IIC0 > 3)
- #error "The location number range of IIC is 0~3"
- #endif
- struct rt_device iic0_device;
- #endif
- #ifdef RT_USING_IIC1
- #if (RT_USING_IIC1 > 3)
- #error "The location number range of IIC is 0~3"
- #endif
- struct rt_device iic1_device;
- #endif
- /* Private function prototypes ---------------------------------------------------*/
- /* Private functions ------------------------------------------------------------*/
- /******************************************************************//**
- * @brief
- * Initialize IIC device
- *
- * @details
- *
- * @note
- *
- * @param[in] dev
- * Pointer to device descriptor
- *
- * @return
- * Error code
- *********************************************************************/
- static rt_err_t rt_iic_init (rt_device_t dev)
- {
- struct efm32_iic_device_t* iic;
- iic = (struct efm32_iic_device_t*)dev->user_data;
- if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
- {
- /* Enable IIC */
- I2C_Enable(iic->iic_device, true);
- dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
- }
- return RT_EOK;
- }
- /******************************************************************//**
- * @brief
- * Read from IIC device
- *
- * @details
- *
- * @note
- *
- * @param[in] dev
- * Pointer to device descriptor
- *
- * @param[in] pos
- * Offset
- *
- * @param[in] buffer
- * Poniter to the buffer
- *
- * @param[in] size
- * Buffer size in byte
- *
- * @return
- * Error code
- *********************************************************************/
- static rt_size_t rt_iic_read (
- rt_device_t dev,
- rt_off_t pos,
- void* buffer,
- rt_size_t size)
- {
- rt_err_t err_code;
- rt_size_t read_size;
- struct efm32_iic_device_t* iic;
- I2C_TransferSeq_TypeDef seq;
- I2C_TransferReturn_TypeDef ret;
- rt_uint8_t data[1];
- if (!size)
- {
- return 0;
- }
- err_code = RT_EOK;
- read_size = 0;
- iic = (struct efm32_iic_device_t*)dev->user_data;
- data[0] = (rt_uint8_t)(pos & 0x000000FF);
- if (iic->is_master)
- {
- seq.addr = iic->slave_address;
- seq.flags = I2C_FLAG_WRITE_READ;
- /* Select register to be read */
- seq.buf[0].data = data;
- seq.buf[0].len = 1;
- /* Select location/length of data to be read */
- seq.buf[1].data = (rt_uint8_t *)buffer;
- seq.buf[1].len = size;
- }
- else
- {
- //TODO
- }
- /* Do a polled transfer */
- ret = I2C_TransferInit(iic->iic_device, &seq);
- while (ret == i2cTransferInProgress)
- {
- ret = I2C_Transfer(iic->iic_device);
- }
- if (ret != i2cTransferDone)
- {
- #ifdef RT_IIC_DEBUG
- rt_kprintf("IIC0 read error: %x\n", ret);
- rt_kprintf("IIC0 read address: %x\n", seq.addr);
- rt_kprintf("IIC0 read data0: %x -> %x\n", seq.buf[0].data, *seq.buf[0].data);
- rt_kprintf("IIC0 read len0: %x\n", seq.buf[0].len);
- rt_kprintf("IIC0 read data1: %x -> %x\n", seq.buf[1].data, *seq.buf[1].data);
- rt_kprintf("IIC0 read len1: %x\n", seq.buf[1].len);
- #endif
- err_code = (rt_err_t)ret;
- }
- else
- {
- #ifdef RT_IIC_DEBUG
- rt_kprintf("IIC0 read size: %d\n", size);
- #endif
- read_size = size;
- }
- /* set error code */
- rt_set_errno(err_code);
- return read_size;
- }
- /******************************************************************//**
- * @brief
- * Write to IIC device
- *
- * @details
- *
- * @note
- *
- * @param[in] dev
- * Pointer to device descriptor
- *
- * @param[in] pos
- * Offset
- *
- * @param[in] buffer
- * Poniter to the buffer
- *
- * @param[in] size
- * Buffer size in byte
- *
- * @return
- * Error code
- *********************************************************************/
- static rt_size_t rt_iic_write (
- rt_device_t dev,
- rt_off_t pos,
- const void* buffer,
- rt_size_t size)
- {
- rt_err_t err_code;
- rt_size_t write_size;
- struct efm32_iic_device_t* iic;
- I2C_TransferSeq_TypeDef seq;
- I2C_TransferReturn_TypeDef ret;
- //rt_uint8_t data[1];
- if (!size)
- {
- return 0;
- }
- err_code = RT_EOK;
- write_size = 0;
- iic = (struct efm32_iic_device_t*)dev->user_data;
- //data[0] = (rt_uint8_t)(pos & 0x000000FF);
- if (iic->is_master)
- {
- seq.addr = iic->slave_address;
- if (pos != (rt_off_t)(-1))
- {
- seq.flags = I2C_FLAG_WRITE_WRITE;
- /* Select register to be write */
- seq.buf[0].data = (rt_uint8_t *)(pos & 0x000000FF);
- seq.buf[0].len = 1;
- /* Select location/length of data to be write */
- seq.buf[1].data = (rt_uint8_t *)buffer;
- seq.buf[1].len = size;
- }
- else
- {
- seq.flags = I2C_FLAG_WRITE;
- /* Select location/length of data to be write */
- seq.buf[0].data = (rt_uint8_t *)buffer;
- seq.buf[0].len = size;
- }
- }
- else
- {
- //TODO
- }
- /* Do a polled transfer */
- ret = I2C_TransferInit(iic->iic_device, &seq);
- while (ret == i2cTransferInProgress)
- {
- ret = I2C_Transfer(iic->iic_device);
- }
-
- if (ret != i2cTransferDone)
- {
- err_code = (rt_err_t)ret;
- }
- else
- {
- write_size = size;
- }
- /* set error code */
- rt_set_errno(err_code);
- return write_size;
- }
- /******************************************************************//**
- * @brief
- * Configure IIC device
- *
- * @details
- *
- * @note
- *
- * @param[in] dev
- * Pointer to device descriptor
- *
- * @param[in] cmd
- * IIC control command
- *
- * @param[in] args
- * Arguments
- *
- * @return
- * Error code
- *********************************************************************/
- static rt_err_t rt_iic_control (
- rt_device_t dev,
- rt_uint8_t cmd,
- void *args)
- {
- RT_ASSERT(dev != RT_NULL);
- struct efm32_iic_device_t *iic;
- iic = (struct efm32_iic_device_t*)dev->user_data;
- switch (cmd)
- {
- case RT_DEVICE_CTRL_SUSPEND:
- /* suspend device */
- dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
- I2C_Enable(iic->iic_device, false);
- break;
- case RT_DEVICE_CTRL_RESUME:
- /* resume device */
- dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
- I2C_Enable(iic->iic_device, true);
- break;
- case RT_DEVICE_CTRL_IIC_SETTING:
- {
- /* change device setting */
- struct efm32_iic_control_t *control;
- control = (struct efm32_iic_control_t *)args;
- iic->is_master = control->is_master;
- iic->master_address = control->master_address << 1;
- iic->slave_address = control->slave_address << 1;
- }
- break;
- }
- return RT_EOK;
- }
- /******************************************************************//**
- * @brief
- * Register IIC device
- *
- * @details
- *
- * @note
- *
- * @param[in] device
- * Pointer to device descriptor
- *
- * @param[in] name
- * Device name
- *
- * @param[in] flag
- * Configuration flags
- *
- * @param[in] iic
- * Pointer to IIC device descriptor
- *
- * @return
- * Error code
- *********************************************************************/
- rt_err_t rt_hw_iic_register(
- rt_device_t device,
- const char *name,
- rt_uint32_t flag,
- struct efm32_iic_device_t *iic)
- {
- RT_ASSERT(device != RT_NULL);
- if ((flag & RT_DEVICE_FLAG_DMA_TX) || (flag & RT_DEVICE_FLAG_DMA_RX) ||
- (flag & RT_DEVICE_FLAG_INT_TX) || (flag & RT_DEVICE_FLAG_INT_RX))
- {
- RT_ASSERT(0);
- }
- device->type = RT_Device_Class_Char;
- device->rx_indicate = RT_NULL;
- device->tx_complete = RT_NULL;
- device->init = rt_iic_init;
- device->open = RT_NULL;
- device->close = RT_NULL;
- device->read = rt_iic_read;
- device->write = rt_iic_write;
- device->control = rt_iic_control;
- device->user_data = iic;
- /* register a character device */
- return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag);
- }
- /******************************************************************//**
- * @brief
- * Initialize the specified IIC unit
- *
- * @details
- *
- * @note
- *
- * @param[in] unitNumber
- * Unit number
- *
- * @param[in] location
- * Pin location number
- *********************************************************************/
- static void rt_hw_iic_unit_init(
- rt_uint8_t unitNumber,
- rt_uint8_t location)
- {
- I2C_TypeDef *iic;
- CMU_Clock_TypeDef iicClock;
- I2C_Init_TypeDef init = I2C_INIT_DEFAULT;
- switch (unitNumber)
- {
- case 0:
- iic = I2C0;
- iicClock = (CMU_Clock_TypeDef)cmuClock_I2C0;
- break;
- #if (I2C_COUNT > 1)
- case 1:
- iic = I2C1;
- iicClock = (CMU_Clock_TypeDef)cmuClock_I2C1;
- break;
- #endif
- default:
- return;
- }
- /* Enabling clock */
- CMU_ClockEnable(iicClock, true);
- /* Reset */
- I2C_Reset(iic);
- /* Config GPIO */
- GPIO_PinModeSet(
- (GPIO_Port_TypeDef)AF_PORT(AF_I2C_SCL(unitNumber), location),
- AF_PIN(AF_I2C_SCL(unitNumber), location),
- gpioModeWiredAndPullUpFilter,
- 1);
- GPIO_PinModeSet(
- (GPIO_Port_TypeDef)AF_PORT(AF_I2C_SDA(unitNumber), location),
- AF_PIN(AF_I2C_SDA(unitNumber), location),
- gpioModeWiredAndPullUpFilter,
- 1);
- /* Enable SDZ and SCL pins and set location */
- iic->ROUTE = I2C_ROUTE_SDAPEN | I2C_ROUTE_SCLPEN | \
- (location << _I2C_ROUTE_LOCATION_SHIFT);
-
- /* Initializing IIC */
- init.enable = false;
- I2C_Init(iic, &init);
- /* Abort current TX data and clear TX buffers */
- iic->CMD = I2C_CMD_ABORT | I2C_CMD_CLEARPC | I2C_CMD_CLEARTX;
-
- /* Clear previous interrupts */
- iic->IFC = _I2C_IFC_MASK;
- }
- /******************************************************************//**
- * @brief
- * Initialize all IIC module related hardware and register IIC device to kernel
- *
- * @details
- *
- * @note
- *********************************************************************/
- void rt_hw_iic_init(void)
- {
- struct efm32_iic_device_t *iic;
- rt_uint32_t flag;
- flag = RT_DEVICE_FLAG_RDWR;
- /* register iic0 */
- #ifdef RT_USING_IIC0
- iic = rt_malloc(sizeof(struct efm32_iic_device_t));
- if (iic == RT_NULL)
- {
- rt_kprintf("no memory for IIC0 driver\n");
- return;
- }
- iic->iic_device = I2C0;
- iic->is_master = true;
- iic->master_address = 0x0000;
- iic->slave_address = 0x0000;
- rt_hw_iic_unit_init(0, RT_USING_IIC0);
- rt_hw_iic_register(&iic0_device, RT_IIC0_NAME, flag, iic);
- #endif
- /* register iic1 */
- #ifdef RT_USING_IIC1
- iic = rt_malloc(sizeof(struct efm32_iic_device_t));
- if (iic == RT_NULL)
- {
- rt_kprintf("no memory for IIC1 driver\n");
- return;
- }
- iic->iic_device = I2C1;
- iic->is_master = true;
- iic->master_address = 0x0000;
- iic->slave_address = 0x0000;
- rt_hw_iic_unit_init(1, RT_USING_IIC1);
-
- rt_hw_iic_register(&iic1_device, RT_IIC1_NAME, flag, iic);
- #endif
- }
- /******************************************************************//**
- * @}
- *********************************************************************/
|