提交 11488d14 编写于 作者: O onelife.real

*** EFM32 branch ***

1. Change the usage of the second parameter of Read and Write functions in IIC driver 
   - to "Slave address" from (seldom used) "Offset" 
2. Add a timer for IIC driver to prevent from forever waiting
3. Add digital (IIC) interface support for accelerometer driver (Freescale MMA7455L)

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1678 bbd45198-f89e-11dd-88c7-29a3b14d5316
上级 da55b185
此差异已折叠。
......@@ -13,28 +13,110 @@
* Date Author Notes
* 2011-07-13 onelife Initial creation for using EFM32 ADC module to
* interface the Freescale MMA7361L
* 2011-08-02 onelife Add digital interface support of using EFM32 IIC
* module for the Freescale MMA7455L
******************************************************************************/
#ifndef __DEV_ACCEL_H__
#define __DEV_ACCEL_H__
/* Includes ------------------------------------------------------------------*/
#if (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
#include "mma7455l.h"
#endif
/* Exported types ------------------------------------------------------------*/
struct efm32_accel_result_t
{
rt_uint32_t x;
rt_uint32_t y;
rt_uint32_t z;
rt_int32_t x;
rt_int32_t y;
rt_int32_t z;
};
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
#define ACCEL_X_ADC_CH ADC_SCANCTRL_INPUTMASK_CH2
#define ACCEL_Y_ADC_CH ADC_SCANCTRL_INPUTMASK_CH3
#define ACCEL_Z_ADC_CH ADC_SCANCTRL_INPUTMASK_CH4
/* MMA7361LC
g-Select g-Range Sensitivity
0 1.5 g 800 mV/g
1 6 g 206 mV/g
MMA7455L
g-Select g-Range Sensitivity
0 2 g 64 LSB/g
1 4 g 32 LSB/g
2 8 g 16 LSB/g
*/
#define ACCEL_G_SELECT (0)
#define ACCEL_CAL_SAMPLES (4) /* Must be multiple of 2 */
#define ACCEL_CAL_ROUND (50)
#define ACCEL_CAL_SIMPLE (0)
#define ACCEL_CAL_INTERACT (1)
#if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC)
/* Reading_at_1g = Sensitivity * Max_reading / Refference_voltage */
#define ACCEL_CAL_1G_VALUE {993, 256}
#define ACCEL_X_ADC_CH ADC_SCANCTRL_INPUTMASK_CH2
#define ACCEL_Y_ADC_CH ADC_SCANCTRL_INPUTMASK_CH3
#define ACCEL_Z_ADC_CH ADC_SCANCTRL_INPUTMASK_CH4
#elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
#define ACCEL_CAL_1G_VALUE {0x3f, 0x1f, 0x0f}
#define ACCEL_IIC_SLAVE_ADDRESS (0x1d)
#define ACCEL_INT1_PORT (gpioPortD)
#define ACCEL_INT1_PIN (13)
#define ACCEL_INT2_PORT (gpioPortD)
#define ACCEL_INT2_PIN (12)
#define ACCEL_MODE_STANDBY (1 << 0)
#define ACCEL_MODE_MEASUREMENT (1 << 1)
#define ACCEL_MODE_LEVEL (1 << 2)
#define ACCEL_MODE_PULSE (1 << 3)
#define ACCEL_RANGE_8G (1 << 4)
#define ACCEL_RANGE_4G (1 << 5)
#define ACCEL_RANGE_2G (1 << 6)
#define ACCEL_INTPIN_INVERSE (1 << 7)
#define ACCEL_INT_LEVEL_PULSE (1 << 8)
#define ACCEL_INT_PULSE_LEVEL (1 << 9)
#define ACCEL_INT_SINGLE_DOUBLE (1 << 10)
#define ACCEL_DISABLE_X (1 << 11)
#define ACCEL_DISABLE_Y (1 << 12)
#define ACCEL_DISABLE_Z (1 << 13)
#define ACCEL_THRESHOLD_INTEGER (1 << 14) /* For level detection only */
#define ACCEL_BANDWIDTH_125HZ (1 << 15)
#define ACCEL_LEVEL_AND (1 << 16)
#define ACCEL_PULSE_AND (1 << 17)
#define ACCEL_DRIVE_STRONG (1 << 18)
#define ACCEL_SOURCE_LEVEL_X (1 << 19)
#define ACCEL_SOURCE_LEVEL_Y (1 << 20)
#define ACCEL_SOURCE_LEVEL_Z (1 << 21)
#define ACCEL_SOURCE_PULSE_X (1 << 22)
#define ACCEL_SOURCE_PULSE_Y (1 << 23)
#define ACCEL_SOURCE_PULSE_Z (1 << 24)
#define ACCEL_SHIFT_MODE (0)
#define ACCEL_SHIFT_RANGE (4)
#define ACCEL_SHIFT_INT (8)
#define ACCEL_SHIFT_DISABLE (11)
#define ACCEL_SHIFT_SOURCE (19)
#define ACCEL_MASK_MODE (0X0000000f << ACCEL_SHIFT_MODE)
#define ACCEL_MASK_RANGE (0X00000007 << ACCEL_SHIFT_RANGE)
#define ACCEL_MASK_INT (0X00000007 << ACCEL_SHIFT_INT)
#define ACCEL_MASK_DISABLE (0X00000007 << ACCEL_SHIFT_DISABLE)
#define ACCEL_MASK_SOURCE (0X0000003f << ACCEL_SHIFT_SOURCE)
#endif
/* Exported functions ------------------------------------------------------- */
rt_err_t efm_accel_get_data(struct efm32_accel_result_t *data);
rt_err_t efm_accel_auto_zero(rt_tick_t period);
rt_err_t efm_accel_get_data(struct efm32_accel_result_t *data,
rt_bool_t lowResolution);
rt_err_t efm_accel_config(rt_uint32_t config,
rt_uint8_t level_threshold,
rt_uint8_t pulse_threshold,
rt_uint8_t pulse_duration,
rt_uint8_t pulse_latency,
rt_uint8_t pulse_duration2);
rt_err_t efm_accel_auto_zero(rt_uint8_t mode, rt_tick_t period);
rt_err_t efm_accel_init(void);
#endif /*__DEV_ACCEL_H__ */
......@@ -15,6 +15,9 @@
* 2011-06-17 onelife Modify init function for efm32lib v2 upgrading
* 2011-07-11 onelife Add lock (semaphore) to prevent simultaneously
* access
* 2011-08-04 onelife Change the usage of the second parameter of Read
* and Write functions from (seldom used) "Offset" to "Slave address"
* 2011-08-04 onelife Add a timer to prevent from forever waiting
******************************************************************************/
/***************************************************************************//**
......@@ -29,6 +32,13 @@
#if (defined(RT_USING_IIC0) || defined(RT_USING_IIC1))
/* Private typedef -----------------------------------------------------------*/
struct efm32_iic_block
{
struct rt_device device;
struct rt_semaphore lock;
struct rt_timer timer;
};
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
#ifdef RT_IIC_DEBUG
......@@ -39,19 +49,17 @@
/* 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;
static struct rt_semaphore iic0_lock;
#if (RT_USING_IIC0 > 3)
#error "The location number range of IIC is 0~3"
#endif
static struct efm32_iic_block iic0;
#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;
static struct rt_semaphore iic1_lock;
#if (RT_USING_IIC1 > 3)
#error "The location number range of IIC is 0~3"
#endif
static struct efm32_iic_block iic1;
#endif
/* Private function prototypes -----------------------------------------------*/
......@@ -161,7 +169,7 @@ static rt_err_t rt_iic_close(rt_device_t dev)
* Pointer to device descriptor
*
* @param[in] pos
* Offset
* Slave address
*
* @param[in] buffer
* Poniter to the buffer
......@@ -183,7 +191,6 @@ static rt_size_t rt_iic_read (
struct efm32_iic_device_t* iic;
I2C_TransferSeq_TypeDef seq;
I2C_TransferReturn_TypeDef ret;
rt_uint8_t data[1];
if (!size)
{
......@@ -193,7 +200,6 @@ static rt_size_t rt_iic_read (
err_code = RT_EOK;
read_size = 0;
iic = (struct efm32_iic_device_t*)dev->user_data;
data[0] = (rt_uint8_t)(pos & 0x000000FF);
/* Lock device */
if (rt_hw_interrupt_check())
......@@ -211,36 +217,39 @@ static rt_size_t rt_iic_read (
if (iic->state & IIC_STATE_MASTER)
{
seq.addr = iic->slave_address;
seq.addr = (rt_uint16_t)pos << 1;
seq.flags = I2C_FLAG_WRITE_READ;
/* Select register to be read */
seq.buf[0].data = data;
/* Set register to be read */
seq.buf[0].data = (rt_uint8_t *)buffer;
seq.buf[0].len = 1;
/* Select location/length of data to be read */
/* Set read buffer pointer and size */
seq.buf[1].data = (rt_uint8_t *)buffer;
seq.buf[1].len = size;
/* Do a polled transfer */
iic->timeout = false;
rt_timer_stop(iic->timer);
rt_timer_start(iic->timer);
ret = I2C_TransferInit(iic->iic_device, &seq);
while (ret == i2cTransferInProgress)
while ((ret == i2cTransferInProgress) && !iic->timeout)
{
ret = I2C_Transfer(iic->iic_device);
}
if (ret != i2cTransferDone)
{
iic_debug("IIC0 read error: %x\n", ret);
iic_debug("IIC0 read address: %x\n", seq.addr);
iic_debug("IIC0 read data0: %x -> %x\n", seq.buf[0].data, *seq.buf[0].data);
iic_debug("IIC0 read len0: %x\n", seq.buf[0].len);
iic_debug("IIC0 read data1: %x -> %x\n", seq.buf[1].data, *seq.buf[1].data);
iic_debug("IIC0 read len1: %x\n", seq.buf[1].len);
iic_debug("IIC read error: %x\n", ret);
iic_debug("IIC read address: %x\n", seq.addr);
iic_debug("IIC read data0: %x -> %x\n", seq.buf[0].data, *seq.buf[0].data);
iic_debug("IIC read len0: %x\n", seq.buf[0].len);
iic_debug("IIC read data1: %x -> %x\n", seq.buf[1].data, *seq.buf[1].data);
iic_debug("IIC read len1: %x\n", seq.buf[1].len);
err_code = (rt_err_t)ret;
}
else
{
read_size = size;
iic_debug("IIC0 read size: %d\n", read_size);
iic_debug("IIC read size: %d\n", read_size);
}
}
else
......@@ -288,7 +297,7 @@ static rt_size_t rt_iic_read (
}
read_size = (rt_uint32_t)ptr - (rt_uint32_t)buffer;
iic_debug("IIC0 slave read size: %d\n", read_size);
iic_debug("IIC slave read size: %d\n", read_size);
}
/* Unlock device */
......@@ -311,7 +320,7 @@ static rt_size_t rt_iic_read (
* Pointer to device descriptor
*
* @param[in] pos
* Offset
* Slave address
*
* @param[in] buffer
* Poniter to the buffer
......@@ -359,24 +368,11 @@ static rt_size_t rt_iic_write (
if (iic->state & IIC_STATE_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;
}
seq.addr = (rt_uint16_t)pos << 1;
seq.flags = I2C_FLAG_WRITE;
/* Set write buffer pointer and size */
seq.buf[0].data = (rt_uint8_t *)buffer;
seq.buf[0].len = size;
}
else
{
......@@ -384,10 +380,13 @@ static rt_size_t rt_iic_write (
}
/* Do a polled transfer */
iic->timeout = false;
rt_timer_stop(iic->timer);
rt_timer_start(iic->timer);
ret = I2C_TransferInit(iic->iic_device, &seq);
while (ret == i2cTransferInProgress)
while ((ret == i2cTransferInProgress) && !iic->timeout)
{
ret = I2C_Transfer(iic->iic_device);
ret = I2C_Transfer(iic->iic_device);
}
if (ret != i2cTransferDone)
......@@ -474,8 +473,7 @@ static rt_err_t rt_iic_control (
control = (struct efm32_iic_control_t *)args;
iic->state = control->config & (IIC_STATE_MASTER | IIC_STATE_BROADCAST);
iic->master_address = control->master_address << 1;
iic->slave_address = control->slave_address << 1;
iic->address = control->address << 1;
if (!(iic->state & IIC_STATE_MASTER))
{
......@@ -503,7 +501,7 @@ static rt_err_t rt_iic_control (
}
/* Enable slave mode */
I2C_SlaveAddressSet(iic->iic_device, iic->slave_address);
I2C_SlaveAddressSet(iic->iic_device, iic->address);
I2C_SlaveAddressMaskSet(iic->iic_device, 0xFF);
iic->iic_device->CTRL |= I2C_CTRL_SLAVE | I2C_CTRL_AUTOACK | I2C_CTRL_AUTOSN;
......@@ -513,7 +511,7 @@ static rt_err_t rt_iic_control (
/* Enable I2Cn interrupt vector in NVIC */
#ifdef RT_USING_IIC0
if (dev == &iic0_device)
if (dev == &iic0.device)
{
NVIC_ClearPendingIRQ(I2C0_IRQn);
NVIC_SetPriority(I2C0_IRQn, EFM32_IRQ_PRI_DEFAULT);
......@@ -521,7 +519,7 @@ static rt_err_t rt_iic_control (
}
#endif
#ifdef RT_USING_IIC1
if (dev == &iic1_device)
if (dev == &iic1.device)
{
NVIC_ClearPendingIRQ(I2C1_IRQn);
NVIC_SetPriority(I2C1_IRQn, EFM32_IRQ_PRI_DEFAULT);
......@@ -539,6 +537,22 @@ static rt_err_t rt_iic_control (
return RT_EOK;
}
/***************************************************************************//**
* @brief
* IIC timeout interrupt handler
*
* @details
*
* @note
*
* @param[in] parameter
* Parameter
******************************************************************************/
static void rt_iic_timer(void *timeout)
{
*(rt_bool_t *)timeout = true;
}
/***************************************************************************//**
* @brief
* Register IIC device
......@@ -683,14 +697,15 @@ static void rt_hw_iic_slave_isr(rt_device_t dev)
* Pin location number
******************************************************************************/
static struct efm32_iic_device_t *rt_hw_iic_unit_init(
rt_device_t device,
rt_uint8_t unitNumber,
rt_uint8_t location)
struct efm32_iic_block *block,
rt_uint8_t unitNumber,
rt_uint8_t location)
{
struct efm32_iic_device_t *iic;
CMU_Clock_TypeDef iicClock;
I2C_Init_TypeDef init = I2C_INIT_DEFAULT;
efm32_irq_hook_init_t hook;
rt_uint8_t name[RT_NAME_MAX];
do
{
......@@ -702,9 +717,10 @@ static struct efm32_iic_device_t *rt_hw_iic_unit_init(
break;
}
iic->counter = 0;
iic->timer = &block->timer;
iic->timeout = false;
iic->state |= IIC_STATE_MASTER;
iic->master_address = 0x0000;
iic->slave_address = 0x0000;
iic->address = 0x0000;
iic->rx_buffer = RT_NULL;
/* Initialization */
......@@ -729,6 +745,7 @@ static struct efm32_iic_device_t *rt_hw_iic_unit_init(
default:
break;
}
rt_sprintf(name, "iic%d", unitNumber);
/* Enabling clock */
CMU_ClockEnable(iicClock, true);
......@@ -751,7 +768,7 @@ static struct efm32_iic_device_t *rt_hw_iic_unit_init(
hook.type = efm32_irq_type_iic;
hook.unit = unitNumber;
hook.cbFunc = rt_hw_iic_slave_isr;
hook.userPtr = device;
hook.userPtr = (void *)&block->device;
efm32_irq_hook_register(&hook);
/* Enable SDZ and SCL pins and set location */
......@@ -765,6 +782,17 @@ static struct efm32_iic_device_t *rt_hw_iic_unit_init(
/* Abort current TX data and clear TX buffers */
iic->iic_device->CMD = I2C_CMD_ABORT | I2C_CMD_CLEARPC | I2C_CMD_CLEARTX;
/* Initialize lock */
iic->lock = &block->lock;
if (rt_sem_init(iic->lock, name, 1, RT_IPC_FLAG_FIFO) != RT_EOK)
{
break;
}
/* Initialize timer */
rt_timer_init(iic->timer, name, rt_iic_timer, &iic->timeout,
IIC_TIMEOUT_PERIOD, RT_TIMER_FLAG_ONE_SHOT);
return iic;
} while(0);
......@@ -795,40 +823,26 @@ void rt_hw_iic_init(void)
flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX;
#ifdef RT_USING_IIC0
/* Initialize and register iic0 */
if ((iic = rt_hw_iic_unit_init(&iic0_device, 0, RT_USING_IIC0)) != RT_NULL)
if ((iic = rt_hw_iic_unit_init(&iic0, 0, RT_USING_IIC0)) != RT_NULL)
{
rt_hw_iic_register(&iic0_device, RT_IIC0_NAME, flag, iic);
rt_hw_iic_register(&iic0.device, RT_IIC0_NAME, flag, iic);
}
else
{
break;
}
/* Initialize lock for iic0 */
iic->lock = &iic0_lock;
if (rt_sem_init(iic->lock, RT_IIC0_NAME, 1, RT_IPC_FLAG_FIFO) != RT_EOK)
{
break;
}
#endif
#ifdef RT_USING_IIC1
/* Initialize and register iic1 */
if ((iic = rt_hw_iic_unit_init(&iic1_device, 1, RT_USING_IIC1)) != RT_NULL)
if ((iic = rt_hw_iic_unit_init(&iic1, 1, RT_USING_IIC1)) != RT_NULL)
{
rt_hw_iic_register(&iic1_device, RT_IIC1_NAME, flag, iic);
rt_hw_iic_register(&iic1.device, RT_IIC1_NAME, flag, iic);
}
else
{
break;
}
/* Initialize lock for iic1 */
iic->lock = &iic1_lock;
if (rt_sem_init(iic->lock, RT_IIC1_NAME, 1, RT_IPC_FLAG_FIFO) != RT_EOK)
{
break;
}
#endif
iic_debug("IIC: H/W init OK!\n");
......
......@@ -14,6 +14,9 @@
* 2011-01-07 onelife Initial creation for EFM32
* 2011-07-11 onelife Add lock (semaphore) to prevent simultaneously
* access
* 2011-08-04 onelife Change the usage of the second parameter of Read
* and Write functions from (seldom used) "Offset" to "Slave address"
* 2011-08-04 onelife Add a timer to prevent from forever waiting
******************************************************************************/
#ifndef __DRV_IIC_H__
#define __DRV_IIC_H__
......@@ -33,14 +36,16 @@ struct efm32_iic_device_t
rt_uint32_t counter;
/* Lock */
struct rt_semaphore *lock;
/* Pointer to timer */
rt_timer_t timer;
/* Timeout flag */
volatile rt_bool_t timeout;
/* State */
rt_uint8_t state;
/* Pointer to IIC device structure */
I2C_TypeDef *iic_device;
/* Master address */
rt_uint16_t master_address;
/* Slave address */
rt_uint16_t slave_address;
/* Self address */
rt_uint16_t address;
/* RX structure */
struct efm32_iic_int_mode_t *rx_buffer;
};
......@@ -48,8 +53,7 @@ struct efm32_iic_device_t
struct efm32_iic_control_t
{
rt_uint8_t config;
rt_uint16_t master_address;
rt_uint16_t slave_address;
rt_uint16_t address;
};
/* Exported constants --------------------------------------------------------*/
......@@ -58,6 +62,7 @@ struct efm32_iic_control_t
#define IIC_STATE_BROADCAST (1 << 1)
//#define IIC_STATE_TX_BUSY (1 << 2)
#define IIC_STATE_RX_BUSY (1 << 3)
#define IIC_TIMEOUT_PERIOD (RT_TICK_PER_SECOND)
/* Exported functions --------------------------------------------------------*/
void rt_hw_iic_init(void);
......
......@@ -49,7 +49,7 @@
//#define RT_RTC_DEBUG
#define EFM32_DEBUG
#define RT_ACCEL_DEBUG
#define EFM32_ACCEL_DEBUG
#define EFM32_SFLASH_DEBUG
//#define EFM32_SDCARD_DEBUG
//#define EFM32_ETHERNET_DEBUG
......@@ -119,7 +119,7 @@
#endif
/* SECTION: IIC options */
//#define RT_USING_IIC0 0x1UL
#define RT_USING_IIC0 0x3UL
#define RT_IIC0_NAME "iic0"
/* SECTION: ACMP options */
......@@ -162,23 +162,34 @@
#define FINSH_USING_DESCRIPTION
/* SECTION: Peripheral devices */
#define EFM32_INTERFACE_ADC (0)
#define EFM32_INTERFACE_IIC (1)
#define EFM32_INTERFACE_SPI (2)
#if defined(EFM32_G290_DK)
//#define EFM32_USING_ACCEL /* Three axis accelerometer */
//#define EFM32_USING_SFLASH /* SPI Flash */
//#define EFM32_USING_SPISD /* MicroSD card */
#define EFM32_USING_ETHERNET /* Ethernet controller */
#define EFM32_USING_ACCEL EFM32_INTERFACE_IIC /* Three axis accelerometer */
//#define EFM32_USING_SFLASH /* SPI Flash */
//#define EFM32_USING_SPISD /* MicroSD card */
//#define EFM32_USING_ETHERNET /* Ethernet controller */
#endif
#if defined(EFM32_USING_ACCEL)
#if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC)
#define ACCEL_USING_DEVICE_NAME RT_ADC0_NAME
#define ACCEL_USING_DMA (0x3UL)
#define ACCEL_USING_DMA (0x3UL) /* For multiple channels scan mode */
#elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
#define ACCEL_USING_DEVICE_NAME RT_IIC0_NAME
#endif
#endif
#if defined(EFM32_USING_SFLASH)
#define SFLASH_USING_DEVICE_NAME RT_USART0_NAME
#endif
#if defined(EFM32_USING_SPISD)
#define SPISD_USING_DEVICE_NAME RT_USART0_NAME
#define SPISD_DEVICE_NAME "spiSd"
#endif
#if defined(EFM32_USING_ETHERNET)
#define ETH_USING_DEVICE_NAME RT_USART2_NAME
#define ETH_DEVICE_NAME "spiEth"
......@@ -205,7 +216,7 @@
//#define hostName "onelife.dyndns.org"
//#define userPwdB64 "dXNlcjpwYXNzd2Q="
#define RT_USING_LWIP
///#define RT_USING_LWIP
//#define RT_USING_NETUTILS
/* LwIP uses RT-Thread Memory Management */
#define RT_LWIP_USING_RT_MEM
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册