onewire_master: remove malloc in favor of pre-allocated buffers
This commit is contained in:
parent
51dad418ad
commit
51bda8b90f
|
@ -17,13 +17,14 @@
|
||||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||||
* @date 2017
|
* @date 2017
|
||||||
* @note peripherals used: timer @ref onewire_master_timer, GPIO @ref onewire_master_gpio
|
* @note peripherals used: timer @ref onewire_master_timer, GPIO @ref onewire_master_gpio
|
||||||
* @warning this library does not support parasite power mode
|
* @note overdrive mode is not supported
|
||||||
|
* @warning this library does not support active parasite power mode (more than the pull-up resistor itself)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* standard libraries */
|
/* standard libraries */
|
||||||
#include <stdint.h> // standard integer types
|
#include <stdint.h> // standard integer types
|
||||||
#include <stdbool.h> // boolean type
|
#include <stdbool.h> // boolean type
|
||||||
#include <stdlib.h> // memory utilities
|
#include <stddef.h> // NULL definition
|
||||||
|
|
||||||
/* STM32 (including CM3) libraries */
|
/* STM32 (including CM3) libraries */
|
||||||
#include <libopencmsis/core_cm3.h> // Cortex M3 utilities
|
#include <libopencmsis/core_cm3.h> // Cortex M3 utilities
|
||||||
|
@ -64,8 +65,8 @@ volatile enum {
|
||||||
|
|
||||||
volatile bool slave_presence = false; /**< if slaves have been detected */
|
volatile bool slave_presence = false; /**< if slaves have been detected */
|
||||||
uint8_t* buffer = NULL; /**< input/output buffer for read/write commands/functions */
|
uint8_t* buffer = NULL; /**< input/output buffer for read/write commands/functions */
|
||||||
size_t buffer_size = 0; /**< size of buffer in bits */
|
uint32_t buffer_size = 0; /**< size of buffer in bits */
|
||||||
volatile size_t buffer_bit = 0; /**< number of bits read/written */
|
volatile uint32_t buffer_bit = 0; /**< number of bits read/written */
|
||||||
|
|
||||||
void onewire_master_setup(void)
|
void onewire_master_setup(void)
|
||||||
{
|
{
|
||||||
|
@ -81,10 +82,10 @@ void onewire_master_setup(void)
|
||||||
timer_set_prescaler(TIM(ONEWIRE_MASTER_TIMER), 1-1); // don't use prescale since this 16 bits timer allows to wait > 480 us used for the reset pulse ( 1/(72E6/1/(2**16))=910us )
|
timer_set_prescaler(TIM(ONEWIRE_MASTER_TIMER), 1-1); // don't use prescale since this 16 bits timer allows to wait > 480 us used for the reset pulse ( 1/(72E6/1/(2**16))=910us )
|
||||||
|
|
||||||
// use comparator to time signal (without using the output), starting at slot start
|
// use comparator to time signal (without using the output), starting at slot start
|
||||||
timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC1, 1*(rcc_ahb_frequency/1000000)); // use compare function to time master pulling low (1 < Tlowr < 15)
|
timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC1, 1*(rcc_ahb_frequency/1000000)-1); // use compare function to time master pulling low (1 < Tlowr < 15)
|
||||||
timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC2, 7*(rcc_ahb_frequency/1000000)); // use compare function to read of write (1 < Trw < 15)
|
timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC2, 7*(rcc_ahb_frequency/1000000)-1); // use compare function to read of write (1 < Trw < 15)
|
||||||
timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC3, 62*(rcc_ahb_frequency/1000000)); // use compare function to end time slot (60 < Tslot < 120), this will be followed by a recovery time (end of timer)
|
timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC3, 62*(rcc_ahb_frequency/1000000)-1); // use compare function to end time slot (60 < Tslot < 120), this will be followed by a recovery time (end of timer)
|
||||||
timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC4, 120*(rcc_ahb_frequency/1000000)); // use compare function to detect slave presence (60 < Tpdl < 240)
|
timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC4, 120*(rcc_ahb_frequency/1000000)-1); // use compare function to detect slave presence (60 < Tpdl < 240)
|
||||||
|
|
||||||
timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_UIF); // clear update (overflow) flag
|
timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_UIF); // clear update (overflow) flag
|
||||||
timer_update_on_overflow(TIM(ONEWIRE_MASTER_TIMER)); // only use counter overflow as UEV source (use overflow as start time or timeout)
|
timer_update_on_overflow(TIM(ONEWIRE_MASTER_TIMER)); // only use counter overflow as UEV source (use overflow as start time or timeout)
|
||||||
|
@ -100,7 +101,7 @@ bool onewire_master_reset(void)
|
||||||
// prepare timer
|
// prepare timer
|
||||||
timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer to reconfigure it
|
timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer to reconfigure it
|
||||||
timer_set_counter(TIM(ONEWIRE_MASTER_TIMER),0); // reset counter
|
timer_set_counter(TIM(ONEWIRE_MASTER_TIMER),0); // reset counter
|
||||||
timer_set_period(TIM(ONEWIRE_MASTER_TIMER), 490*(rcc_ahb_frequency/1000000)); // set timeout to > 480 us (490)
|
timer_set_period(TIM(ONEWIRE_MASTER_TIMER), 490*(rcc_ahb_frequency/1000000)-1); // set timeout to > 480 us
|
||||||
|
|
||||||
slave_presence = false; // reset state
|
slave_presence = false; // reset state
|
||||||
onewire_master_state = ONEWIRE_STATE_MASTER_RESET; // set new state
|
onewire_master_state = ONEWIRE_STATE_MASTER_RESET; // set new state
|
||||||
|
@ -119,7 +120,7 @@ bool onewire_master_reset(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** write bits on 1-Wire bus
|
/** write bits on 1-Wire bus
|
||||||
* @warning buffer_size must be set to the number of bits to write and buffer must contain the data to write
|
* @warning buffer_size must be set to the number of bits to writen and buffer must contain the data to write
|
||||||
* @return if write succeeded
|
* @return if write succeeded
|
||||||
*/
|
*/
|
||||||
static bool onewire_master_write(void)
|
static bool onewire_master_write(void)
|
||||||
|
@ -139,7 +140,7 @@ static bool onewire_master_write(void)
|
||||||
// start writing
|
// start writing
|
||||||
gpio_clear(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // pull signal low to start slot
|
gpio_clear(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // pull signal low to start slot
|
||||||
timer_enable_counter(TIM(ONEWIRE_MASTER_TIMER)); // start timer
|
timer_enable_counter(TIM(ONEWIRE_MASTER_TIMER)); // start timer
|
||||||
while (onewire_master_state!=ONEWIRE_STATE_DONE && onewire_master_state!=ONEWIRE_STATE_ERROR) { // wait until reset procedure completed
|
while (onewire_master_state!=ONEWIRE_STATE_DONE && onewire_master_state!=ONEWIRE_STATE_ERROR) { // wait until write procedure completed
|
||||||
__WFI(); // go to sleep
|
__WFI(); // go to sleep
|
||||||
}
|
}
|
||||||
if (ONEWIRE_STATE_ERROR==onewire_master_state) { // an error occurred
|
if (ONEWIRE_STATE_ERROR==onewire_master_state) { // an error occurred
|
||||||
|
@ -157,9 +158,6 @@ static bool onewire_master_read(void)
|
||||||
if (0==buffer_size) { // check input
|
if (0==buffer_size) { // check input
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!(buffer=realloc(buffer, (buffer_size-1)/8+1))) { // allocate memory
|
|
||||||
return false; // error in memory allocation
|
|
||||||
}
|
|
||||||
buffer_bit = 0; // reset bit index
|
buffer_bit = 0; // reset bit index
|
||||||
onewire_master_state = ONEWIRE_STATE_MASTER_READ; // set new state
|
onewire_master_state = ONEWIRE_STATE_MASTER_READ; // set new state
|
||||||
|
|
||||||
|
@ -175,7 +173,7 @@ static bool onewire_master_read(void)
|
||||||
// start reading
|
// start reading
|
||||||
gpio_clear(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // pull signal low to start slot
|
gpio_clear(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // pull signal low to start slot
|
||||||
timer_enable_counter(TIM(ONEWIRE_MASTER_TIMER)); // start timer
|
timer_enable_counter(TIM(ONEWIRE_MASTER_TIMER)); // start timer
|
||||||
while (onewire_master_state!=ONEWIRE_STATE_DONE && onewire_master_state!=ONEWIRE_STATE_ERROR) { // wait until reset procedure completed
|
while (onewire_master_state!=ONEWIRE_STATE_DONE && onewire_master_state!=ONEWIRE_STATE_ERROR) { // wait until read procedure completed
|
||||||
__WFI(); // go to sleep
|
__WFI(); // go to sleep
|
||||||
}
|
}
|
||||||
if (ONEWIRE_STATE_ERROR==onewire_master_state) { // an error occurred
|
if (ONEWIRE_STATE_ERROR==onewire_master_state) { // an error occurred
|
||||||
|
@ -184,14 +182,14 @@ static bool onewire_master_read(void)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t onewire_master_crc(uint8_t* data, size_t size)
|
uint8_t onewire_master_crc(uint8_t* data, uint32_t length)
|
||||||
{
|
{
|
||||||
if (NULL==data || 0==size) { // check input
|
if (NULL==data || 0==length) { // check input
|
||||||
return 0; // wrong input
|
return 0; // wrong input
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t crc = 0x00; // initial value
|
uint8_t crc = 0x00; // initial value
|
||||||
for (uint8_t i=0; i<size; i++) { // go through every byte
|
for (uint8_t i=0; i<length; i++) { // go through every byte
|
||||||
crc ^= data[i]; // XOR byte
|
crc ^= data[i]; // XOR byte
|
||||||
for (uint8_t b=0; b<8; b++) { // go through every bit
|
for (uint8_t b=0; b<8; b++) { // go through every bit
|
||||||
if (crc&0x01) { // least significant bit is set (we are using the reverse way)
|
if (crc&0x01) { // least significant bit is set (we are using the reverse way)
|
||||||
|
@ -204,14 +202,11 @@ uint8_t onewire_master_crc(uint8_t* data, size_t size)
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool onewire_master_function_read(uint8_t function, uint8_t* data, size_t bits)
|
bool onewire_master_function_read(uint8_t function, uint8_t* data, uint32_t bits)
|
||||||
{
|
{
|
||||||
// send function command
|
// send function command
|
||||||
buffer_size = 8; // function command is only one byte
|
buffer_size = 8; // function command is only one byte
|
||||||
if (!(buffer=realloc(buffer, (buffer_size-1)/8+1))) { // allocate memory
|
buffer = &function; // set the buffer to the function code
|
||||||
return false; // error in memory allocation
|
|
||||||
}
|
|
||||||
buffer[0] = function; // set function command
|
|
||||||
if (!onewire_master_write()) { // send command
|
if (!onewire_master_write()) { // send command
|
||||||
return false; // an error occurred
|
return false; // an error occurred
|
||||||
}
|
}
|
||||||
|
@ -222,52 +217,19 @@ bool onewire_master_function_read(uint8_t function, uint8_t* data, size_t bits)
|
||||||
|
|
||||||
// read data
|
// read data
|
||||||
buffer_size = bits; // save number of bits to read
|
buffer_size = bits; // save number of bits to read
|
||||||
|
buffer = data; // set the buffer to the data to write
|
||||||
if (!onewire_master_read()) { // read bits from slave
|
if (!onewire_master_read()) { // read bits from slave
|
||||||
return false; // an error occurred
|
return false; // an error occurred
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy data to user buffer
|
|
||||||
for (uint8_t i=0; i<bits/8; i++) { // copy bytes
|
|
||||||
data[i] = buffer[i]; // copy data
|
|
||||||
}
|
|
||||||
// copy remaining bits
|
|
||||||
switch (bits%8) {
|
|
||||||
case 1:
|
|
||||||
data[(bits-1)/8] = data[(bits-1)/8]&0x01;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
data[(bits-1)/8] = data[(bits-1)/8]&0x03;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
data[(bits-1)/8] = data[(bits-1)/8]&0x07;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
data[(bits-1)/8] = data[(bits-1)/8]&0x0f;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
data[(bits-1)/8] = data[(bits-1)/8]&0x1f;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
data[(bits-1)/8] = data[(bits-1)/8]&0x3f;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
data[(bits-1)/8] = data[(bits-1)/8]&0x7f;
|
|
||||||
break;
|
|
||||||
case 0: // no bits remaining
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool onewire_master_function_write(uint8_t function, uint8_t* data, size_t bits)
|
bool onewire_master_function_write(uint8_t function, uint8_t* data, uint32_t bits)
|
||||||
{
|
{
|
||||||
// send function command
|
// send function command
|
||||||
buffer_size = 8; // function command is only one byte
|
buffer_size = 8; // function command is only one byte
|
||||||
if (!(buffer=realloc(buffer, (buffer_size-1)/8+1))) { // allocate memory
|
buffer = &function; // set the buffer to the function code
|
||||||
return false; // error in memory allocation
|
|
||||||
}
|
|
||||||
buffer[0] = function; // set function command
|
|
||||||
if (!onewire_master_write()) { // send command
|
if (!onewire_master_write()) { // send command
|
||||||
return false; // an error occurred
|
return false; // an error occurred
|
||||||
}
|
}
|
||||||
|
@ -278,12 +240,7 @@ bool onewire_master_function_write(uint8_t function, uint8_t* data, size_t bits)
|
||||||
|
|
||||||
// copy data from user buffer
|
// copy data from user buffer
|
||||||
buffer_size = bits; // save number of bits to write
|
buffer_size = bits; // save number of bits to write
|
||||||
if (!(buffer=realloc(buffer, (buffer_size-1)/8+1))) { // allocate memory
|
buffer = data; // set the buffer to the data to write
|
||||||
return false; // error in memory allocation
|
|
||||||
}
|
|
||||||
for (uint8_t i=0; i<(buffer_size-1)/8+1; i++) { // copy bytes
|
|
||||||
buffer[i] = data[i]; // copy data
|
|
||||||
}
|
|
||||||
// write data
|
// write data
|
||||||
if (!onewire_master_write()) { // read bits from slave
|
if (!onewire_master_write()) { // read bits from slave
|
||||||
return false; // an error occurred
|
return false; // an error occurred
|
||||||
|
@ -304,7 +261,7 @@ uint64_t onewire_master_rom_read(void)
|
||||||
|
|
||||||
// return ROM code
|
// return ROM code
|
||||||
uint64_t code = 0;
|
uint64_t code = 0;
|
||||||
for (size_t i=0; i<8; i++) {
|
for (uint32_t i=0; i<8; i++) {
|
||||||
code += (uint64_t)rom_code[i]<<(8*i); // add byte
|
code += (uint64_t)rom_code[i]<<(8*i); // add byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,6 +286,7 @@ bool onewire_master_rom_search(uint64_t* code, bool alarm)
|
||||||
*code = 0; // restart search codes
|
*code = 0; // restart search codes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buffer = (uint8_t*){0}; // buffer to read up to two bits
|
||||||
for (uint8_t bit=0; bit<64; bit++) { // go through all 64 bits ROM code
|
for (uint8_t bit=0; bit<64; bit++) { // go through all 64 bits ROM code
|
||||||
buffer_size = 2; // read two first bits to detect conflict
|
buffer_size = 2; // read two first bits to detect conflict
|
||||||
if (!onewire_master_read()) { // read ROM ID from slave
|
if (!onewire_master_read()) { // read ROM ID from slave
|
||||||
|
@ -353,9 +311,6 @@ bool onewire_master_rom_search(uint64_t* code, bool alarm)
|
||||||
goto end; // an error has occurred
|
goto end; // an error has occurred
|
||||||
}
|
}
|
||||||
buffer_size = 1; // to send next bit
|
buffer_size = 1; // to send next bit
|
||||||
if (!(buffer=realloc(buffer, 1))) { // allocate memory
|
|
||||||
goto end; // an error has occurred
|
|
||||||
}
|
|
||||||
buffer[0] = (*code>>bit); // set bit to send
|
buffer[0] = (*code>>bit); // set bit to send
|
||||||
if (!onewire_master_write()) { // send bit
|
if (!onewire_master_write()) { // send bit
|
||||||
goto end; // an error has occurred
|
goto end; // an error has occurred
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||||
* @date 2017
|
* @date 2017
|
||||||
* @note peripherals used: timer @ref onewire_master_timer, GPIO @ref onewire_master_gpio
|
* @note peripherals used: timer @ref onewire_master_timer, GPIO @ref onewire_master_gpio
|
||||||
* @warning this library does not support parasite power mode
|
* @note overdrive mode is not supported
|
||||||
|
* @warning this library does not support active parasite power mode (more than the pull-up resistor itself)
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
@ -30,11 +31,11 @@ bool onewire_master_reset(void);
|
||||||
/** compute CRC for 1-Wire
|
/** compute CRC for 1-Wire
|
||||||
* @note this CRC-8 uses normal polynomial 0x31, reverse polynomial 0x8C, start value 0x00
|
* @note this CRC-8 uses normal polynomial 0x31, reverse polynomial 0x8C, start value 0x00
|
||||||
* @param[in] data bytes on which to calculate CRC checksum on
|
* @param[in] data bytes on which to calculate CRC checksum on
|
||||||
* @param[in] size number of bytes in data
|
* @param[in] length number of bytes in data
|
||||||
* @return computed CRC checksum
|
* @return computed CRC checksum
|
||||||
*/
|
*/
|
||||||
uint8_t onewire_master_crc(uint8_t* data, size_t size);
|
uint8_t onewire_master_crc(uint8_t* data, uint32_t length);
|
||||||
/** send READ ROM command
|
/** send READ ROM command and read ROM code response
|
||||||
* @note user needs to send reset pulse before
|
* @note user needs to send reset pulse before
|
||||||
* @return ROM code read
|
* @return ROM code read
|
||||||
*/
|
*/
|
||||||
|
@ -65,7 +66,7 @@ bool onewire_master_rom_match(uint64_t code);
|
||||||
* @param[in] bits number of bits to read (0 if only the function command should be sent)
|
* @param[in] bits number of bits to read (0 if only the function command should be sent)
|
||||||
* @return if operation succeeded
|
* @return if operation succeeded
|
||||||
*/
|
*/
|
||||||
bool onewire_master_function_read(uint8_t function, uint8_t* data, size_t bits);
|
bool onewire_master_function_read(uint8_t function, uint8_t* data, uint32_t bits);
|
||||||
/** issue function and write data
|
/** issue function and write data
|
||||||
* @note user needs to send a ROM command before
|
* @note user needs to send a ROM command before
|
||||||
* @param[in] function function command to send
|
* @param[in] function function command to send
|
||||||
|
@ -73,4 +74,4 @@ bool onewire_master_function_read(uint8_t function, uint8_t* data, size_t bits);
|
||||||
* @param[in] bits number of bits to write (0 if only the function command should be sent)
|
* @param[in] bits number of bits to write (0 if only the function command should be sent)
|
||||||
* @return if operation succeeded
|
* @return if operation succeeded
|
||||||
*/
|
*/
|
||||||
bool onewire_master_function_write(uint8_t function, uint8_t* data, size_t bits);
|
bool onewire_master_function_write(uint8_t function, uint8_t* data, uint32_t bits);
|
||||||
|
|
Loading…
Reference in New Issue