*** 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
This commit is contained in:
onelife.real 2011-08-23 00:59:24 +00:00
parent da55b1857f
commit 11488d143a
5 changed files with 931 additions and 190 deletions

View File

@ -13,6 +13,8 @@
* 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
******************************************************************************/
/***************************************************************************//**
@ -22,25 +24,37 @@
/* Includes ------------------------------------------------------------------*/
#include "board.h"
#include "drv_adc.h"
#include "dev_accel.h"
#if defined(EFM32_USING_ACCEL)
#if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC)
#include "drv_adc.h"
#elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
#include "drv_iic.h"
#include "hdl_interrupt.h"
#endif
#include "dev_accel.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
#ifdef RT_ACCEL_DEBUG
#ifdef EFM32_ACCEL_DEBUG
#define accel_debug(format,args...) rt_kprintf(format, ##args)
#else
#define accel_debug(format,args...)
#endif
/* Private constants ---------------------------------------------------------*/
static rt_device_t accel;
static struct efm32_adc_control_t control = \
static rt_device_t accel;
#if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC)
static struct efm32_adc_control_t control = \
{ADC_MODE_SCAN, {3, ACCEL_USING_DMA}, {}};
static struct efm32_accel_result_t accelOffset = {0};
static rt_bool_t accelInTime = true;
static struct efm32_accel_result_t accelOffset = {0};
#elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
static const struct efm32_iic_control_t control = \
{IIC_STATE_MASTER, 0x0000};
#endif
static rt_bool_t accelInTime = true;
static rt_uint32_t accelConfig = 0;
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
@ -56,26 +70,97 @@ static rt_bool_t accelInTime = true;
* @param[out] data
* Pointer to output buffer
*
* @param[in] lowResolution
* Resolution selection
*
* @return
* Error code
******************************************************************************/
rt_err_t efm_accel_get_data(struct efm32_accel_result_t *data)
rt_err_t efm_accel_get_data(struct efm32_accel_result_t *data,
rt_bool_t lowResolution)
{
RT_ASSERT(accel != RT_NULL);
struct efm32_adc_result_t result;
rt_err_t ret;
if (data == RT_NULL)
{
return -RT_ERROR;
}
result.mode = control.mode;
result.buffer = (void *)data;
accel->control(accel, RT_DEVICE_CTRL_RESUME, &result);
accel->control(accel, RT_DEVICE_CTRL_ADC_RESULT, &result);
ret = RT_EOK;
do
{
/* --------- ADC interface --------- */
#if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC)
struct efm32_adc_result_t result;
return RT_EOK;
result.mode = control.mode;
result.buffer = (void *)data;
if ((ret = accel->control(accel, RT_DEVICE_CTRL_RESUME,
(void *)&result)) != RT_EOK)
{
break;
}
if ((ret = accel->control(accel, RT_DEVICE_CTRL_ADC_RESULT, \
(void *)&result)) != RT_EOK)
{
break;
}
data->x += accelOffset.x - 0x800;
data->y += accelOffset.y - 0x800;
data->z += accelOffset.z - 0x800;
if (lowResolution)
{
data->x >>= 4;
data->y >>= 4;
data->z >>= 4;
}
/* --------- IIC interface --------- */
#elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
if (lowResolution || \
((accelConfig & ACCEL_MASK_RANGE) != MCTL_RANGE_8G))
{
rt_int8_t buf[3];
buf[0] = XOUT8;
if (accel->read(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, \
sizeof(buf)) == 0)
{
ret = -RT_ERROR;
break;
}
data->x = buf[0];
data->y = buf[1];
data->z = buf[2];
}
else
{
rt_uint8_t buf[6];
rt_uint16_t *temp = (rt_uint16_t *)&buf;
buf[0] = XOUTL;
if (accel->read(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, \
sizeof(buf)) == 0)
{
ret = -RT_ERROR;
break;
}
data->x = (*temp & 0x200) ? ((rt_uint32_t)*temp | ~0x3FF) : \
((rt_uint32_t)*temp & 0x3FF);
data->y = (*++temp & 0x200) ? ((rt_uint32_t)*temp | ~0x3FF) : \
((rt_uint32_t)*temp & 0x3FF);
data->z = (*++temp & 0x200) ? ((rt_uint32_t)*temp | ~0x3FF) : \
((rt_uint32_t)*temp & 0x3FF);
}
#endif
return RT_EOK;
} while (0);
accel_debug("Accel err: Get data failed!\n");
return ret;
}
/***************************************************************************//**
@ -94,6 +179,354 @@ static void efm_accel_timer(void* parameter)
accelInTime = false;
}
#if (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
/***************************************************************************//**
* @brief
* Accelerometer level and pulse detection interrupts handler
*
* @details
*
* @note
*
* @param[in] device
* Pointer to device descriptor
******************************************************************************/
static void efm_accel_isr(rt_device_t device)
{
rt_uint8_t buf[2];
if ((accelConfig & ACCEL_MASK_MODE) != ACCEL_MODE_MEASUREMENT)
{
/* Read detection source */
buf[0] = DETSRC;
if (accel->read(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 1) != 1)
{
accel_debug("Accel: read error\n");
return;
}
accel_debug("Accel: DETSRC %x\n", buf[0]);
/* Reset the interrupt flags: Part 1 */
buf[0] = INTRST;
buf[1] = INTRST_INT_1 | INTRST_INT_2;
accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2);
/* Read status to waste some time */
buf[0] = STATUS;
if (accel->read(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 1) != 1)
{
accel_debug("Accel: read error\n");
return;
}
accel_debug("Accel: STATUS %x\n", buf[0]);
/* Reset the interrupt flags: Part 2 */
buf[0] = INTRST;
buf[1] = 0x00;
accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2);
}
}
/***************************************************************************//**
* @brief
* Accelerometer configuration function
*
* @details
*
* @note
*
* @param[in] config
* Configuration options
*
* @param[in] level_threshold
* Level detection threshold
*
* @param[in] pulse_threshold
* Pulse detection threshold
*
* @param[in] pulse_duration
* Time window for 1st pulse
*
* @param[in] pulse_latency
* Pulse latency Time
*
* @param[in] pulse_duration2
* Time window for 2nd pulse
*
* @return
* Error code
******************************************************************************/
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 ret;
rt_uint8_t buf[2];
rt_uint8_t mode, mctl_reg, ctl1_reg, ctl2_reg;
ret = RT_EOK;
mctl_reg = 0;
ctl1_reg = 0;
ctl2_reg = 0;
/* Modify MCTL */
mode = config & ACCEL_MASK_MODE;
switch (mode)
{
case ACCEL_MODE_STANDBY:
mctl_reg |= MCTL_MODE_STANDBY;
break;
case ACCEL_MODE_MEASUREMENT:
mctl_reg |= MCTL_MODE_MEASUREMENT;
break;
case ACCEL_MODE_LEVEL:
mctl_reg |= MCTL_MODE_LEVEL;
break;
case ACCEL_MODE_PULSE:
mctl_reg |= MCTL_MODE_PULSE;
break;
default:
return -RT_ERROR;
}
switch (config & ACCEL_MASK_RANGE)
{
case ACCEL_RANGE_8G:
mctl_reg |= MCTL_RANGE_8G;
break;
case ACCEL_RANGE_4G:
mctl_reg |= MCTL_RANGE_4G;
break;
case ACCEL_RANGE_2G:
mctl_reg |= MCTL_RANGE_2G;
break;
default:
return -RT_ERROR;
}
if ((mode == ACCEL_MODE_LEVEL) || (mode == ACCEL_MODE_PULSE))
{
mctl_reg |= MCTL_PIN_INT1;
}
/* Modify CTL1 */
if (config & ACCEL_INTPIN_INVERSE)
{
ctl1_reg |= CTL1_INTPIN_INVERSE;
}
switch (config & ACCEL_MASK_INT)
{
case ACCEL_INT_LEVEL_PULSE:
ctl1_reg |= CTL1_INT_LEVEL_PULSE;
break;
case ACCEL_INT_PULSE_LEVEL:
ctl1_reg |= CTL1_INT_PULSE_LEVEL;
break;
case ACCEL_INT_SINGLE_DOUBLE:
ctl1_reg |= CTL1_INT_SINGLE_DOUBLE;
break;
default:
break;
}
switch (config & ACCEL_MASK_DISABLE)
{
case ACCEL_DISABLE_X:
ctl1_reg |= CTL1_X_DISABLE;
break;
case ACCEL_DISABLE_Y:
ctl1_reg |= CTL1_Y_DISABLE;
break;
case ACCEL_DISABLE_Z:
ctl1_reg |= CTL1_Z_DISABLE;
break;
default:
break;
}
if (config & ACCEL_THRESHOLD_INTEGER)
{
ctl1_reg |= CTL1_THRESHOLD_INTEGER;
}
if (config & ACCEL_BANDWIDTH_125HZ)
{
ctl1_reg |= CTL1_BANDWIDTH_125HZ;
}
/* Modify CTL2 */
if (config & ACCEL_LEVEL_AND)
{
ctl2_reg |= CTL2_LEVEL_AND;
}
if (config & ACCEL_PULSE_AND)
{
ctl2_reg |= CTL2_PULSE_AND;
}
if (config & ACCEL_DRIVE_STRONG)
{
ctl2_reg |= CTL2_DRIVE_STRONG;
}
do
{
/* Write registers */
buf[0] = MCTL;
buf[1] = mctl_reg;
if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
{
ret = -RT_ERROR;
break;
}
accel_debug("Accel: MCTL %x\n", mctl_reg);
buf[0] = CTL1;
buf[1] = ctl1_reg;
if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
{
ret = -RT_ERROR;
break;
}
accel_debug("Accel: CTL1 %x\n", ctl1_reg);
buf[0] = CTL2;
buf[1] = ctl2_reg;
if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
{
ret = -RT_ERROR;
break;
}
accel_debug("Accel: CTL2 %x\n", ctl2_reg);
accelConfig = config;
if (mode == ACCEL_MODE_PULSE)
{
buf[0] = PDTH;
buf[1] = pulse_threshold;
if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
{
ret = -RT_ERROR;
break;
}
accel_debug("Accel: PDTH %x\n", buf[1]);
buf[0] = PW;
buf[1] = pulse_duration;
if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
{
ret = -RT_ERROR;
break;
}
accel_debug("Accel: PW %x\n", buf[1]);
buf[0] = LT;
buf[1] = pulse_latency;
if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
{
ret = -RT_ERROR;
break;
}
accel_debug("Accel: LT %x\n", buf[1]);
buf[0] = TW;
buf[1] = pulse_duration2;
if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
{
ret = -RT_ERROR;
break;
}
accel_debug("Accel: TW %x\n", buf[1]);
}
if ((mode == ACCEL_MODE_LEVEL) || (mode == ACCEL_MODE_PULSE))
{
efm32_irq_hook_init_t hook;
/* Reset the interrupt flags: Part 1 */
buf[0] = INTRST;
buf[1] = INTRST_INT_1 | INTRST_INT_2;
if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
{
ret = -RT_ERROR;
break;
}
/* Set level detection threshold */
buf[0] = LDTH;
if (config & ACCEL_THRESHOLD_INTEGER)
{
buf[1] = level_threshold;
}
else
{
buf[1] = level_threshold & 0x7f;
}
if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
{
ret = -RT_ERROR;
break;
}
accel_debug("Accel: LDTH %x\n", buf[1]);
/* Config interrupt */
hook.type = efm32_irq_type_gpio;
hook.unit = ACCEL_INT1_PIN;
hook.cbFunc = efm_accel_isr;
hook.userPtr = RT_NULL;
efm32_irq_hook_register(&hook);
hook.unit = ACCEL_INT2_PIN;
efm32_irq_hook_register(&hook);
/* Clear pending interrupt */
BITBAND_Peripheral(&(GPIO->IFC), ACCEL_INT1_PIN, 0x1UL);
BITBAND_Peripheral(&(GPIO->IFC), ACCEL_INT2_PIN, 0x1UL);
/* Set raising edge interrupt and clear/enable it */
GPIO_IntConfig(
ACCEL_INT1_PORT,
ACCEL_INT1_PIN,
true,
false,
true);
GPIO_IntConfig(
ACCEL_INT2_PORT,
ACCEL_INT2_PIN,
true,
false,
true);
if (((rt_uint8_t)ACCEL_INT1_PORT % 2) || \
((rt_uint8_t)ACCEL_INT2_PORT % 2))
{
NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
NVIC_SetPriority(GPIO_ODD_IRQn, EFM32_IRQ_PRI_DEFAULT);
NVIC_EnableIRQ(GPIO_ODD_IRQn);
}
if (!((rt_uint8_t)ACCEL_INT1_PORT % 2) || \
!((rt_uint8_t)ACCEL_INT2_PORT % 2))
{
NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn);
NVIC_SetPriority(GPIO_EVEN_IRQn, EFM32_IRQ_PRI_DEFAULT);
NVIC_EnableIRQ(GPIO_EVEN_IRQn);
}
/* Reset the interrupt flags: Part 2 */
buf[0] = INTRST;
buf[1] = 0x00;
if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
{
ret = -RT_ERROR;
break;
}
}
} while (0);
return ret;
}
#endif
/***************************************************************************//**
* @brief
* Accelerometer auto-zero calibration function
@ -102,76 +535,203 @@ static void efm_accel_timer(void* parameter)
*
* @note
*
* @param[in] mode
* 0, simple mode (assuming the device is placed on flat surface)
* 1, interaction method
*
* @param[in] period
* Time period to perform auto-zero calibration
*
* @return
* Error code
******************************************************************************/
rt_err_t efm_accel_auto_zero(rt_tick_t period)
rt_err_t efm_accel_auto_zero(rt_uint8_t mode, rt_tick_t period)
{
RT_ASSERT(accel != RT_NULL);
rt_timer_t calTimer;
struct efm32_accel_result_t min = {0x7ff, 0x7ff, 0x7ff};
struct efm32_accel_result_t max = {0x7ff, 0x7ff, 0x7ff};
struct efm32_accel_result_t temp;
struct efm32_adc_result_t result;
struct efm32_accel_result_t min = {0, 0, 0};
struct efm32_accel_result_t max = {0, 0, 0};
struct efm32_accel_result_t temp, sum;
rt_int32_t simpleOffset[] = ACCEL_CAL_1G_VALUE;
rt_uint8_t cmd[7] = {0};
rt_uint8_t i, j;
if ((calTimer = rt_timer_create(
"cal_tmr",
efm_accel_timer,
RT_NULL,
period,
RT_TIMER_FLAG_ONE_SHOT)) == RT_NULL)
/* Reset offset */
#if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC)
accelOffset.x = 0;
accelOffset.y = 0;
accelOffset.z = 0;
#elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
cmd[0] = XOFFL;
if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, cmd, sizeof(cmd)) == 0)
{
accel_debug("Accel err: Create timer failed!\n");
return -RT_ERROR;
}
#endif
result.mode = control.mode;
result.buffer = (void *)&temp;
accelInTime = true;
rt_timer_start(calTimer);
do
if (mode == ACCEL_CAL_SIMPLE)
{
accel->control(accel, RT_DEVICE_CTRL_RESUME, &result);
accel->control(accel, RT_DEVICE_CTRL_ADC_RESULT, &result);
if (temp.x < min.x)
/* Simple mode */
for (j = 0; j < ACCEL_CAL_ROUND; j++)
{
min.x = temp.x;
}
if (temp.y < min.y)
{
min.y = temp.y;
}
if (temp.z < min.z)
{
min.z = temp.z;
}
if (temp.x > max.x)
{
max.x = temp.x;
}
if (temp.y > max.y)
{
max.y = temp.y;
}
if (temp.z > max.z)
{
max.z = temp.z;
}
rt_thread_sleep(1);
} while (accelInTime);
sum.x = 0x0;
sum.y = 0x0;
sum.z = 0x0;
accelOffset.x = (min.x + max.x) >> 1;
accelOffset.y = (min.y + max.y) >> 1;
accelOffset.z = (min.z + max.z) >> 1;
accel_debug("Accel: Min %x %x %x, max %x %x %x, Offset %x %x %x\n",
min.x, min.y, min.z, max.x, max.y, max.z,
for (i = 0; i < ACCEL_CAL_SAMPLES; i++)
{
#if (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
/* Waiting for data ready */
while(!GPIO_PinInGet(ACCEL_INT1_PORT, ACCEL_INT1_PIN));
#endif
if (efm_accel_get_data(&temp, false) != RT_EOK)
{
return -RT_ERROR;
}
sum.x += temp.x;
sum.y += temp.y;
sum.z += temp.z;
}
#if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC)
temp.x = sum.x / ACCEL_CAL_SAMPLES;
temp.y = sum.y / ACCEL_CAL_SAMPLES;
temp.z = sum.z / ACCEL_CAL_SAMPLES - simpleOffset[ACCEL_G_SELECT];
if ((temp.x == 0) && (temp.y == 0) && \
(temp.z == 0))
{
accel_debug("Accel: Offset %+d %+d %+d\n",
accelOffset.x, accelOffset.y, accelOffset.z);
break;
}
accelOffset.x -= temp.x;
accelOffset.y -= temp.y;
accelOffset.z -= temp.z;
#elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
temp.x = sum.x / (ACCEL_CAL_SAMPLES >> 1);
temp.y = sum.y / (ACCEL_CAL_SAMPLES >> 1);
temp.z = sum.z / (ACCEL_CAL_SAMPLES >> 1) \
- (simpleOffset[ACCEL_G_SELECT] << 1);
if ((temp.x == 0) && (temp.y == 0) && \
(temp.z == 0))
{
break;
}
/* Set offset drift registers */
max.x -= temp.x;
max.y -= temp.y;
max.z -= temp.z;
*(rt_int16_t *)&cmd[1] = (rt_int16_t)max.x;
*(rt_int16_t *)&cmd[3] = (rt_int16_t)max.y;
*(rt_int16_t *)&cmd[5] = (rt_int16_t)max.z;
if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, cmd, sizeof(cmd)) == 0)
{
return -RT_ERROR;
}
accel_debug("Accel: Offset %+d %+d %+d\n", *(rt_int16_t *)&cmd[1], \
*(rt_int16_t *)&cmd[3], *(rt_int16_t *)&cmd[5]);
#endif
rt_thread_sleep(1);
}
}
else
{
/* Interact mode */
if ((calTimer = rt_timer_create(
"cal_tmr",
efm_accel_timer,
RT_NULL,
period,
RT_TIMER_FLAG_ONE_SHOT)) == RT_NULL)
{
accel_debug("Accel err: Create timer failed!\n");
return -RT_ERROR;
}
accelInTime = true;
rt_timer_start(calTimer);
do
{
sum.x = 0x0;
sum.y = 0x0;
sum.z = 0x0;
for (i = 0; i < ACCEL_CAL_SAMPLES; i++)
{
#if (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
/* Waiting for data ready */
while(!GPIO_PinInGet(ACCEL_INT1_PORT, ACCEL_INT1_PIN));
#endif
if (efm_accel_get_data(&temp, false) != RT_EOK)
{
return -RT_ERROR;
}
sum.x += temp.x;
sum.y += temp.y;
sum.z += temp.z;
}
sum.x /= ACCEL_CAL_SAMPLES;
sum.y /= ACCEL_CAL_SAMPLES;
sum.z /= ACCEL_CAL_SAMPLES;
if (sum.x < min.x)
{
min.x = sum.x;
}
if (sum.y < min.y)
{
min.y = sum.y;
}
if (sum.z < min.z)
{
min.z = sum.z;
}
if (sum.x > max.x)
{
max.x = sum.x;
}
if (sum.y > max.y)
{
max.y = sum.y;
}
if (sum.z > max.z)
{
max.z = sum.z;
}
rt_thread_sleep(1);
} while (accelInTime);
accel_debug("Accel: Min %+d %+d %+d, max %+d %+d %+d\n",
min.x, min.y, min.z, max.x, max.y, max.z);
#if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC)
accelOffset.x = -((min.x + max.x) >> 1);
accelOffset.y = -((min.y + max.y) >> 1);
accelOffset.z = -((min.z + max.z) >> 1);
accel_debug("Accel: Offset %+d %+d %+d\n",
accelOffset.x, accelOffset.y, accelOffset.z);
rt_timer_delete(calTimer);
#elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
/* Set offset drift registers */
*(rt_int16_t *)&cmd[1] = (rt_int16_t)-(min.x + max.x);
*(rt_int16_t *)&cmd[3] = (rt_int16_t)-(min.y + max.y);
*(rt_int16_t *)&cmd[5] = (rt_int16_t)-(min.z + max.z);
if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, cmd, sizeof(cmd)) == 0)
{
return -RT_ERROR;
}
accel_debug("Accel: Offset %+d %+d %+d\n",
*(rt_int16_t *)&cmd[1], *(rt_int16_t *)&cmd[3], *(rt_int16_t *)&cmd[5]);
#endif
rt_timer_delete(calTimer);
}
return RT_EOK;
}
@ -188,15 +748,9 @@ rt_err_t efm_accel_auto_zero(rt_tick_t period)
******************************************************************************/
rt_err_t efm_accel_init(void)
{
ADC_InitScan_TypeDef scanInit = ADC_INITSCAN_DEFAULT;
#if defined(EFM32_G290_DK)
/* Enable accelerometer */
DVK_enablePeripheral(DVK_ACCEL);
/* Select low g-range */
DVK_disablePeripheral(DVK_ACCEL_GSEL);
#endif
rt_err_t ret;
ret = RT_EOK;
do
{
/* Find ADC device */
@ -204,16 +758,65 @@ rt_err_t efm_accel_init(void)
if (accel == RT_NULL)
{
accel_debug("Accel err: Can't find device: %s!\n", ACCEL_USING_DEVICE_NAME);
ret = -RT_ERROR;
break;
}
accel_debug("Accel: Find device %s\n", ACCEL_USING_DEVICE_NAME);
/* --------- ADC interface --------- */
#if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC)
ADC_InitScan_TypeDef scanInit = ADC_INITSCAN_DEFAULT;
#if defined(EFM32_G290_DK)
/* Enable accelerometer */
DVK_enablePeripheral(DVK_ACCEL);
/* Select g-range */
#if (ACCEL_G_SELECT == 0)
DVK_disablePeripheral(DVK_ACCEL_GSEL);
#elif (ACCEL_G_SELECT == 1)
DVK_enablePeripheral(DVK_ACCEL_GSEL);
#else
#error "Wrong value for ACCEL_G_SELECT"
#endif
#endif
/* Init ADC for scan mode */
scanInit.reference = adcRefVDD;
scanInit.input = ACCEL_X_ADC_CH | ACCEL_Y_ADC_CH | ACCEL_Z_ADC_CH;
control.scan.init = &scanInit;
accel->control(accel, RT_DEVICE_CTRL_ADC_MODE, &control);
if ((ret = accel->control(accel, RT_DEVICE_CTRL_ADC_MODE, \
(void *)&control)) != RT_EOK)
{
break;
}
/* --------- IIC interface --------- */
#elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
rt_uint8_t cmd[2];
/* Initialize */
if ((ret = accel->control(accel, RT_DEVICE_CTRL_IIC_SETTING, \
(void *)&control)) != RT_EOK)
{
break;
}
if (efm_accel_config(
ACCEL_MODE_MEASUREMENT | ACCEL_RANGE_2G,
EFM32_NO_DATA,
EFM32_NO_DATA,
EFM32_NO_DATA,
EFM32_NO_DATA,
EFM32_NO_DATA) != RT_EOK)
{
break;
}
/* Config interrupt pin1 */
GPIO_PinModeSet(ACCEL_INT1_PORT, ACCEL_INT1_PIN, gpioModeInput, 0);
/* Config interrupt pin2 */
GPIO_PinModeSet(ACCEL_INT2_PORT, ACCEL_INT2_PIN, gpioModeInput, 0);
#endif
accel_debug("Accel: Init OK\n");
return RT_EOK;
@ -229,35 +832,61 @@ rt_err_t efm_accel_init(void)
#ifdef RT_USING_FINSH
#include <finsh.h>
void accel_cal(rt_uint32_t second)
void accel_cal(rt_uint8_t mode, rt_uint32_t second)
{
efm_accel_auto_zero(RT_TICK_PER_SECOND * second);
if (efm_accel_auto_zero(mode, RT_TICK_PER_SECOND * second) != RT_EOK)
{
rt_kprintf("Error occurred.");
return;
}
rt_kprintf("Calibration done. Offset: 0x%03x, 0x%03x, 0x%03x\n",
accelOffset.x, accelOffset.y, accelOffset.z);
rt_kprintf("Calibration done.\n");
}
FINSH_FUNCTION_EXPORT(accel_cal, auto-zero calibration.)
void list_accel(void)
{
struct efm32_accel_result_t temp;
rt_int32_t x, y, z;
struct efm32_accel_result_t data;
if ((accelOffset.x == 0) && \
(accelOffset.y == 0) && \
(accelOffset.z == 0))
{
rt_kprintf("Please calibrate the device first!\n");
return;
}
efm_accel_get_data(&temp);
x = temp.x - accelOffset.x;
y = temp.y - accelOffset.y;
z = temp.z - accelOffset.z;
rt_kprintf("X: %d, Y: %d, Z: %d\n", x, y, z);
efm_accel_get_data(&data, false);
rt_kprintf("X: %d, Y: %d, Z: %d\n", data.x, data.y, data.z);
}
FINSH_FUNCTION_EXPORT(list_accel, list accelerometer info.)
void test_accel(rt_uint8_t mode)
{
if (mode == 0)
{
if (efm_accel_config(
ACCEL_MODE_LEVEL | ACCEL_RANGE_8G | ACCEL_INT_LEVEL_PULSE | \
ACCEL_SOURCE_LEVEL_X | ACCEL_SOURCE_LEVEL_Y,
0x1f,
EFM32_NO_DATA,
EFM32_NO_DATA,
EFM32_NO_DATA,
EFM32_NO_DATA) != RT_EOK)
{
rt_kprintf("efm_accel_config(): error\n");
return;
}
}
else
{
if (efm_accel_config(
ACCEL_MODE_PULSE | ACCEL_RANGE_8G | ACCEL_INT_SINGLE_DOUBLE | \
ACCEL_SOURCE_PULSE_X | ACCEL_SOURCE_PULSE_Y,
0x1f,
0x1f,
200,
255,
255) != RT_EOK)
{
rt_kprintf("efm_accel_config(): error\n");
return;
}
}
}
FINSH_FUNCTION_EXPORT(test_accel, list accelerometer info.)
#endif
#endif

View File

@ -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__ */

View File

@ -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");

View File

@ -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);

View File

@ -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