From 4bd8dc6cb05f6ffe88986f5eb2cee7574cb36a49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 3 Feb 2018 10:09:51 +0100 Subject: [PATCH] split some files in units to smaller .c files, comments etc --- units/1wire/_ow_api.c | 130 +++++++++++++ units/1wire/_ow_checksum.c | 2 + units/1wire/_ow_checksum.h | 4 + units/1wire/_ow_commands.h | 4 + units/1wire/_ow_low_level.h | 4 + units/1wire/_ow_search.h | 3 +- units/1wire/unit_1wire.c | 182 ++---------------- units/i2c/_i2c_api.c | 124 ++++++++++++ units/i2c/_i2c_internal.h | 28 +++ units/i2c/unit_i2c.c | 130 +------------ units/usart/_settings_bin.c | 74 ------- units/usart/_usart_api.c | 56 ++++++ units/usart/{_dmas.c => _usart_dmas.c} | 2 +- units/usart/{_init.c => _usart_init.c} | 2 +- .../usart/{_internal.h => _usart_internal.h} | 0 .../{_settings_ini.c => _usart_settings.c} | 69 ++++++- units/usart/unit_usart.c | 63 ++---- 17 files changed, 456 insertions(+), 421 deletions(-) create mode 100644 units/1wire/_ow_api.c create mode 100644 units/i2c/_i2c_api.c create mode 100644 units/i2c/_i2c_internal.h delete mode 100644 units/usart/_settings_bin.c create mode 100644 units/usart/_usart_api.c rename units/usart/{_dmas.c => _usart_dmas.c} (99%) rename units/usart/{_init.c => _usart_init.c} (99%) rename units/usart/{_internal.h => _usart_internal.h} (100%) rename units/usart/{_settings_ini.c => _usart_settings.c} (78%) diff --git a/units/1wire/_ow_api.c b/units/1wire/_ow_api.c new file mode 100644 index 0000000..3ca5d91 --- /dev/null +++ b/units/1wire/_ow_api.c @@ -0,0 +1,130 @@ +// +// Created by MightyPork on 2018/02/03. +// + +#include "platform.h" +#include "unit_1wire.h" + +// 1WIRE master +#define OW_INTERNAL +#include "_ow_internal.h" +#include "_ow_commands.h" +#include "_ow_checksum.h" +#include "_ow_low_level.h" + +/* Check presence of any devices on the bus */ +error_t UU_1WIRE_CheckPresence(Unit *unit, bool *presence) +{ + CHECK_TYPE(unit, &UNIT_1WIRE); + // reset + *presence = ow_reset(unit); + return E_SUCCESS; +} + +/* Read address of a lone device on the bus */ +error_t UU_1WIRE_ReadAddress(Unit *unit, uint64_t *address) +{ + CHECK_TYPE(unit, &UNIT_1WIRE); + *address = 0; + if (!ow_reset(unit)) return E_HW_TIMEOUT; + + // command + ow_write_u8(unit, OW_ROM_READ); + + // read the ROM code + *address = ow_read_u64(unit); + + const uint8_t *addr_as_bytes = (void*)address; + if (0 != ow_checksum(addr_as_bytes, 8)) { + *address = 0; + return E_CHECKSUM_MISMATCH; // checksum mismatch + } + return E_SUCCESS; +} + +/* Write bytes to a device */ +error_t UU_1WIRE_Write(Unit *unit, uint64_t address, const uint8_t *buff, uint32_t len) +{ + CHECK_TYPE(unit, &UNIT_1WIRE); + if (!ow_reset(unit)) return E_HW_TIMEOUT; + + // MATCH_ROM+addr, or SKIP_ROM + if (address != 0) { + ow_write_u8(unit, OW_ROM_MATCH); + ow_write_u64(unit, address); + } else { + ow_write_u8(unit, OW_ROM_SKIP); + } + + // write the payload; + for (uint32_t i = 0; i < len; i++) { + ow_write_u8(unit, *buff++); + } + return E_SUCCESS; +} + +/* Write a request to a device and read a response */ +error_t UU_1WIRE_Read(Unit *unit, uint64_t address, + const uint8_t *request_buff, uint32_t request_len, + uint8_t *response_buff, uint32_t response_len, bool check_crc) +{ + CHECK_TYPE(unit, &UNIT_1WIRE); + if (!ow_reset(unit)) return E_HW_TIMEOUT; + + uint8_t *rb = response_buff; + + // MATCH_ROM+addr, or SKIP_ROM + if (address != 0) { + ow_write_u8(unit, OW_ROM_MATCH); + ow_write_u64(unit, address); + } else { + ow_write_u8(unit, OW_ROM_SKIP); + } + + // write the payload; + for (uint32_t i = 0; i < request_len; i++) { + ow_write_u8(unit, *request_buff++); + } + + // read the requested number of bytes + for (uint32_t i = 0; i < response_len; i++) { + *rb++ = ow_read_u8(unit); + } + + if (check_crc) { + if (0 != ow_checksum(response_buff, response_len)) { + return E_CHECKSUM_MISMATCH; + } + } + return E_SUCCESS; +} + +/* Perform the search algorithm (start or continue) */ +error_t UU_1WIRE_Search(Unit *unit, bool with_alarm, bool restart, + uint64_t *buffer, uint32_t capacity, uint32_t *real_count, + bool *have_more) +{ + CHECK_TYPE(unit, &UNIT_1WIRE); + struct priv *priv = unit->data; + + if (restart) { + uint8_t search_cmd = (uint8_t) (with_alarm ? OW_ROM_ALM_SEARCH : OW_ROM_SEARCH); + ow_search_init(unit, search_cmd, true); + } + + *real_count = ow_search_run(unit, (ow_romcode_t *) buffer, capacity); + + // resolve the code + switch (priv->searchState.status) { + case OW_SEARCH_MORE: + *have_more = priv->searchState.status == OW_SEARCH_MORE; + + case OW_SEARCH_DONE: + return E_SUCCESS; + + case OW_SEARCH_FAILED: + return priv->searchState.error; + } + + return E_FAILURE; +} diff --git a/units/1wire/_ow_checksum.c b/units/1wire/_ow_checksum.c index 1a179b5..66be8b1 100644 --- a/units/1wire/_ow_checksum.c +++ b/units/1wire/_ow_checksum.c @@ -3,6 +3,8 @@ // #include "platform.h" + +#define OW_INTERNAL #include "_ow_checksum.h" static inline uint8_t crc8_bits(uint8_t data) diff --git a/units/1wire/_ow_checksum.h b/units/1wire/_ow_checksum.h index 581b197..fc9ef9a 100644 --- a/units/1wire/_ow_checksum.h +++ b/units/1wire/_ow_checksum.h @@ -5,6 +5,10 @@ #ifndef GEX_F072_OW_CHECKSUM_H #define GEX_F072_OW_CHECKSUM_H +#ifndef OW_INTERNAL +#error bad include! +#endif + #include /** diff --git a/units/1wire/_ow_commands.h b/units/1wire/_ow_commands.h index 4283b33..4270bde 100644 --- a/units/1wire/_ow_commands.h +++ b/units/1wire/_ow_commands.h @@ -5,6 +5,10 @@ #ifndef GEX_F072_OW_COMMANDS_H #define GEX_F072_OW_COMMANDS_H +#ifndef OW_INTERNAL +#error bad include! +#endif + #define OW_ROM_SEARCH 0xF0 #define OW_ROM_READ 0x33 #define OW_ROM_MATCH 0x55 diff --git a/units/1wire/_ow_low_level.h b/units/1wire/_ow_low_level.h index cddf896..b8e3dc4 100644 --- a/units/1wire/_ow_low_level.h +++ b/units/1wire/_ow_low_level.h @@ -5,6 +5,10 @@ #ifndef GEX_F072_OW_LOW_LEVEL_H #define GEX_F072_OW_LOW_LEVEL_H +#ifndef OW_INTERNAL +#error bad include! +#endif + #include "platform.h" #include "unit_base.h" #include "_ow_low_level.h" diff --git a/units/1wire/_ow_search.h b/units/1wire/_ow_search.h index e3d6cfc..738ef6d 100644 --- a/units/1wire/_ow_search.h +++ b/units/1wire/_ow_search.h @@ -75,7 +75,8 @@ void ow_search_init(Unit *unit, uint8_t command, bool test_checksums); * @param[in,out] state - search state, used for multiple calls with limited buffer size * @param[out] codes - buffer for found romcodes * @param[in] capacity - buffer capacity - * @return number of romcodes found. Search status is stored in state->status + * @return number of romcodes found. Search status is stored in `state->status`, + * possible error code in `status->error` */ uint32_t ow_search_run(Unit *unit, ow_romcode_t *codes, uint32_t capacity); diff --git a/units/1wire/unit_1wire.c b/units/1wire/unit_1wire.c index e4e5aca..106bc13 100644 --- a/units/1wire/unit_1wire.c +++ b/units/1wire/unit_1wire.c @@ -4,15 +4,11 @@ #include "comm/messages.h" #include "unit_base.h" -#include "utils/avrlibc.h" #include "unit_1wire.h" // 1WIRE master #define OW_INTERNAL #include "_ow_internal.h" -#include "_ow_commands.h" -#include "_ow_search.h" -#include "_ow_checksum.h" #include "_ow_low_level.h" // ------------------------------------------------------------------------ @@ -80,6 +76,16 @@ static void U1WIRE_writeIni(Unit *unit, IniWriter *iw) // ------------------------------------------------------------------------ +/** + * 1-Wire timer callback, used for the 'wait_ready' function. + * + * - In parasitic mode, this is a simple 750ms wait, after which a SUCCESS response is sent. + * - In 3-wire mode, the callback is fired periodically and performs a Read operation on the bus. + * The unit responds with 0 while the operation is ongoing. On receiving 1 a SUCCESS response is sent. + * The polling is abandoned after a timeout, sending a TIMEOUT response. + * + * @param xTimer + */ static void U1WIRE_TimerCb(TimerHandle_t xTimer) { Unit *unit = pvTimerGetTimerID(xTimer); @@ -87,6 +93,11 @@ static void U1WIRE_TimerCb(TimerHandle_t xTimer) struct priv *priv = unit->data; assert_param(priv->busy); + // XXX Possible bug + // This is run on the timers thread. The TF write functions block on a semaphore. + // The FreeRTOS documentation warns against blocking in the timers thread, + // but does not say why. This can be solved by scheduling the response using the job queue. + if (priv->parasitic) { // this is the end of the 750ms measurement time goto halt_ok; @@ -175,169 +186,6 @@ static void U1WIRE_deInit(Unit *unit) // ------------------------------------------------------------------------ -/** - * Check if there are any units present on the bus - * - * @param[in,out] unit - * @param[out] presence - any devices present - * @return success - */ -error_t UU_1WIRE_CheckPresence(Unit *unit, bool *presence) -{ - CHECK_TYPE(unit, &UNIT_1WIRE); - // reset - *presence = ow_reset(unit); - return E_SUCCESS; -} - -/** - * Read a device's address (use only with a single device attached) - * - * @param[in,out] unit - * @param[out] address - the device's address, 0 on error or CRC mismatch - * @return success - */ -error_t UU_1WIRE_ReadAddress(Unit *unit, uint64_t *address) -{ - CHECK_TYPE(unit, &UNIT_1WIRE); - *address = 0; - if (!ow_reset(unit)) return E_HW_TIMEOUT; - - // command - ow_write_u8(unit, OW_ROM_READ); - - // read the ROM code - *address = ow_read_u64(unit); - - const uint8_t *addr_as_bytes = (void*)address; - if (0 != ow_checksum(addr_as_bytes, 8)) { - *address = 0; - return E_CHECKSUM_MISMATCH; // checksum mismatch - } - return E_SUCCESS; -} - -/** - * Write bytes to a device / devices - * - * @param[in,out] unit - * @param[in] address - device address, 0 to skip match (single device or broadcast) - * @param[in] buff - bytes to write - * @param[in] len - buffer length - * @return success - */ -error_t UU_1WIRE_Write(Unit *unit, uint64_t address, const uint8_t *buff, uint32_t len) -{ - CHECK_TYPE(unit, &UNIT_1WIRE); - if (!ow_reset(unit)) return E_HW_TIMEOUT; - - // MATCH_ROM+addr, or SKIP_ROM - if (address != 0) { - ow_write_u8(unit, OW_ROM_MATCH); - ow_write_u64(unit, address); - } else { - ow_write_u8(unit, OW_ROM_SKIP); - } - - // write the payload; - for (uint32_t i = 0; i < len; i++) { - ow_write_u8(unit, *buff++); - } - return E_SUCCESS; -} - -/** - * Read bytes from a device / devices, first writing a query - * - * @param[in,out] unit - * @param[in] address - device address, 0 to skip match (single device ONLY!) - * @param[in] request_buff - bytes to write before reading a response - * @param[in] request_len - number of bytes to write - * @param[out] response_buff - buffer for storing the read response - * @param[in] response_len - number of bytes to read - * @param[in] check_crc - verify CRC - * @return success - */ -error_t UU_1WIRE_Read(Unit *unit, uint64_t address, - const uint8_t *request_buff, uint32_t request_len, - uint8_t *response_buff, uint32_t response_len, bool check_crc) -{ - CHECK_TYPE(unit, &UNIT_1WIRE); - if (!ow_reset(unit)) return E_HW_TIMEOUT; - - uint8_t *rb = response_buff; - - // MATCH_ROM+addr, or SKIP_ROM - if (address != 0) { - ow_write_u8(unit, OW_ROM_MATCH); - ow_write_u64(unit, address); - } else { - ow_write_u8(unit, OW_ROM_SKIP); - } - - // write the payload; - for (uint32_t i = 0; i < request_len; i++) { - ow_write_u8(unit, *request_buff++); - } - - // read the requested number of bytes - for (uint32_t i = 0; i < response_len; i++) { - *rb++ = ow_read_u8(unit); - } - - if (check_crc) { - if (0 != ow_checksum(response_buff, response_len)) { - return E_CHECKSUM_MISMATCH; - } - } - return E_SUCCESS; -} - -/** - * Perform a ROM search operation. - * The algorithm is on a depth-first search without backtracking, - * taking advantage of the open-drain topology. - * - * This function either starts the search, or continues it. - * - * @param[in,out] unit - * @param[in] with_alarm - true to match only devices in alarm state - * @param[in] restart - true to restart the search (search from the lowest address) - * @param[out] buffer - buffer for storing found addresses - * @param[in] capacity - buffer capacity in address entries (8 bytes) - * @param[out] real_count - real number of found addresses (for which the CRC matched) - * @param[out] have_more - flag indicating there are more devices to be found - * @return success - */ -error_t UU_1WIRE_Search(Unit *unit, bool with_alarm, bool restart, - uint64_t *buffer, uint32_t capacity, uint32_t *real_count, - bool *have_more) -{ - CHECK_TYPE(unit, &UNIT_1WIRE); - struct priv *priv = unit->data; - - if (restart) { - uint8_t search_cmd = (uint8_t) (with_alarm ? OW_ROM_ALM_SEARCH : OW_ROM_SEARCH); - ow_search_init(unit, search_cmd, true); - } - - *real_count = ow_search_run(unit, (ow_romcode_t *) buffer, capacity); - - // resolve the code - switch (priv->searchState.status) { - case OW_SEARCH_MORE: - *have_more = priv->searchState.status == OW_SEARCH_MORE; - - case OW_SEARCH_DONE: - return E_SUCCESS; - - case OW_SEARCH_FAILED: - return priv->searchState.error; - } - - return E_FAILURE; -} - enum PinCmd_ { CMD_CHECK_PRESENCE = 0, // simply tests that any devices are attached diff --git a/units/i2c/_i2c_api.c b/units/i2c/_i2c_api.c new file mode 100644 index 0000000..ec87d44 --- /dev/null +++ b/units/i2c/_i2c_api.c @@ -0,0 +1,124 @@ +// +// Created by MightyPork on 2018/02/03. +// + +#include "platform.h" +#include "unit_base.h" +#include "unit_i2c.h" + +#define I2C_INTERNAL +#include "_i2c_internal.h" + + +static void i2c_reset(struct priv *priv) +{ + LL_I2C_Disable(priv->periph); + HAL_Delay(1); + LL_I2C_Enable(priv->periph); +} + +static error_t i2c_wait_until_flag(struct priv *priv, uint32_t flag, bool stop_state) +{ + uint32_t t_start = HAL_GetTick(); + while (((priv->periph->ISR & flag)!=0) != stop_state) { + if (HAL_GetTick() - t_start > 10) { + i2c_reset(priv); + return E_HW_TIMEOUT; + } + } + return E_SUCCESS; +} + +error_t UU_I2C_Write(Unit *unit, uint16_t addr, const uint8_t *bytes, uint32_t bcount) +{ + CHECK_TYPE(unit, &UNIT_I2C); + + struct priv *priv = unit->data; + + uint8_t addrsize = (uint8_t) (((addr & 0x8000) == 0) ? 7 : 10); + addr &= 0x3FF; + uint32_t ll_addrsize = (addrsize == 7) ? LL_I2C_ADDRSLAVE_7BIT : LL_I2C_ADDRSLAVE_10BIT; + if (addrsize == 7) addr <<= 1; // 7-bit address must be shifted to left for LL to use it correctly + + TRY(i2c_wait_until_flag(priv, I2C_ISR_BUSY, 0)); + + bool first = true; + while (bcount > 0) { + uint32_t len = bcount; + uint32_t chunk_remain = (uint8_t) ((len > 255) ? 255 : len); // if more than 255, first chunk is 255 + LL_I2C_HandleTransfer(priv->periph, addr, ll_addrsize, chunk_remain, + (len > 255) ? LL_I2C_MODE_RELOAD : LL_I2C_MODE_AUTOEND, // Autoend if this is the last chunk + first ? LL_I2C_GENERATE_START_WRITE : LL_I2C_GENERATE_NOSTARTSTOP); // no start/stop condition if we're continuing + first = false; + bcount -= chunk_remain; + + for (; chunk_remain > 0; chunk_remain--) { + TRY(i2c_wait_until_flag(priv, I2C_ISR_TXIS, 1)); + uint8_t byte = *bytes++; + LL_I2C_TransmitData8(priv->periph, byte); + } + } + + TRY(i2c_wait_until_flag(priv, I2C_ISR_STOPF, 1)); + LL_I2C_ClearFlag_STOP(priv->periph); + return E_SUCCESS; +} + +error_t UU_I2C_Read(Unit *unit, uint16_t addr, uint8_t *dest, uint32_t bcount) +{ + CHECK_TYPE(unit, &UNIT_I2C); + + struct priv *priv = unit->data; + + uint8_t addrsize = (uint8_t) (((addr & 0x8000) == 0) ? 7 : 10); + addr &= 0x3FF; + uint32_t ll_addrsize = (addrsize == 7) ? LL_I2C_ADDRSLAVE_7BIT : LL_I2C_ADDRSLAVE_10BIT; + if (addrsize == 7) addr <<= 1; // 7-bit address must be shifted to left for LL to use it correctly + + TRY(i2c_wait_until_flag(priv, I2C_ISR_BUSY, 0)); + + bool first = true; + while (bcount > 0) { + if (!first) { + TRY(i2c_wait_until_flag(priv, I2C_ISR_TCR, 1)); + } + + uint8_t chunk_remain = (uint8_t) ((bcount > 255) ? 255 : bcount); // if more than 255, first chunk is 255 + LL_I2C_HandleTransfer(priv->periph, addr, ll_addrsize, chunk_remain, + (bcount > 255) ? LL_I2C_MODE_RELOAD : LL_I2C_MODE_AUTOEND, // Autoend if this is the last chunk + first ? LL_I2C_GENERATE_START_READ : LL_I2C_GENERATE_NOSTARTSTOP); // no start/stop condition if we're continuing + first = false; + bcount -= chunk_remain; + + for (; chunk_remain > 0; chunk_remain--) { + TRY(i2c_wait_until_flag(priv, I2C_ISR_RXNE, 1)); + + uint8_t byte = LL_I2C_ReceiveData8(priv->periph); + *dest++ = byte; + } + } + + TRY(i2c_wait_until_flag(priv, I2C_ISR_STOPF, 1)); + LL_I2C_ClearFlag_STOP(priv->periph); + return E_SUCCESS; +} + +error_t UU_I2C_ReadReg(Unit *unit, uint16_t addr, uint8_t regnum, uint8_t *dest, uint32_t width) +{ + TRY(UU_I2C_Write(unit, addr, ®num, 1)); + TRY(UU_I2C_Read(unit, addr, dest, width)); + return E_SUCCESS; +} + +error_t UU_I2C_WriteReg(Unit *unit, uint16_t addr, uint8_t regnum, const uint8_t *bytes, uint32_t width) +{ + CHECK_TYPE(unit, &UNIT_I2C); + + // we have to insert the address first - needs a buffer (XXX realistically the buffer needs 1-4 bytes + addr) + PayloadBuilder pb = pb_start((uint8_t*)unit_tmp512, UNIT_TMP_LEN, NULL); + pb_u8(&pb, regnum); + pb_buf(&pb, bytes, width); + + TRY(UU_I2C_Write(unit, addr, (uint8_t *) unit_tmp512, pb_length(&pb))); + return E_SUCCESS; +} diff --git a/units/i2c/_i2c_internal.h b/units/i2c/_i2c_internal.h new file mode 100644 index 0000000..ad5c19d --- /dev/null +++ b/units/i2c/_i2c_internal.h @@ -0,0 +1,28 @@ +// +// Created by MightyPork on 2018/02/03. +// + +#ifndef GEX_F072_I2C_INTERNAL_H +#define GEX_F072_I2C_INTERNAL_H + +#ifndef I2C_INTERNAL +#error bad include! +#endif + +/** Private data structure */ +struct priv { + uint8_t periph_num; //!< 1 or 2 + uint8_t remap; //!< I2C remap option + + bool anf; //!< Enable analog noise filter + uint8_t dnf; //!< Enable digital noise filter (1-15 ... max spike width) + uint8_t speed; //!< 0 - Standard, 1 - Fast, 2 - Fast+ + + I2C_TypeDef *periph; + +// GPIO_TypeDef *port; +// uint32_t ll_pin_scl; +// uint32_t ll_pin_sda; +}; + +#endif //GEX_F072_I2C_INTERNAL_H diff --git a/units/i2c/unit_i2c.c b/units/i2c/unit_i2c.c index 84b99c7..9293dee 100644 --- a/units/i2c/unit_i2c.c +++ b/units/i2c/unit_i2c.c @@ -8,22 +8,9 @@ #include "unit_i2c.h" // I2C master +#define I2C_INTERNAL +#include "_i2c_internal.h" -/** Private data structure */ -struct priv { - uint8_t periph_num; //!< 1 or 2 - uint8_t remap; //!< I2C remap option - - bool anf; //!< Enable analog noise filter - uint8_t dnf; //!< Enable digital noise filter (1-15 ... max spike width) - uint8_t speed; //!< 0 - Standard, 1 - Fast, 2 - Fast+ - - I2C_TypeDef *periph; - -// GPIO_TypeDef *port; -// uint32_t ll_pin_scl; -// uint32_t ll_pin_sda; -}; // ------------------------------------------------------------------------ @@ -285,119 +272,6 @@ enum PinCmd_ { CMD_READ_REG = 3, }; -static void i2c_reset(struct priv *priv) -{ - LL_I2C_Disable(priv->periph); - HAL_Delay(1); - LL_I2C_Enable(priv->periph); -} - -static error_t i2c_wait_until_flag(struct priv *priv, uint32_t flag, bool stop_state) -{ - uint32_t t_start = HAL_GetTick(); - while (((priv->periph->ISR & flag)!=0) != stop_state) { - if (HAL_GetTick() - t_start > 10) { - i2c_reset(priv); - return E_HW_TIMEOUT; - } - } - return E_SUCCESS; -} - -error_t UU_I2C_Write(Unit *unit, uint16_t addr, const uint8_t *bytes, uint32_t bcount) -{ - CHECK_TYPE(unit, &UNIT_I2C); - - struct priv *priv = unit->data; - - uint8_t addrsize = (uint8_t) (((addr & 0x8000) == 0) ? 7 : 10); - addr &= 0x3FF; - uint32_t ll_addrsize = (addrsize == 7) ? LL_I2C_ADDRSLAVE_7BIT : LL_I2C_ADDRSLAVE_10BIT; - if (addrsize == 7) addr <<= 1; // 7-bit address must be shifted to left for LL to use it correctly - - TRY(i2c_wait_until_flag(priv, I2C_ISR_BUSY, 0)); - - bool first = true; - while (bcount > 0) { - uint32_t len = bcount; - uint32_t chunk_remain = (uint8_t) ((len > 255) ? 255 : len); // if more than 255, first chunk is 255 - LL_I2C_HandleTransfer(priv->periph, addr, ll_addrsize, chunk_remain, - (len > 255) ? LL_I2C_MODE_RELOAD : LL_I2C_MODE_AUTOEND, // Autoend if this is the last chunk - first ? LL_I2C_GENERATE_START_WRITE : LL_I2C_GENERATE_NOSTARTSTOP); // no start/stop condition if we're continuing - first = false; - bcount -= chunk_remain; - - for (; chunk_remain > 0; chunk_remain--) { - TRY(i2c_wait_until_flag(priv, I2C_ISR_TXIS, 1)); - uint8_t byte = *bytes++; - LL_I2C_TransmitData8(priv->periph, byte); - } - } - - TRY(i2c_wait_until_flag(priv, I2C_ISR_STOPF, 1)); - LL_I2C_ClearFlag_STOP(priv->periph); - return E_SUCCESS; -} - -error_t UU_I2C_Read(Unit *unit, uint16_t addr, uint8_t *dest, uint32_t bcount) -{ - CHECK_TYPE(unit, &UNIT_I2C); - - struct priv *priv = unit->data; - - uint8_t addrsize = (uint8_t) (((addr & 0x8000) == 0) ? 7 : 10); - addr &= 0x3FF; - uint32_t ll_addrsize = (addrsize == 7) ? LL_I2C_ADDRSLAVE_7BIT : LL_I2C_ADDRSLAVE_10BIT; - if (addrsize == 7) addr <<= 1; // 7-bit address must be shifted to left for LL to use it correctly - - TRY(i2c_wait_until_flag(priv, I2C_ISR_BUSY, 0)); - - bool first = true; - while (bcount > 0) { - if (!first) { - TRY(i2c_wait_until_flag(priv, I2C_ISR_TCR, 1)); - } - - uint8_t chunk_remain = (uint8_t) ((bcount > 255) ? 255 : bcount); // if more than 255, first chunk is 255 - LL_I2C_HandleTransfer(priv->periph, addr, ll_addrsize, chunk_remain, - (bcount > 255) ? LL_I2C_MODE_RELOAD : LL_I2C_MODE_AUTOEND, // Autoend if this is the last chunk - first ? LL_I2C_GENERATE_START_READ : LL_I2C_GENERATE_NOSTARTSTOP); // no start/stop condition if we're continuing - first = false; - bcount -= chunk_remain; - - for (; chunk_remain > 0; chunk_remain--) { - TRY(i2c_wait_until_flag(priv, I2C_ISR_RXNE, 1)); - - uint8_t byte = LL_I2C_ReceiveData8(priv->periph); - *dest++ = byte; - } - } - - TRY(i2c_wait_until_flag(priv, I2C_ISR_STOPF, 1)); - LL_I2C_ClearFlag_STOP(priv->periph); - return E_SUCCESS; -} - -error_t UU_I2C_ReadReg(Unit *unit, uint16_t addr, uint8_t regnum, uint8_t *dest, uint32_t width) -{ - TRY(UU_I2C_Write(unit, addr, ®num, 1)); - TRY(UU_I2C_Read(unit, addr, dest, width)); - return E_SUCCESS; -} - -error_t UU_I2C_WriteReg(Unit *unit, uint16_t addr, uint8_t regnum, const uint8_t *bytes, uint32_t width) -{ - CHECK_TYPE(unit, &UNIT_I2C); - - // we have to insert the address first - needs a buffer (XXX realistically the buffer needs 1-4 bytes + addr) - PayloadBuilder pb = pb_start((uint8_t*)unit_tmp512, UNIT_TMP_LEN, NULL); - pb_u8(&pb, regnum); - pb_buf(&pb, bytes, width); - - TRY(UU_I2C_Write(unit, addr, (uint8_t *) unit_tmp512, pb_length(&pb))); - return E_SUCCESS; -} - /** Handle a request message */ static error_t UI2C_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp) { diff --git a/units/usart/_settings_bin.c b/units/usart/_settings_bin.c deleted file mode 100644 index dcfe398..0000000 --- a/units/usart/_settings_bin.c +++ /dev/null @@ -1,74 +0,0 @@ -// -// Created by MightyPork on 2018/01/14. -// - -#include "platform.h" -#include "unit_base.h" - -#define UUSART_INTERNAL -#include "_internal.h" - -/** Load from a binary buffer stored in Flash */ -void UUSART_loadBinary(Unit *unit, PayloadParser *pp) -{ - struct priv *priv = unit->data; - - uint8_t version = pp_u8(pp); - (void)version; - - priv->periph_num = pp_u8(pp); - priv->remap = pp_u8(pp); - - priv->baudrate = pp_u32(pp); - priv->parity = pp_u8(pp); - priv->stopbits = pp_u8(pp); - priv->direction = pp_u8(pp); - - priv->hw_flow_control = pp_u8(pp); - priv->clock_output = pp_bool(pp); - priv->cpol = pp_bool(pp); - priv->cpha = pp_bool(pp); - priv->lsb_first = pp_bool(pp); - priv->width = pp_u8(pp); - - priv->data_inv = pp_bool(pp); - priv->rx_inv = pp_bool(pp); - priv->tx_inv = pp_bool(pp); - - priv->de_output = pp_bool(pp); - priv->de_polarity = pp_bool(pp); - priv->de_assert_time = pp_u8(pp); - priv->de_clear_time = pp_u8(pp); -} - -/** Write to a binary buffer for storing in Flash */ -void UUSART_writeBinary(Unit *unit, PayloadBuilder *pb) -{ - struct priv *priv = unit->data; - - pb_u8(pb, 0); // version - - pb_u8(pb, priv->periph_num); - pb_u8(pb, priv->remap); - - pb_u32(pb, priv->baudrate); - pb_u8(pb, priv->parity); - pb_u8(pb, priv->stopbits); - pb_u8(pb, priv->direction); - - pb_u8(pb, priv->hw_flow_control); - pb_bool(pb, priv->clock_output); - pb_bool(pb, priv->cpol); - pb_bool(pb, priv->cpha); - pb_bool(pb, priv->lsb_first); - pb_u8(pb, priv->width); - - pb_bool(pb, priv->data_inv); - pb_bool(pb, priv->rx_inv); - pb_bool(pb, priv->tx_inv); - - pb_bool(pb, priv->de_output); - pb_bool(pb, priv->de_polarity); - pb_u8(pb, priv->de_assert_time); - pb_u8(pb, priv->de_clear_time); -} diff --git a/units/usart/_usart_api.c b/units/usart/_usart_api.c new file mode 100644 index 0000000..932621a --- /dev/null +++ b/units/usart/_usart_api.c @@ -0,0 +1,56 @@ +// +// Created by MightyPork on 2018/02/03. +// + +#include "platform.h" +#include "unit_base.h" +#include "unit_usart.h" + +#define UUSART_INTERNAL +#include "_usart_internal.h" + + +error_t UU_USART_Write(Unit *unit, const uint8_t *buffer, uint32_t len) +{ + CHECK_TYPE(unit, &UNIT_USART); + struct priv *priv = unit->data; + + uint32_t t_start = HAL_GetTick(); + while (len > 0) { + // this should be long enough even for the slowest bitrates and 512 bytes + if (HAL_GetTick() - t_start > 5000) { + return E_HW_TIMEOUT; + } + + uint16_t chunk = UUSART_DMA_TxQueue(priv, buffer, (uint16_t) len); + + buffer += chunk; + len -= chunk; + + // We give up control if there's another thread waiting and this isn't the last cycle + if (len > 0) { + osThreadYield(); + } + } + + return E_SUCCESS; +} + + +error_t UU_USART_WriteSync(Unit *unit, const uint8_t *buffer, uint32_t len) +{ + CHECK_TYPE(unit, &UNIT_USART); + struct priv *priv = unit->data; + + TRY(UU_USART_Write(unit, buffer, len)); + + // Now wait for the last DMA to complete + uint32_t t_start = HAL_GetTick(); + while (priv->tx_dma_busy) { + if (HAL_GetTick() - t_start > 1000) { + return E_HW_TIMEOUT; + } + } + + return E_SUCCESS; +} diff --git a/units/usart/_dmas.c b/units/usart/_usart_dmas.c similarity index 99% rename from units/usart/_dmas.c rename to units/usart/_usart_dmas.c index 5c51694..1723832 100644 --- a/units/usart/_dmas.c +++ b/units/usart/_usart_dmas.c @@ -7,7 +7,7 @@ #include "unit_base.h" #define UUSART_INTERNAL -#include "_internal.h" +#include "_usart_internal.h" static void UUSART_DMA_RxHandler(void *arg); static void UUSART_DMA_TxHandler(void *arg); diff --git a/units/usart/_init.c b/units/usart/_usart_init.c similarity index 99% rename from units/usart/_init.c rename to units/usart/_usart_init.c index a4068f5..87a733e 100644 --- a/units/usart/_init.c +++ b/units/usart/_usart_init.c @@ -6,7 +6,7 @@ #include "unit_base.h" #define UUSART_INTERNAL -#include "_internal.h" +#include "_usart_internal.h" extern error_t UUSART_ClaimDMAs(Unit *unit); extern error_t UUSART_SetupDMAs(Unit *unit); diff --git a/units/usart/_internal.h b/units/usart/_usart_internal.h similarity index 100% rename from units/usart/_internal.h rename to units/usart/_usart_internal.h diff --git a/units/usart/_settings_ini.c b/units/usart/_usart_settings.c similarity index 78% rename from units/usart/_settings_ini.c rename to units/usart/_usart_settings.c index 487465c..4e17273 100644 --- a/units/usart/_settings_ini.c +++ b/units/usart/_usart_settings.c @@ -4,10 +4,75 @@ #include "platform.h" #include "unit_base.h" -#include "avrlibc.h" +#include "unit_usart.h" #define UUSART_INTERNAL -#include "_internal.h" +#include "_usart_internal.h" + +/** Load from a binary buffer stored in Flash */ +void UUSART_loadBinary(Unit *unit, PayloadParser *pp) +{ + struct priv *priv = unit->data; + + uint8_t version = pp_u8(pp); + (void)version; + + priv->periph_num = pp_u8(pp); + priv->remap = pp_u8(pp); + + priv->baudrate = pp_u32(pp); + priv->parity = pp_u8(pp); + priv->stopbits = pp_u8(pp); + priv->direction = pp_u8(pp); + + priv->hw_flow_control = pp_u8(pp); + priv->clock_output = pp_bool(pp); + priv->cpol = pp_bool(pp); + priv->cpha = pp_bool(pp); + priv->lsb_first = pp_bool(pp); + priv->width = pp_u8(pp); + + priv->data_inv = pp_bool(pp); + priv->rx_inv = pp_bool(pp); + priv->tx_inv = pp_bool(pp); + + priv->de_output = pp_bool(pp); + priv->de_polarity = pp_bool(pp); + priv->de_assert_time = pp_u8(pp); + priv->de_clear_time = pp_u8(pp); +} + +/** Write to a binary buffer for storing in Flash */ +void UUSART_writeBinary(Unit *unit, PayloadBuilder *pb) +{ + struct priv *priv = unit->data; + + pb_u8(pb, 0); // version + + pb_u8(pb, priv->periph_num); + pb_u8(pb, priv->remap); + + pb_u32(pb, priv->baudrate); + pb_u8(pb, priv->parity); + pb_u8(pb, priv->stopbits); + pb_u8(pb, priv->direction); + + pb_u8(pb, priv->hw_flow_control); + pb_bool(pb, priv->clock_output); + pb_bool(pb, priv->cpol); + pb_bool(pb, priv->cpha); + pb_bool(pb, priv->lsb_first); + pb_u8(pb, priv->width); + + pb_bool(pb, priv->data_inv); + pb_bool(pb, priv->rx_inv); + pb_bool(pb, priv->tx_inv); + + pb_bool(pb, priv->de_output); + pb_bool(pb, priv->de_polarity); + pb_u8(pb, priv->de_assert_time); + pb_u8(pb, priv->de_clear_time); +} /** Parse a key-value pair from the INI file */ error_t UUSART_loadIni(Unit *unit, const char *key, const char *value) diff --git a/units/usart/unit_usart.c b/units/usart/unit_usart.c index 09dcc63..985074a 100644 --- a/units/usart/unit_usart.c +++ b/units/usart/unit_usart.c @@ -6,8 +6,18 @@ #include "unit_usart.h" #define UUSART_INTERNAL -#include "_internal.h" +#include "_usart_internal.h" +/** + * Data RX handler, run on the jobs thread. + * + * unit - unit + * timestamp - timestamp + * data1 - read start position + * data2 - nr of bytes to read + * + * @param job + */ static void UUSART_SendReceivedDataToMaster(Job *job) { Unit *unit = job->unit; @@ -27,7 +37,9 @@ static void UUSART_SendReceivedDataToMaster(Job *job) } /** - * Handle received data (we're inside the IRQ) + * Handle received data (we're inside the IRQ). + * This is called either from a DMA complete / half interrupot, + * or form the timeout interrupt. * * @param unit - handled unit * @param endpos - end position in the buffer @@ -79,51 +91,6 @@ void UUSART_Tick(Unit *unit) } } - -error_t UU_USART_Write(Unit *unit, const uint8_t *buffer, uint32_t len) -{ - CHECK_TYPE(unit, &UNIT_USART); - struct priv *priv = unit->data; - - uint32_t t_start = HAL_GetTick(); - while (len > 0) { - // this should be long enough even for the slowest bitrates and 512 bytes - if (HAL_GetTick() - t_start > 5000) { - return E_HW_TIMEOUT; - } - - uint16_t chunk = UUSART_DMA_TxQueue(priv, buffer, (uint16_t) len); - - buffer += chunk; - len -= chunk; - - // We give up control if there's another thread waiting and this isn't the last cycle - if (len > 0) { - osThreadYield(); - } - } - - return E_SUCCESS; -} - -error_t UU_USART_WriteSync(Unit *unit, const uint8_t *buffer, uint32_t len) -{ - CHECK_TYPE(unit, &UNIT_USART); - struct priv *priv = unit->data; - - TRY(UU_USART_Write(unit, buffer, len)); - - // Now wait for the last DMA to complete - uint32_t t_start = HAL_GetTick(); - while (priv->tx_dma_busy) { - if (HAL_GetTick() - t_start > 1000) { - return E_HW_TIMEOUT; - } - } - - return E_SUCCESS; -} - enum PinCmd_ { CMD_WRITE = 0, CMD_WRITE_SYNC = 1, @@ -135,11 +102,13 @@ static error_t UUSART_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, uint32_t len; const uint8_t *pld; switch (command) { + /** Write bytes to the USART. Payload consists of the data to send. Waits for completion. */ case CMD_WRITE: pld = pp_tail(pp, &len); TRY(UU_USART_Write(unit, pld, len)); return E_SUCCESS; + /** Write bytes to the USART, without waiting for completion. */ case CMD_WRITE_SYNC: pld = pp_tail(pp, &len); TRY(UU_USART_WriteSync(unit, pld, len));