onewire_master: remove malloc in favor of pre-allocated buffers

This commit is contained in:
King Kévin 2017-08-01 19:17:22 +02:00
parent 51dad418ad
commit 51bda8b90f
2 changed files with 31 additions and 75 deletions

View File

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

View File

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