All about Chibios 3.0 from trunk, and STM32F031F4.
I'm using this driver for hymidity sensor DHT11 (founded somewhere on the internet and some modified):
Code: Select all
#include "ch.h"
#include "hal.h"
#include "ext.h"
#include "chconf.h"
#include "core.h"
#if DHT11_PRESENT
#include <DHT11_hal.h>
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
GPTDriver GPTD17;
dht11_t DHTD1;
#define Timer_Clock 100000
#define T172US(n) ((((n) - 1UL) * (1000000UL / Timer_Clock)) + 1UL)
/*
* GPT2 configuration.
*/
static const GPTConfig gpt17cfg =
{ Timer_Clock, /* 100kHz timer clock.*/
NULL, /* Timer callback.*/
0, 0 };
/**
* @brief Enables the TIM3 peripheral clock.
* @note The @p lp parameter is ignored in this family.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp)
/**
* @brief Disables the TIM3 peripheral clock.
* @note The @p lp parameter is ignored in this family.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableTIM17(lp) rccDisableAPB2(RCC_APB2ENR_TIM17EN, lp)
/**
* @brief Resets the TIM3 peripheral.
*
* @api
*/
#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST)
/** @} */
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*
* @brief ...
*/
dht11_t *sensor_handlers[EXT_MAX_CHANNELS];
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*
* @brief
*/
inline bool lldLock(lld_lock_t *lock)
{
bool locked = false;
//
chSysLock();
if (lock->flag == false)
{
lock->flag = true;
locked = true;
}
chSysUnlock();
return locked;
}
/*
* @brief
*/
inline void lldUnlock(lld_lock_t *lock)
{
//
chSysLock();
if (lock->flag == true)
{
lock->flag = false;
}
chSysUnlock();
}
/*
* @brief
*/
inline bool lldLockISR(lld_lock_t *lock)
{
bool locked = false;
//
chSysLockFromISR();
if (lock->flag == false)
{
lock->flag = true;
locked = true;
}
chSysUnlockFromISR();
return locked;
}
/*
* @brief
*/
inline void lldUnlockISR(lld_lock_t *lock)
{
//
chSysLockFromISR();
if (lock->flag == true)
{
lock->flag = false;
}
chSysUnlockFromISR();
}
/*
* @brief ...
* @details ...
*/
static void dht11_lld_ext_handler(EXTDriver *extp, expchannel_t channel)
{
//
(void) extp;
dht11_t *sensor = sensor_handlers[channel];
if (sensor == NULL)
{
return;
}
//
if (lldLockISR(&sensor->lock) == true)
{
switch (sensor->state)
{
case DHT11_WAIT_RESPONSE:
sensor->bit_count++;
if (sensor->bit_count == 3)
{
sensor->bit_count = 0;
sensor->data = 0;
sensor->state = DHT11_READ_DATA;
}
break;
case DHT11_READ_DATA:
sensor->bit_count++;
if (sensor->bit_count % 2 == 1)
{
sensor->time_measurment = gptGetCounterX(&GPTD17);
sensor->data <<= 1;
}
else
{
volatile systime_t tmp_time = gptGetCounterX(&GPTD17);
sensor->time_measurment = tmp_time - sensor->time_measurment;
if (T172US(sensor->time_measurment) > 50)
{
sensor->data += 1;
}
}
if (sensor->bit_count == 64)
{
sensor->bit_count = 0;
sensor->crc = 0;
sensor->state = DHT11_READ_CRC;
}
break;
case DHT11_READ_CRC:
sensor->bit_count++;
//sensor->crc = sensor->crc << 1;
if (sensor->bit_count % 2 == 1)
{
sensor->time_measurment = gptGetCounterX(&GPTD17);
sensor->crc <<= 1;
}
else
{
volatile systime_t tmp_time = gptGetCounterX(&GPTD17);
sensor->time_measurment = tmp_time - sensor->time_measurment;
if (T172US(sensor->time_measurment) > 40)
{
sensor->crc += 1;
}
}
if (sensor->bit_count == 16)
{
chSysLockFromISR();
extChannelDisableI(sensor->ext_drv, sensor->ext_pin);
// if (chVTIsArmedI(&sensor->timer) == true)
// {
chVTResetI(&sensor->timer);
// }
gptStopTimerI(&GPTD17);
chSysUnlockFromISR();
sensor->temp = (sensor->data & 0xFF00) >> 8;
sensor->humidity = (sensor->data & 0xFF000000) >> 24;
sensor->state = DHT11_READ_OK;
}
break;
case DHT11_UNINIT:
case DHT11_IDLE:
case DHT11_READ_REQUEST:
case DHT11_READ_OK:
case DHT11_BUSY:
case DHT11_ERROR:
break;
}
lldUnlockISR(&sensor->lock);
}
}
/*
* @brief ...
* @details ...
*/
void dht11_timer_handler(void *p)
{
dht11_t *sensor = (dht11_t *) p;
//
if (lldLockISR(&sensor->lock) == true)
{
switch (sensor->state)
{
case DHT11_READ_REQUEST:
chSysLockFromISR();
chVTSetI(&sensor->timer, MS2ST(5), dht11_timer_handler, sensor);
extChannelEnableI(sensor->ext_drv, sensor->ext_pin);
chSysUnlockFromISR();
palSetPad(sensor->ext_port, sensor->ext_pin);
palSetPadMode(sensor->ext_port, sensor->ext_pin, PAL_MODE_INPUT_PULLUP);
sensor->bit_count = 0;
sensor->state = DHT11_WAIT_RESPONSE;
break;
case DHT11_UNINIT:
case DHT11_IDLE:
case DHT11_WAIT_RESPONSE:
case DHT11_READ_DATA:
case DHT11_READ_CRC:
case DHT11_READ_OK:
case DHT11_BUSY:
case DHT11_ERROR:
chSysLockFromISR();
extChannelDisableI(sensor->ext_drv, sensor->ext_pin);
palSetPadMode(sensor->ext_port, sensor->ext_pin, PAL_MODE_OUTPUT_PUSHPULL);
palSetPad(sensor->ext_port, sensor->ext_pin);
// if (chVTIsArmedI(&sensor->timer) == true)
// {
chVTResetI(&sensor->timer);
// }
gptStopTimerI(&GPTD17);
chSysUnlockFromISR();
sensor->state = DHT11_ERROR;
// SerialConsole::debug("dht11Update timer error\r\n");
break;
}
lldUnlockISR(&sensor->lock);
}
}
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/*
* @brief ...
*/
dht11_state_t dht11Init(dht11_t *sensor)
{
GPTD17.tim = STM32_TIM17;
gptObjectInit(&GPTD17);
rccEnableTIM17(FALSE);
rccResetTIM17();
// nvicEnableVector(STM32_TIM14_NUMBER, STM32_GPT_TIM14_IRQ_PRIORITY);
GPTD17.clock = STM32_TIMCLK1;
gptStart(&GPTD17, &gpt17cfg);
dht11_state_t state;
if (lldLock(&sensor->lock) == true)
{
sensor->refresh_time = 0;
sensor->temp = 0;
sensor->humidity = 0;
sensor_handlers[sensor->ext_pin] = sensor;
palSetPadMode(sensor->ext_port, sensor->ext_pin, PAL_MODE_OUTPUT_PUSHPULL);
sensor->ext_cfg.mode = EXT_CH_MODE_BOTH_EDGES | sensor->ext_mode;
sensor->ext_cfg.cb = dht11_lld_ext_handler;
chSysLock();
extSetChannelModeI(sensor->ext_drv, sensor->ext_pin, &sensor->ext_cfg);
extChannelDisableI(sensor->ext_drv, sensor->ext_pin);
chSysUnlock();
state = sensor->state = DHT11_IDLE;
lldUnlock(&sensor->lock);
return state;
}
else
{
return DHT11_UNINIT;
}
}
/*
* @brief ...
*/
bool dht11Update(dht11_t *sensor, varg_t unused)
{
//
(void) unused;
dht11_state_t state;
if (lldLock(&sensor->lock) == true)
{
// low pulse
sensor->bit_count = 0;
state = sensor->state = DHT11_READ_REQUEST;
palSetPadMode(sensor->ext_port, sensor->ext_pin, PAL_MODE_OUTPUT_PUSHPULL);
palClearPad(sensor->ext_port, sensor->ext_pin);
osalSysLock();
gptStopTimerI(&GPTD17);
gptStartContinuousI(&GPTD17, 65000);
chVTSetI(&sensor->timer, MS2ST(25), dht11_timer_handler, sensor);
osalSysUnlock();
lldUnlock(&sensor->lock);
//
return state;
}
else
{
return DHT11_BUSY;
}
}
/*
* @brief ...
*/
bool dht11GetTemperature(dht11_t *sensor, int8_t *temp)
{
//
*temp = sensor->temp;
return true;
}
/*
* @brief ...
*/
bool dht11GetHumidity(dht11_t *sensor, int8_t *humidity)
{
//
*humidity = sensor->humidity;
return true;
}
#endifIt uses Vitrual Timers, GPT17 fot high precision clocks and EXT interrupts.
A separate thread polls the sensor every 3 seconds. Another thread pools DS18B20 sensor which uses USART.
I've encountered a strange problem when disabling CH_DBG options:
Code: Select all
/**
* @brief Debug option, system state check.
* @details If enabled the correct call protocol for system APIs is checked
* at runtime.
*
* @note The default is @p FALSE.
*/
#if CH_DEBUG
#define CH_DBG_SYSTEM_STATE_CHECK TRUE
#else
#define CH_DBG_SYSTEM_STATE_CHECK FALSE
#endif
/**
* @brief Debug option, parameters checks.
* @details If enabled then the checks on the API functions input
* parameters are activated.
*
* @note The default is @p FALSE.
*/
#if CH_DEBUG
#define CH_DBG_ENABLE_CHECKS TRUE
#else
#define CH_DBG_ENABLE_CHECKS FALSE
#endif
/**
* @brief Debug option, consistency checks.
* @details If enabled then all the assertions in the kernel code are
* activated. This includes consistency checks inside the kernel,
* runtime anomalies and port-defined checks.
*
* @note The default is @p FALSE.
*/
#if CH_DEBUG
#define CH_DBG_ENABLE_ASSERTS TRUE
#else
#define CH_DBG_ENABLE_ASSERTS FALSE
#endif
/**
* @brief Debug option, trace buffer.
* @details If enabled then the context switch circular trace buffer is
* activated.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_ENABLE_TRACE FALSE
/**
* @brief Debug option, stack checks.
* @details If enabled then a runtime stack check is performed.
*
* @note The default is @p FALSE.
* @note The stack check is performed in a architecture/port dependent way.
* It may not be implemented or some ports.
* @note The default failure mode is to halt the system with the global
* @p panic_msg variable set to @p NULL.
*/
#if CH_DEBUG
#define CH_DBG_ENABLE_STACK_CHECK TRUE
#else
#define CH_DBG_ENABLE_STACK_CHECK FALSE
#endif
/**
* @brief Debug option, stacks initialization.
* @details If enabled then the threads working area is filled with a byte
* value when a thread is created. This can be useful for the
* runtime measurement of the used stack.
*
* @note The default is @p FALSE.
*/
#if CH_DEBUG
#define CH_DBG_FILL_THREADS TRUE
#else
#define CH_DBG_FILL_THREADS FALSE
#endifWhile they set to TRUE, all works fine:
Once I'm disabling this debug options - I'm getting strange aperiodic errors on DHT11. Some times values getting very big, just some smaller than 65535 and 16384. DS18B20 works fine both way.
I don't think that it's a Chibios problem, I suppose that it's from some delays caused by this debug checks, maybe they helps get rid of some jitter...
I racked my brains for a week and can't find the couse. Maybe here someone can help me...