1-wire driver improvements.

This commit is contained in:
barthess 2016-01-24 20:41:06 +03:00
parent d43271e5bc
commit 956134d0ba
5 changed files with 182 additions and 101 deletions

View File

@ -46,6 +46,16 @@
#define ONEWIRE_CMD_CONVERT_TEMP 0x44
#define ONEWIRE_CMD_READ_SCRATCHPAD 0xBE
/**
* @brief How many bits will be used for transaction length storage.
*/
#define ONEWIRE_REG_BYTES_WIDTH 16U
/**
* @brief Precalculated maximum transaction length.
*/
#define ONEWIRE_MAX_TRANSACTION_LEN ((1U << ONEWIRE_REG_BYTES_WIDTH) - 1U)
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
@ -116,6 +126,20 @@ typedef struct {
* @brief Pointer to @p PWM driver used for communication.
*/
PWMDriver *pwmd;
/**
* @brief Pointer to configuration structure for underlying PWM driver.
* @note It is NOT constant because 1-wire driver needs to change them
* during normal functioning.
*/
PWMConfig *pwmcfg;
/**
* @brief Active logic level for master channel.
* @details Just set it to @p PWM_OUTPUT_ACTIVE_LOW when 1-wire bus
* connected to direct (not complementary) output of the timer.
* In opposite case you need to check documentation to choose
* correct value.
*/
pwmmode_t pwmmode;
/**
* @brief Number of PWM channel used as master pulse generator.
*/
@ -167,7 +191,7 @@ typedef struct {
*/
typedef struct {
/**
* @brief Bool flag. If @p true than only bus has only one slave device.
* @brief Bool flag. True when bus has single slave device.
*/
uint32_t single_device: 1;
/**
@ -260,7 +284,7 @@ typedef struct {
/**
* @brief Bytes number to be processing in current transaction.
*/
uint32_t bytes: 16;
uint32_t bytes: ONEWIRE_REG_BYTES_WIDTH;
} onewire_reg_t;
/**
@ -275,10 +299,6 @@ typedef struct {
* @brief Onewire config.
*/
const onewireConfig *config;
/**
* @brief Config for underlying PWM driver.
*/
PWMConfig pwmcfg;
/**
* @brief Pointer to I/O data buffer.
*/
@ -315,14 +335,11 @@ extern "C" {
bool onewireReset(onewireDriver *owp);
void onewireRead(onewireDriver *owp, uint8_t *rxbuf, size_t rxbytes);
uint8_t onewireCRC(const uint8_t *buf, size_t len);
void onewireWrite(onewireDriver *owp,
uint8_t *txbuf,
size_t txbytes,
systime_t pullup_time);
void onewireWrite(onewireDriver *owp, uint8_t *txbuf,
size_t txbytes, systime_t pullup_time);
#if ONEWIRE_USE_SEARCH_ROM
size_t onewireSearchRom(onewireDriver *owp,
uint8_t *result,
size_t max_rom_cnt);
uint8_t *result, size_t max_rom_cnt);
#endif /* ONEWIRE_USE_SEARCH_ROM */
#if ONEWIRE_SYNTH_SEARCH_TEST
void _synth_ow_write_bit(onewireDriver *owp, uint8_t bit);

View File

@ -63,7 +63,12 @@ on every timer overflow event.
/* Driver local definitions. */
/*===========================================================================*/
/**
* @brief Pulse width constants.
* @brief 1MHz clock for PWM driver.
*/
#define ONEWIRE_PWM_FREQUENCY 1000000
/**
* @brief Pulse width constants in microseconds.
* @details Inspired by Microchip's AN1199
* "1-Wire® Communication with PIC® Microcontroller"
*/
@ -100,23 +105,6 @@ onewireDriver OWD1;
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/**
* @brief Config for fast initialization of all config's fields
*/
static const PWMConfig pwm_default_cfg = {
1000000,
ONEWIRE_RESET_TOTAL_WIDTH,
NULL,
{
{PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL}
},
0,
0
};
/**
* @brief Look up table for fast 1-wire CRC calculation
*/
@ -173,7 +161,7 @@ static void ow_bus_idle(onewireDriver *owp) {
* @brief Put bus in active mode.
*/
static void ow_bus_active(onewireDriver *owp) {
pwmStart(owp->config->pwmd, &owp->pwmcfg);
pwmStart(owp->config->pwmd, owp->config->pwmcfg);
#if defined(STM32F1XX)
palSetPadMode(owp->config->port, owp->config->pad,
owp->config->pad_mode_active);
@ -588,8 +576,6 @@ void onewireObjectInit(onewireDriver *owp) {
owp->reg.final_timeslot = false;
owp->buf = NULL;
owp->pwmcfg = pwm_default_cfg;
#if ONEWIRE_USE_STRONG_PULLUP
owp->reg.need_pullup = false;
#endif
@ -615,6 +601,9 @@ void onewireStart(onewireDriver *owp, const onewireConfig *config) {
#endif
owp->config = config;
owp->config->pwmcfg->frequency = ONEWIRE_PWM_FREQUENCY;
owp->config->pwmcfg->period = ONEWIRE_RESET_TOTAL_WIDTH;
#if !defined(STM32F1XX)
palSetPadMode(owp->config->port, owp->config->pad,
owp->config->pad_mode_active);
@ -651,6 +640,7 @@ void onewireStop(onewireDriver *owp) {
*/
bool onewireReset(onewireDriver *owp) {
PWMDriver *pwmd;
PWMConfig *pwmcfg;
size_t mch, sch;
osalDbgCheck(NULL != owp);
@ -661,15 +651,17 @@ bool onewireReset(onewireDriver *owp) {
return false;
pwmd = owp->config->pwmd;
pwmcfg = owp->config->pwmcfg;
mch = owp->config->master_channel;
sch = owp->config->sample_channel;
owp->pwmcfg.period = ONEWIRE_RESET_LOW_WIDTH + ONEWIRE_RESET_SAMPLE_WIDTH;
owp->pwmcfg.callback = NULL;
owp->pwmcfg.channels[mch].callback = NULL;
owp->pwmcfg.channels[mch].mode = PWM_OUTPUT_ACTIVE_LOW;
owp->pwmcfg.channels[sch].callback = pwm_reset_cb;
owp->pwmcfg.channels[sch].mode = PWM_OUTPUT_ACTIVE_LOW;
pwmcfg->period = ONEWIRE_RESET_LOW_WIDTH + ONEWIRE_RESET_SAMPLE_WIDTH;
pwmcfg->callback = NULL;
pwmcfg->channels[mch].callback = NULL;
pwmcfg->channels[mch].mode = owp->config->pwmmode;
pwmcfg->channels[sch].callback = pwm_reset_cb;
pwmcfg->channels[sch].mode = PWM_OUTPUT_ACTIVE_LOW;
ow_bus_active(owp);
pwmEnableChannel(pwmd, mch, ONEWIRE_RESET_LOW_WIDTH);
@ -696,10 +688,11 @@ bool onewireReset(onewireDriver *owp) {
*/
void onewireRead(onewireDriver *owp, uint8_t *rxbuf, size_t rxbytes) {
PWMDriver *pwmd;
PWMConfig *pwmcfg;
size_t mch, sch;
osalDbgCheck((NULL != owp) && (NULL != rxbuf));
osalDbgCheck((rxbytes > 0) && (rxbytes < 65536));
osalDbgCheck((rxbytes > 0) && (rxbytes <= ONEWIRE_MAX_TRANSACTION_LEN));
osalDbgAssert(owp->reg.state == ONEWIRE_READY, "Invalid state");
/* Buffer zeroing. This is important because of driver collects
@ -707,6 +700,7 @@ void onewireRead(onewireDriver *owp, uint8_t *rxbuf, size_t rxbytes) {
memset(rxbuf, 0, rxbytes);
pwmd = owp->config->pwmd;
pwmcfg = owp->config->pwmcfg;
mch = owp->config->master_channel;
sch = owp->config->sample_channel;
@ -715,12 +709,12 @@ void onewireRead(onewireDriver *owp, uint8_t *rxbuf, size_t rxbytes) {
owp->buf = rxbuf;
owp->reg.bytes = rxbytes;
owp->pwmcfg.period = ONEWIRE_ZERO_WIDTH + ONEWIRE_RECOVERY_WIDTH;
owp->pwmcfg.callback = NULL;
owp->pwmcfg.channels[mch].callback = NULL;
owp->pwmcfg.channels[mch].mode = PWM_OUTPUT_ACTIVE_LOW;
owp->pwmcfg.channels[sch].callback = pwm_read_bit_cb;
owp->pwmcfg.channels[sch].mode = PWM_OUTPUT_ACTIVE_LOW;
pwmcfg->period = ONEWIRE_ZERO_WIDTH + ONEWIRE_RECOVERY_WIDTH;
pwmcfg->callback = NULL;
pwmcfg->channels[mch].callback = NULL;
pwmcfg->channels[mch].mode = owp->config->pwmmode;
pwmcfg->channels[sch].callback = pwm_read_bit_cb;
pwmcfg->channels[sch].mode = PWM_OUTPUT_ACTIVE_LOW;
ow_bus_active(owp);
pwmEnableChannel(pwmd, mch, ONEWIRE_ONE_WIDTH);
@ -746,10 +740,11 @@ void onewireRead(onewireDriver *owp, uint8_t *rxbuf, size_t rxbytes) {
void onewireWrite(onewireDriver *owp, uint8_t *txbuf,
size_t txbytes, systime_t pullup_time) {
PWMDriver *pwmd;
PWMConfig *pwmcfg;
size_t mch, sch;
osalDbgCheck((NULL != owp) && (NULL != txbuf));
osalDbgCheck((txbytes > 0) && (txbytes < 65536));
osalDbgCheck((txbytes > 0) && (txbytes <= ONEWIRE_MAX_TRANSACTION_LEN));
osalDbgAssert(owp->reg.state == ONEWIRE_READY, "Invalid state");
#if !ONEWIRE_USE_STRONG_PULLUP
osalDbgAssert(0 == pullup_time,
@ -757,6 +752,7 @@ void onewireWrite(onewireDriver *owp, uint8_t *txbuf,
#endif
pwmd = owp->config->pwmd;
pwmcfg = owp->config->pwmcfg;
mch = owp->config->master_channel;
sch = owp->config->sample_channel;
@ -765,12 +761,12 @@ void onewireWrite(onewireDriver *owp, uint8_t *txbuf,
owp->reg.final_timeslot = false;
owp->reg.bytes = txbytes;
owp->pwmcfg.period = ONEWIRE_ZERO_WIDTH + ONEWIRE_RECOVERY_WIDTH;
owp->pwmcfg.callback = pwm_write_bit_cb;
owp->pwmcfg.channels[mch].callback = NULL;
owp->pwmcfg.channels[mch].mode = PWM_OUTPUT_ACTIVE_LOW;
owp->pwmcfg.channels[sch].callback = NULL;
owp->pwmcfg.channels[sch].mode = PWM_OUTPUT_DISABLED;
pwmcfg->period = ONEWIRE_ZERO_WIDTH + ONEWIRE_RECOVERY_WIDTH;
pwmcfg->callback = pwm_write_bit_cb;
pwmcfg->channels[mch].callback = NULL;
pwmcfg->channels[mch].mode = owp->config->pwmmode;
pwmcfg->channels[sch].callback = NULL;
pwmcfg->channels[sch].mode = PWM_OUTPUT_DISABLED;
#if ONEWIRE_USE_STRONG_PULLUP
if (pullup_time > 0) {
@ -814,6 +810,7 @@ void onewireWrite(onewireDriver *owp, uint8_t *txbuf,
size_t onewireSearchRom(onewireDriver *owp, uint8_t *result,
size_t max_rom_cnt) {
PWMDriver *pwmd;
PWMConfig *pwmcfg;
uint8_t cmd;
size_t mch, sch;
@ -822,6 +819,7 @@ size_t onewireSearchRom(onewireDriver *owp, uint8_t *result,
osalDbgCheck((max_rom_cnt <= 256) && (max_rom_cnt > 0));
pwmd = owp->config->pwmd;
pwmcfg = owp->config->pwmcfg;
cmd = ONEWIRE_CMD_SEARCH_ROM;
mch = owp->config->master_channel;
sch = owp->config->sample_channel;
@ -847,12 +845,12 @@ size_t onewireSearchRom(onewireDriver *owp, uint8_t *result,
onewireWrite(&OWD1, &cmd, 1, 0);
/* Reconfiguration always needed because of previous call onewireWrite.*/
owp->pwmcfg.period = ONEWIRE_ZERO_WIDTH + ONEWIRE_RECOVERY_WIDTH;
owp->pwmcfg.callback = NULL;
owp->pwmcfg.channels[mch].callback = NULL;
owp->pwmcfg.channels[mch].mode = PWM_OUTPUT_ACTIVE_LOW;
owp->pwmcfg.channels[sch].callback = pwm_search_rom_cb;
owp->pwmcfg.channels[sch].mode = PWM_OUTPUT_ACTIVE_LOW;
pwmcfg->period = ONEWIRE_ZERO_WIDTH + ONEWIRE_RECOVERY_WIDTH;
pwmcfg->callback = NULL;
pwmcfg->channels[mch].callback = NULL;
pwmcfg->channels[mch].mode = owp->config->pwmmode;
pwmcfg->channels[sch].callback = pwm_search_rom_cb;
pwmcfg->channels[sch].mode = PWM_OUTPUT_ACTIVE_LOW;
ow_bus_active(owp);
pwmEnableChannel(pwmd, mch, ONEWIRE_ONE_WIDTH);

View File

@ -59,7 +59,7 @@
#define ONEWIRE_SAMPLE_CHANNEL 3
#else
#define ONEWIRE_PORT GPIOB
#define GPIOB_ONEWIRE GPIOB_TACHOMETER
#define ONEWIRE_PIN GPIOB_TACHOMETER
#include "pads.h"
#define ONEWIRE_PAD_MODE_ACTIVE (PAL_MODE_ALTERNATE(2) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUDR_PULLUP)
#define search_led_on red_led_on
@ -97,22 +97,46 @@ static uint8_t testbuf[12];
static int32_t temperature[3];
/*
* Config for underlied PWM driver.
* Note! It is NOT constant because 1-wire driver needs to change them
* during functioning.
*/
static PWMConfig pwm_cfg = {
0,
0,
NULL,
{
{PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL}
},
0,
#if STM32_PWM_USE_ADVANCED
0,
#endif
0
};
/*
*
*/
static const onewireConfig ow_cfg = {
&PWMD3,
ONEWIRE_MASTER_CHANNEL,
ONEWIRE_SAMPLE_CHANNEL,
ONEWIRE_PORT,
ONEWIRE_PIN,
&PWMD3,
&pwm_cfg,
PWM_OUTPUT_ACTIVE_LOW,
ONEWIRE_MASTER_CHANNEL,
ONEWIRE_SAMPLE_CHANNEL,
ONEWIRE_PORT,
ONEWIRE_PIN,
#if defined(STM32F1XX)
ONEWIRE_PAD_MODE_IDLE,
ONEWIRE_PAD_MODE_IDLE,
#endif
ONEWIRE_PAD_MODE_ACTIVE,
ONEWIRE_PAD_MODE_ACTIVE,
#if ONEWIRE_USE_STRONG_PULLUP
strong_pullup_assert,
strong_pullup_release
strong_pullup_assert,
strong_pullup_release
#endif
};
@ -129,16 +153,14 @@ static const onewireConfig ow_cfg = {
*
*/
static void strong_pullup_assert(void) {
palSetPadMode(GPIOB, GPIOB_ONEWIRE, PAL_MODE_ALTERNATE(2) |
PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_PUDR_PULLUP);
palSetPadMode(ONEWIRE_PORT, ONEWIRE_PIN, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
}
/**
*
*/
static void strong_pullup_release(void) {
palSetPadMode(GPIOB, GPIOB_ONEWIRE, PAL_MODE_ALTERNATE(2) |
PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUDR_PULLUP);
palSetPadMode(ONEWIRE_PORT, ONEWIRE_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
}
#endif /* ONEWIRE_USE_STRONG_PULLUP */

View File

@ -59,7 +59,7 @@
#define ONEWIRE_SAMPLE_CHANNEL 3
#else
#define ONEWIRE_PORT GPIOB
#define GPIOB_ONEWIRE GPIOB_TACHOMETER
#define ONEWIRE_PIN GPIOB_TACHOMETER
#include "pads.h"
#define ONEWIRE_PAD_MODE_ACTIVE (PAL_MODE_ALTERNATE(2) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUDR_PULLUP)
#define search_led_on red_led_on
@ -97,22 +97,46 @@ static uint8_t testbuf[12];
static int32_t temperature[3];
/*
* Config for underlied PWM driver.
* Note! It is NOT constant because 1-wire driver needs to change them
* during functioning.
*/
static PWMConfig pwm_cfg = {
0,
0,
NULL,
{
{PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL}
},
0,
#if STM32_PWM_USE_ADVANCED
0,
#endif
0
};
/*
*
*/
static const onewireConfig ow_cfg = {
&PWMD3,
ONEWIRE_MASTER_CHANNEL,
ONEWIRE_SAMPLE_CHANNEL,
ONEWIRE_PORT,
ONEWIRE_PIN,
&PWMD3,
&pwm_cfg,
PWM_OUTPUT_ACTIVE_LOW,
ONEWIRE_MASTER_CHANNEL,
ONEWIRE_SAMPLE_CHANNEL,
ONEWIRE_PORT,
ONEWIRE_PIN,
#if defined(STM32F1XX)
ONEWIRE_PAD_MODE_IDLE,
ONEWIRE_PAD_MODE_IDLE,
#endif
ONEWIRE_PAD_MODE_ACTIVE,
ONEWIRE_PAD_MODE_ACTIVE,
#if ONEWIRE_USE_STRONG_PULLUP
strong_pullup_assert,
strong_pullup_release
strong_pullup_assert,
strong_pullup_release
#endif
};
@ -129,16 +153,14 @@ static const onewireConfig ow_cfg = {
*
*/
static void strong_pullup_assert(void) {
palSetPadMode(GPIOB, GPIOB_ONEWIRE, PAL_MODE_ALTERNATE(2) |
PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_PUDR_PULLUP);
palSetPadMode(ONEWIRE_PORT, ONEWIRE_PIN, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
}
/**
*
*/
static void strong_pullup_release(void) {
palSetPadMode(GPIOB, GPIOB_ONEWIRE, PAL_MODE_ALTERNATE(2) |
PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUDR_PULLUP);
palSetPadMode(ONEWIRE_PORT, ONEWIRE_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
}
#endif /* ONEWIRE_USE_STRONG_PULLUP */

View File

@ -59,7 +59,7 @@
#define ONEWIRE_SAMPLE_CHANNEL 3
#else
#define ONEWIRE_PORT GPIOB
#define GPIOB_ONEWIRE GPIOB_TACHOMETER
#define ONEWIRE_PIN GPIOB_TACHOMETER
#include "pads.h"
#define ONEWIRE_PAD_MODE_ACTIVE (PAL_MODE_ALTERNATE(2) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUDR_PULLUP)
#define search_led_on red_led_on
@ -97,22 +97,46 @@ static uint8_t testbuf[12];
static int32_t temperature[3];
/*
* Config for underlied PWM driver.
* Note! It is NOT constant because 1-wire driver needs to change them
* during functioning.
*/
static PWMConfig pwm_cfg = {
0,
0,
NULL,
{
{PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL}
},
0,
#if STM32_PWM_USE_ADVANCED
0,
#endif
0
};
/*
*
*/
static const onewireConfig ow_cfg = {
&PWMD3,
ONEWIRE_MASTER_CHANNEL,
ONEWIRE_SAMPLE_CHANNEL,
ONEWIRE_PORT,
ONEWIRE_PIN,
&PWMD3,
&pwm_cfg,
PWM_OUTPUT_ACTIVE_LOW,
ONEWIRE_MASTER_CHANNEL,
ONEWIRE_SAMPLE_CHANNEL,
ONEWIRE_PORT,
ONEWIRE_PIN,
#if defined(STM32F1XX)
ONEWIRE_PAD_MODE_IDLE,
ONEWIRE_PAD_MODE_IDLE,
#endif
ONEWIRE_PAD_MODE_ACTIVE,
ONEWIRE_PAD_MODE_ACTIVE,
#if ONEWIRE_USE_STRONG_PULLUP
strong_pullup_assert,
strong_pullup_release
strong_pullup_assert,
strong_pullup_release
#endif
};
@ -129,16 +153,14 @@ static const onewireConfig ow_cfg = {
*
*/
static void strong_pullup_assert(void) {
palSetPadMode(GPIOB, GPIOB_ONEWIRE, PAL_MODE_ALTERNATE(2) |
PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_PUDR_PULLUP);
palSetPadMode(ONEWIRE_PORT, ONEWIRE_PIN, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
}
/**
*
*/
static void strong_pullup_release(void) {
palSetPadMode(GPIOB, GPIOB_ONEWIRE, PAL_MODE_ALTERNATE(2) |
PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUDR_PULLUP);
palSetPadMode(ONEWIRE_PORT, ONEWIRE_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
}
#endif /* ONEWIRE_USE_STRONG_PULLUP */