From 29264540f7bdb246b882b914eb215af22af81073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 13 Jan 2018 01:37:14 +0100 Subject: [PATCH] added uart init (untested) and more config option --- units/spi/unit_spi.c | 10 +- units/usart/unit_uart.c | 530 ++++++++++++++++++++++++++++------------ utils/str_utils.c | 72 ++++++ utils/str_utils.h | 52 ++-- 4 files changed, 488 insertions(+), 176 deletions(-) diff --git a/units/spi/unit_spi.c b/units/spi/unit_spi.c index dd3f924..72548c5 100644 --- a/units/spi/unit_spi.c +++ b/units/spi/unit_spi.c @@ -97,8 +97,8 @@ static error_t USPI_loadIni(Unit *unit, const char *key, const char *value) else if (streq(key, "tx-only")) { priv->tx_only = str_parse_yn(value, &suc); } - else if (streq(key, "lsb-first")) { - priv->lsb_first = str_parse_yn(value, &suc); + else if (streq(key, "first-bit")) { + priv->lsb_first = (bool)str_parse_2(value, "MSB", 0, "LSB", 1, &suc); } else if (streq(key, "port")) { suc = parse_port(value, &priv->ssn_port_name); @@ -151,8 +151,10 @@ static void USPI_writeIni(Unit *unit, IniWriter *iw) iw_comment(iw, "Transmit only, disable MISO"); iw_entry(iw, "tx-only", str_yn(priv->tx_only)); - iw_comment(iw, "Use LSB-first bit order"); - iw_entry(iw, "lsb-first", str_yn(priv->lsb_first)); + iw_comment(iw, "Bit order (LSB or MSB first)"); + iw_entry(iw, "first-bit", str_2((uint32_t)priv->lsb_first, + 0, "MSB", + 1, "LSB")); iw_cmt_newline(iw); iw_comment(iw, "SS port name"); diff --git a/units/usart/unit_uart.c b/units/usart/unit_uart.c index 596dbdd..36903dd 100644 --- a/units/usart/unit_uart.c +++ b/units/usart/unit_uart.c @@ -15,20 +15,26 @@ struct priv { uint8_t periph_num; //!< 1-6 uint8_t remap; //!< UART remap option - uint32_t baudrate; //!< UART baud rate + uint32_t baudrate; //!< baud rate uint8_t parity; //!< 0-none, 1-odd, 2-even - uint8_t stopbits; //!< 1-one, 2-2, 3-1.5 - bool enable_rx; //!< Configure and enable the Rx line - bool enable_tx; //!< Configure and enable the Tx line + uint8_t stopbits; //!< 0-half, 1-one, 2-one-and-half, 3-two (halves - 1) + uint8_t direction; //!< 1-RX, 2-TX, 3-RXTX - uint8_t hw_flow_control; //!< HW flow control 0-none, 1-RTX, 2-CTS, 3-both - bool clock_output; //!< Output serial clock + uint8_t hw_flow_control; //!< HW flow control 0-none, 1-RTC, 2-CTS, 3-full + bool clock_output; //!< Output serial clock bool cpol; //!< clock CPOL setting bool cpha; //!< clock CPHA setting + bool lsb_first; //!< bit order + uint8_t width; //!< word width - 7, 8, 9 (this includes parity) - uint32_t rx_buf_size; //!< Receive buffer size - uint32_t rx_full_thr; //!< Receive buffer full threshold (will be sent to PC) - uint16_t rx_timeout; //!< Receive timeout (time of inactivity before flushing to PC) + bool data_inv; //!< Invert data bytes + bool rx_inv; //!< Invert the RX pin levels + bool tx_inv; //!< Invert the TX pin levels + + bool de_output; //!< Generate the Driver Enable signal for RS485 + bool de_polarity; //!< DE active level + uint8_t de_assert_time; //!< Time to assert the DE signal before transmit + uint8_t de_clear_time; //!< Time to clear the DE signal after transmit USART_TypeDef *periph; }; @@ -46,18 +52,25 @@ static error_t UUSART_preInit(Unit *unit) priv->baudrate = 115200; priv->parity = 0; //!< 0-none, 1-odd, 2-even - priv->stopbits = 1; //!< 1-one, 2-2, 3-1.5 - priv->enable_rx = true; - priv->enable_tx = true; + priv->stopbits = 1; //!< 0-half, 1-one, 2-1.5, 3-two + priv->direction = 3; // RXTX priv->hw_flow_control = false; priv->clock_output = false; priv->cpol = 0; priv->cpha = 0; + priv->lsb_first = true; // LSB first is default for UART + priv->width = 8; + + priv->data_inv = false; + priv->rx_inv = false; + priv->tx_inv = false; - priv->rx_buf_size = 128; - priv->rx_full_thr = 90; - priv->rx_timeout = 3; // ms + priv->de_output = false; + priv->de_polarity = 1; // active high + // this should equal to a half-byte length when oversampling by 16 is used (default) + priv->de_assert_time = 8; + priv->de_clear_time = 8; return E_SUCCESS; } @@ -73,22 +86,28 @@ static void UUSART_loadBinary(Unit *unit, PayloadParser *pp) (void)version; priv->periph_num = pp_u8(pp); - priv->remap = pp_u8(pp); + priv->remap = pp_u8(pp); - priv->baudrate = pp_u32(pp); - priv->parity = pp_u8(pp); - priv->stopbits = pp_u8(pp); - priv->enable_rx = pp_bool(pp); - priv->enable_tx = pp_bool(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->rx_buf_size = pp_u32(pp); - priv->rx_full_thr = pp_u32(pp); - priv->rx_timeout = pp_u16(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 */ @@ -104,17 +123,23 @@ static void UUSART_writeBinary(Unit *unit, PayloadBuilder *pb) pb_u32(pb, priv->baudrate); pb_u8(pb, priv->parity); pb_u8(pb, priv->stopbits); - pb_bool(pb, priv->enable_rx); - pb_bool(pb, priv->enable_tx); + 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_u32(pb, priv->rx_buf_size); - pb_u32(pb, priv->rx_full_thr); - pb_u16(pb, priv->rx_timeout); + 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); } // ------------------------------------------------------------------------ @@ -135,22 +160,39 @@ static error_t UUSART_loadIni(Unit *unit, const char *key, const char *value) priv->baudrate = (uint32_t ) avr_atoi(value); } else if (streq(key, "parity")) { - priv->parity = (uint8_t) avr_atoi(value); + priv->parity = (uint8_t) str_parse_3(value, + "NONE", 0, + "ODD", 1, + "EVEN", 2, &suc); } else if (streq(key, "stop-bits")) { - priv->stopbits = (uint8_t) (1 + str_parse_012(value, "1", "2", "1.5", &suc)); + priv->stopbits = (uint8_t) str_parse_4(value, + "0.5", 0, + "1", 1, + "1.5", 2, + "2", 3, &suc); } - else if (streq(key, "enable-rx")) { - priv->enable_rx = str_parse_yn(value, &suc); - } - else if (streq(key, "enable-tx")) { - priv->enable_tx = str_parse_yn(value, &suc); + else if (streq(key, "direction")) { + priv->direction = (uint8_t) str_parse_3(value, + "RX", 1, + "TX", 2, + "RXTX", 3, &suc); } else if (streq(key, "hw-flow-control")) { - priv->hw_flow_control = (uint8_t) avr_atoi(value); + priv->hw_flow_control = (uint8_t) str_parse_4(value, + "NONE", 0, + "RTS", 1, + "CTS", 2, + "FULL", 3, &suc); + } + else if (streq(key, "word-width")) { + priv->width = (uint8_t ) avr_atoi(value); + } + else if (streq(key, "first-bit")) { + priv->lsb_first = (bool)str_parse_2(value, "MSB", 0, "LSB", 1, &suc); } - else if (streq(key, "synchronous")) { - priv->clock_output = (bool) avr_atoi(value); + else if (streq(key, "clock-output")) { + priv->clock_output = str_parse_yn(value, &suc); } else if (streq(key, "cpol")) { priv->cpol = (bool) avr_atoi(value); @@ -158,14 +200,17 @@ static error_t UUSART_loadIni(Unit *unit, const char *key, const char *value) else if (streq(key, "cpha")) { priv->cpha = (bool) avr_atoi(value); } - else if (streq(key, "rx-buffer")) { - priv->rx_buf_size = (uint32_t ) avr_atoi(value); + else if (streq(key, "de-output")) { + priv->de_output = str_parse_yn(value, &suc); } - else if (streq(key, "rx-full-theshold")) { - priv->rx_full_thr = (uint32_t ) avr_atoi(value); + else if (streq(key, "de-polarity")) { + priv->de_polarity = (bool) avr_atoi(value); } - else if (streq(key, "rx-timeout")) { - priv->rx_timeout = (uint16_t ) avr_atoi(value); + else if (streq(key, "de-assert-time")) { + priv->de_assert_time = (uint8_t) avr_atoi(value); + } + else if (streq(key, "de-clear-time")) { + priv->de_clear_time = (uint8_t) avr_atoi(value); } else { return E_BAD_KEY; @@ -180,14 +225,16 @@ static void UUSART_writeIni(Unit *unit, IniWriter *iw) { struct priv *priv = unit->data; - iw_comment(iw, "Peripheral number (UARTx)"); + iw_comment(iw, "Peripheral number (UARTx 1-4)"); iw_entry(iw, "device", "%d", (int)priv->periph_num); - iw_comment(iw, "Pin mappings (SCK,MISO,MOSI)"); + iw_comment(iw, "Pin mappings (TX,RX,CK,CTS,RTS)"); #if GEX_PLAT_F072_DISCOVERY // TODO -// iw_comment(iw, " SPI1: (0) A5,A6,A7 (1) B3,B4,B5 (2) E13,E14,E15"); -// iw_comment(iw, " SPI2: (0) B13,B14,B15 (1) D1,D3,D4"); + iw_comment(iw, " USART1: (0) A9,A10,A8,A11,A12 (1) B6,B7,A8,A11,A12"); + iw_comment(iw, " USART2: (0) A2,A3,A4,A0,A1 (1) D5,D6,D7,D3,D4"); + iw_comment(iw, " USART3: (0) B10,B11,B12,B13,B14 (1) D8,D9,D10,D11,D12"); + iw_comment(iw, " USART4: (0) A0,A1,C12,B7,A15 (1) C10,C11,C12,B7,A15"); #elif GEX_PLAT_F103_BLUEPILL #error "NO IMPL" #elif GEX_PLAT_F303_DISCOVERY @@ -200,37 +247,69 @@ static void UUSART_writeIni(Unit *unit, IniWriter *iw) iw_entry(iw, "remap", "%d", (int)priv->remap); iw_cmt_newline(iw); - iw_comment(iw, "Baud rate"); // TODO examples/range + iw_comment(iw, "Baud rate in bps (eg. 9600, 115200)"); // TODO examples/range iw_entry(iw, "baud-rate", "%d", (int)priv->baudrate); - iw_comment(iw, "Parity (0-none, 1-odd, 2-even)"); - iw_entry(iw, "parity", "%d", (int)priv->parity); - - iw_comment(iw, "Stop-bits (1, 1.5, 2)"); - iw_entry(iw, "stop-bits", "%s", (priv->stopbits==3)?"1.5":(priv->stopbits==2?"2":"1")); - - iw_comment(iw, "Enable the RX / TX lines"); - iw_entry(iw, "exable-rx", str_yn(priv->enable_rx)); - iw_entry(iw, "exable-tx", str_yn(priv->enable_tx)); + iw_comment(iw, "Parity type (NONE, ODD, EVEN)"); + iw_entry(iw, "parity", "%s", str_3(priv->parity, + 0, "NONE", + 1, "ODD", + 2, "EVEN")); + + iw_comment(iw, "Number of stop bits (0.5, 1, 1.5, 2)"); + iw_entry(iw, "stop-bits", "%s", str_4(priv->stopbits, + 0, "0.5", + 1, "1", + 2, "1.5", + 3, "2")); + + iw_comment(iw, "Bit order (LSB or MSB first)"); + iw_entry(iw, "first-bit", str_2((uint32_t)priv->lsb_first, + 0, "MSB", + 1, "LSB")); + + iw_comment(iw, "Word width (7,8,9) - including parity bit if used"); + iw_entry(iw, "word-width", "%d", (int)priv->width); + + iw_comment(iw, "Enabled lines (RX,TX,RXTX)"); + iw_entry(iw, "direction", str_3(priv->direction, + 1, "RX", + 2, "TX", + 3, "RXTX")); + + iw_comment(iw, "Hardware flow control (NONE, RTS, CTS, FULL)"); + iw_entry(iw, "hw-flow-control", "%s", str_4(priv->hw_flow_control, + 0, "NONE", + 1, "RTS", + 2, "CTS", + 3, "FULL")); - iw_comment(iw, "Hardware flow control (NONE, RTS, CTS, ALL)"); - iw_entry(iw, "hw-flow-control", "%s", str_4(priv->hw_flow_control, 0, "NONE", 1, "RTS", 2, "CTS", 3, "ALL")); - - iw_comment(iw, "Clock output (Y,N) - N for async"); + iw_cmt_newline(iw); + iw_comment(iw, "Generate serial clock (Y,N)"); iw_entry(iw, "clock-output", str_yn(priv->clock_output)); - iw_comment(iw, "Sync: Clock polarity: 0,1 (clock idle level)"); + iw_comment(iw, "Output clock polarity: 0,1 (clock idle level)"); iw_entry(iw, "cpol", "%d", (int)priv->cpol); - iw_comment(iw, "Sync: Clock phase: 0,1 (active edge, 0-first, 1-second)"); + iw_comment(iw, "Output clock phase: 0,1 (active edge, 0-first, 1-second)"); iw_entry(iw, "cpha", "%d", (int)priv->cpha); - iw_comment(iw, "Receive buffer capacity, full threshold and flush timeout"); - iw_entry(iw, "rx-buffer", "%d", (int)priv->rx_buf_size); - iw_entry(iw, "rx-full-theshold", "%d", (int)priv->rx_full_thr); - iw_entry(iw, "rx-timeout", "%d", (int)priv->rx_timeout); + iw_cmt_newline(iw); + iw_comment(iw, "Generate RS485 Driver Enable signal (Y,N) - uses RTS pin"); + iw_entry(iw, "de-output", str_yn(priv->de_output)); + iw_comment(iw, "DE active level: 0,1"); + iw_entry(iw, "de-polarity", "%d", (int)(priv->de_polarity)); + iw_comment(iw, "DE assert time (0-31)"); + iw_entry(iw, "de-assert-time", "%d", (int)(priv->de_assert_time)); + iw_comment(iw, "DE clear time (0-31)"); + iw_entry(iw, "de-clear-time", "%d", (int)(priv->de_clear_time)); } // ------------------------------------------------------------------------ +struct paf { + char port; + uint8_t pin; + uint8_t af; +}; /** Finalize unit set-up */ static error_t UUSART_init(Unit *unit) @@ -239,8 +318,7 @@ static error_t UUSART_init(Unit *unit) struct priv *priv = unit->data; if (!(priv->periph_num >= 1 && priv->periph_num <= 4)) { - dbg("!! Bad UART periph"); - // TODO count based on platform chip + dbg("!! Bad USART periph"); return E_BAD_CONFIG; } @@ -249,49 +327,124 @@ static error_t UUSART_init(Unit *unit) TRY(rsc_claim(unit, R_USART1)); priv->periph = USART1; } +#if defined(USART2) else if (priv->periph_num == 2) { TRY(rsc_claim(unit, R_USART2)); priv->periph = USART2; } +#endif +#if defined(USART3) else if (priv->periph_num == 3) { TRY(rsc_claim(unit, R_USART3)); priv->periph = USART3; } +#endif +#if defined(USART4) else if (priv->periph_num == 4) { TRY(rsc_claim(unit, R_USART4)); priv->periph = USART4; } +#endif + else return E_BAD_CONFIG; + // This is written for F072, other platforms will need adjustments // Configure UART pins (AF) - char uart_portname; - uint8_t pin_rx; - uint8_t pin_tx; - uint8_t pin_clk; - uint8_t pin_rts; - uint8_t pin_cts; - uint32_t af_uart; + const struct paf *mappings = NULL; // TODO #if GEX_PLAT_F072_DISCOVERY - // SPI1 - many options - // sck, miso, mosi, af + const struct paf mapping_1_0[5] = { + {'A', 8, LL_GPIO_AF_1}, // CK + {'A', 9, LL_GPIO_AF_1}, // TX + {'A', 10, LL_GPIO_AF_1}, // RX + {'A', 11, LL_GPIO_AF_1}, // CTS + {'A', 12, LL_GPIO_AF_1}, // RTS + }; + + const struct paf mapping_1_1[5] = { + {'A', 8, LL_GPIO_AF_1}, // CK + {'B', 6, LL_GPIO_AF_1}, // TX + {'B', 7, LL_GPIO_AF_1}, // RX + {'A', 11, LL_GPIO_AF_1}, // CTS + {'A', 12, LL_GPIO_AF_1}, // RTS + }; + + const struct paf mapping_2_0[5] = { + {'A', 4, LL_GPIO_AF_1}, // CK + {'A', 2, LL_GPIO_AF_1}, // TX + {'A', 3, LL_GPIO_AF_1}, // RX + {'A', 0, LL_GPIO_AF_1}, // CTS + {'A', 1, LL_GPIO_AF_1}, // RTS + }; + + const struct paf mapping_2_1[5] = { + {'D', 7, LL_GPIO_AF_0}, // CK + {'D', 5, LL_GPIO_AF_0}, // TX + {'D', 6, LL_GPIO_AF_0}, // RX + {'D', 3, LL_GPIO_AF_0}, // CTS + {'D', 4, LL_GPIO_AF_0}, // RTS + }; + + const struct paf mapping_3_0[5] = { + {'B', 12, LL_GPIO_AF_4}, // CK + {'B', 10, LL_GPIO_AF_4}, // TX + {'B', 11, LL_GPIO_AF_4}, // RX + {'B', 13, LL_GPIO_AF_4}, // CTS + {'B', 14, LL_GPIO_AF_4}, // RTS + }; + + const struct paf mapping_3_1[5] = { + {'D', 10, LL_GPIO_AF_0}, // CK + {'D', 8, LL_GPIO_AF_0}, // TX + {'D', 9, LL_GPIO_AF_0}, // RX + {'D', 11, LL_GPIO_AF_0}, // CTS + {'D', 12, LL_GPIO_AF_0}, // RTS + }; + + const struct paf mapping_4_0[5] = { + {'C', 12, LL_GPIO_AF_0}, // CK + {'A', 0, LL_GPIO_AF_4}, // TX + {'A', 1, LL_GPIO_AF_4}, // RX + {'B', 7, LL_GPIO_AF_4}, // CTS + {'A', 15, LL_GPIO_AF_4}, // RTS + }; + + const struct paf mapping_4_1[5] = { + {'C', 12, LL_GPIO_AF_0}, // CK + {'C', 10, LL_GPIO_AF_0}, // TX + {'C', 11, LL_GPIO_AF_0}, // RX + {'B', 7, LL_GPIO_AF_4}, // CTS + {'A', 15, LL_GPIO_AF_4}, // RTS + }; if (priv->periph_num == 1) { - // SPI1 - if (priv->remap == 0) { - uart_portname = 'A'; -// af_spi = LL_GPIO_AF_0; -// pin_sck = 5; -// pin_miso = 6; -// pin_mosi = 7; - } - else { - return E_BAD_CONFIG; - } + // USART1 + if (priv->remap == 0) mappings = &mapping_1_0[0]; + else if (priv->remap == 1) mappings = &mapping_1_1[0]; + else return E_BAD_CONFIG; + } + else if (priv->periph_num == 2) { + // USART2 + if (priv->remap == 0) mappings = &mapping_2_0[0]; + else if (priv->remap == 1) mappings = &mapping_2_1[0]; + else return E_BAD_CONFIG; + } + else if (priv->periph_num == 3) { + // USART3 + if (priv->remap == 0) mappings = &mapping_3_0[0]; + else if (priv->remap == 1) mappings = &mapping_3_1[0]; + else return E_BAD_CONFIG; + } + else if (priv->periph_num == 4) { + // USART3 + if (priv->remap == 0) mappings = &mapping_4_0[0]; + else if (priv->remap == 1) mappings = &mapping_4_1[0]; + else return E_BAD_CONFIG; } + else return E_BAD_CONFIG; // TODO other periphs #elif GEX_PLAT_F103_BLUEPILL @@ -303,54 +456,117 @@ static error_t UUSART_init(Unit *unit) #else #error "BAD PLATFORM!" #endif -// -// // first, we have to claim the pins -// TRY(rsc_claim_pin(unit, uart_portname, pin_mosi)); -// TRY(rsc_claim_pin(unit, uart_portname, pin_miso)); -// TRY(rsc_claim_pin(unit, uart_portname, pin_sck)); -// -// configure_gpio_alternate(uart_portname, pin_mosi, af_spi); -// configure_gpio_alternate(uart_portname, pin_miso, af_spi); -// configure_gpio_alternate(uart_portname, pin_sck, af_spi); -// -// if (priv->periph_num == 1) { -// __HAL_RCC_SPI1_CLK_ENABLE(); -// } else { -// __HAL_RCC_SPI2_CLK_ENABLE(); -// } -// -// // configure SSN GPIOs -// { -// // Claim all needed pins -// TRY(rsc_claim_gpios(unit, priv->ssn_port_name, priv->ssn_pins)); -// TRY(configure_sparse_pins(priv->ssn_port_name, priv->ssn_pins, &priv->ssn_port, -// LL_GPIO_MODE_OUTPUT, LL_GPIO_OUTPUT_PUSHPULL)); -// // Set the initial state - all high -// priv->ssn_port->BSRR = priv->ssn_pins; -// } -// -// // Configure SPI - must be configured under reset -// LL_SPI_Disable(priv->periph); -// { -// uint32_t presc = priv->prescaller; -// uint32_t lz = __CLZ(presc); -// if (lz < 23) lz = 23; -// if (lz > 30) lz = 30; -// presc = (32 - lz - 2); -// LL_SPI_SetBaudRatePrescaler(priv->periph, (presc<periph, priv->cpol ? LL_SPI_POLARITY_HIGH : LL_SPI_POLARITY_LOW); -// LL_SPI_SetClockPhase(priv->periph, priv->cpha ? LL_SPI_PHASE_1EDGE : LL_SPI_PHASE_2EDGE); -// LL_SPI_SetTransferDirection(priv->periph, priv->tx_only ? LL_SPI_HALF_DUPLEX_TX : LL_SPI_FULL_DUPLEX); -// LL_SPI_SetTransferBitOrder(priv->periph, priv->lsb_first ? LL_SPI_LSB_FIRST : LL_SPI_MSB_FIRST); -// -// LL_SPI_SetNSSMode(priv->periph, LL_SPI_NSS_SOFT); -// LL_SPI_SetDataWidth(priv->periph, LL_SPI_DATAWIDTH_8BIT); -// LL_SPI_SetRxFIFOThreshold(priv->periph, LL_SPI_RX_FIFO_TH_QUARTER); // trigger RXNE on 1 byte -// -// LL_SPI_SetMode(priv->periph, LL_SPI_MODE_MASTER); -// } -// LL_SPI_Enable(priv->periph); + + // CK + if (priv->clock_output) { + TRY(rsc_claim_pin(unit, mappings[0].port, mappings[0].pin)); + configure_gpio_alternate( mappings[0].port, mappings[0].pin, mappings[0].af); + } + // TX + if (priv->direction & 2) { + TRY(rsc_claim_pin(unit, mappings[1].port, mappings[1].pin)); + configure_gpio_alternate( mappings[1].port, mappings[1].pin, mappings[1].af); + } + // RX + if (priv->direction & 1) { + TRY(rsc_claim_pin(unit, mappings[2].port, mappings[2].pin)); + configure_gpio_alternate( mappings[2].port, mappings[2].pin, mappings[2].af); + } + // CTS + if (priv->hw_flow_control==2 || priv->hw_flow_control==3) { + TRY(rsc_claim_pin(unit, mappings[4].port, mappings[4].pin)); + configure_gpio_alternate( mappings[4].port, mappings[4].pin, mappings[4].af); + } + // RTS + if (priv->de_output || priv->hw_flow_control==1 || priv->hw_flow_control==3) { + TRY(rsc_claim_pin(unit, mappings[5].port, mappings[5].pin)); + configure_gpio_alternate( mappings[5].port, mappings[5].pin, mappings[5].af); + } + + if (priv->periph_num == 1) { + __HAL_RCC_USART1_CLK_ENABLE(); + } else if (priv->periph_num == 2) { + __HAL_RCC_USART2_CLK_ENABLE(); + } else if (priv->periph_num == 3) { + __HAL_RCC_USART3_CLK_ENABLE(); + } else if (priv->periph_num == 4) { + __HAL_RCC_USART4_CLK_ENABLE(); + } + + LL_USART_Disable(priv->periph); + { + LL_USART_DeInit(priv->periph); + LL_USART_SetBaudRate(priv->periph, + PLAT_AHB_MHZ/2,//FIXME this isn't great ... + LL_USART_OVERSAMPLING_16, + priv->baudrate); + + LL_USART_SetParity(priv->periph, + priv->parity == 0 ? LL_USART_PARITY_NONE : + priv->parity == 1 ? LL_USART_PARITY_ODD + : LL_USART_PARITY_EVEN); + + LL_USART_SetStopBitsLength(priv->periph, + priv->stopbits == 0 ? LL_USART_STOPBITS_0_5 : + priv->stopbits == 1 ? LL_USART_STOPBITS_1 : + priv->stopbits == 2 ? LL_USART_STOPBITS_1_5 + : LL_USART_STOPBITS_2); + + LL_USART_SetTransferDirection(priv->periph, + priv->direction == 1 ? LL_USART_DIRECTION_RX : + priv->direction == 2 ? LL_USART_DIRECTION_TX + : LL_USART_DIRECTION_TX_RX); + + LL_USART_SetHWFlowCtrl(priv->periph, + priv->hw_flow_control == 0 ? LL_USART_HWCONTROL_NONE : + priv->hw_flow_control == 1 ? LL_USART_HWCONTROL_RTS : + priv->hw_flow_control == 2 ? LL_USART_HWCONTROL_CTS + : LL_USART_HWCONTROL_RTS_CTS); + + LL_USART_ConfigClock(priv->periph, + priv->cpha ? LL_USART_PHASE_2EDGE + : LL_USART_PHASE_1EDGE, + priv->cpol ? LL_USART_POLARITY_HIGH + : LL_USART_POLARITY_LOW, + true); // clock on last bit - TODO configurable? + + if (priv->clock_output) + LL_USART_EnableSCLKOutput(priv->periph); + else + LL_USART_DisableSCLKOutput(priv->periph); + + LL_USART_SetTransferBitOrder(priv->periph, + priv->lsb_first ? LL_USART_BITORDER_LSBFIRST + : LL_USART_BITORDER_MSBFIRST); + + LL_USART_SetDataWidth(priv->periph, + priv->width == 7 ? LL_USART_DATAWIDTH_7B : + priv->width == 8 ? LL_USART_DATAWIDTH_8B + : LL_USART_DATAWIDTH_9B); + + LL_USART_SetBinaryDataLogic(priv->periph, + priv->data_inv ? LL_USART_BINARY_LOGIC_NEGATIVE + : LL_USART_BINARY_LOGIC_POSITIVE); + + LL_USART_SetRXPinLevel(priv->periph, priv->rx_inv ? LL_USART_RXPIN_LEVEL_INVERTED + : LL_USART_RXPIN_LEVEL_STANDARD); + + LL_USART_SetTXPinLevel(priv->periph, priv->tx_inv ? LL_USART_TXPIN_LEVEL_INVERTED + : LL_USART_TXPIN_LEVEL_STANDARD); + + if (priv->de_output) + LL_USART_EnableDEMode(priv->periph); + else + LL_USART_DisableDEMode(priv->periph); + + LL_USART_SetDESignalPolarity(priv->periph, + priv->de_polarity ? LL_USART_DE_POLARITY_HIGH + : LL_USART_DE_POLARITY_LOW); + + LL_USART_SetDEAssertionTime(priv->periph, priv->de_assert_time); + LL_USART_SetDEDeassertionTime(priv->periph, priv->de_clear_time); + } + LL_USART_Enable(priv->periph); return E_SUCCESS; } @@ -360,18 +576,22 @@ static void UUSART_deInit(Unit *unit) { struct priv *priv = unit->data; -// // de-init the pins & peripheral only if inited correctly -// if (unit->status == E_SUCCESS) { -// assert_param(priv->periph); -// -// LL_SPI_DeInit(priv->periph); -// -// if (priv->periph_num == 1) { -// __HAL_RCC_SPI1_CLK_DISABLE(); -// } else { -// __HAL_RCC_SPI2_CLK_DISABLE(); -// } -// } + // de-init the pins & peripheral only if inited correctly + if (unit->status == E_SUCCESS) { + assert_param(priv->periph); + + LL_USART_DeInit(priv->periph); + + if (priv->periph_num == 1) { + __HAL_RCC_USART1_CLK_DISABLE(); + } else if (priv->periph_num == 2) { + __HAL_RCC_USART2_CLK_DISABLE(); + } else if (priv->periph_num == 3) { + __HAL_RCC_USART3_CLK_DISABLE(); + } else if (priv->periph_num == 4) { + __HAL_RCC_USART4_CLK_DISABLE(); + } + } // Release all resources rsc_teardown(unit); diff --git a/utils/str_utils.c b/utils/str_utils.c index b0fb104..1f67552 100644 --- a/utils/str_utils.c +++ b/utils/str_utils.c @@ -40,3 +40,75 @@ uint8_t str_parse_012(const char *str, const char *a, const char *b, const char *suc = false; return 0; } + +/** Convert number to one of 2 options */ +const char *str_2(uint32_t n, + uint32_t na, const char *a, + uint32_t nb, const char *b) +{ + if (n == nb) return b; + return a; +} + +/** Convert number to one of 3 options */ +const char *str_3(uint32_t n, + uint32_t na, const char *a, + uint32_t nb, const char *b, + uint32_t nc, const char *c) +{ + if (n == nb) return b; + if (n == nc) return c; + return a; +} + +/** Convert number to one of 4 options */ +const char *str_4(uint32_t n, + uint32_t na, const char *a, + uint32_t nb, const char *b, + uint32_t nc, const char *c, + uint32_t nd, const char *d) +{ + if (n == nb) return b; + if (n == nc) return c; + if (n == nd) return d; + return a; +} + +uint32_t str_parse_2(const char *tpl, + const char *a, uint32_t na, + const char *b, uint32_t nb, + bool *suc) +{ + if (streq(tpl, a)) return na; + if (streq(tpl, b)) return nb; + *suc = false; + return na; +} + +uint32_t str_parse_3(const char *tpl, + const char *a, uint32_t na, + const char *b, uint32_t nb, + const char *c, uint32_t nc, + bool *suc) +{ + if (streq(tpl, a)) return na; + if (streq(tpl, b)) return nb; + if (streq(tpl, c)) return nc; + *suc = false; + return na; +} + +uint32_t str_parse_4(const char *tpl, + const char *a, uint32_t na, + const char *b, uint32_t nb, + const char *c, uint32_t nc, + const char *d, uint32_t nd, + bool *suc) +{ + if (streq(tpl, a)) return na; + if (streq(tpl, b)) return nb; + if (streq(tpl, c)) return nc; + if (streq(tpl, d)) return nd; + *suc = false; + return na; +} diff --git a/utils/str_utils.h b/utils/str_utils.h index 0f27d5d..a4170e0 100644 --- a/utils/str_utils.h +++ b/utils/str_utils.h @@ -107,23 +107,41 @@ uint8_t str_parse_01(const char *str, const char *a, const char *b, bool *suc); /** Compare string with three options */ uint8_t str_parse_012(const char *str, const char *a, const char *b, const char *c, bool *suc); -/** Convert bool to one of two options */ -#define str_01(cond, a, b) ((cond) ? (b) : (a)) - -/** Convert number to one of three options */ -#define str_3(cond, na, a, nb, b, nc, c) (\ - ((cond)==(na)) ? (a) : \ - ((cond)==(nb)) ? (b) : \ - (c) \ -) - -/** Convert number to one of three options */ -#define str_4(cond, na, a, nb, b, nc, c, nd, d) (\ - ((cond)==(na)) ? (a) : \ - ((cond)==(nb)) ? (b) : \ - ((cond)==(nc)) ? (c) : \ - (d) \ -) +/** Convert number to one of 4 options */ +const char *str_2(uint32_t n, + uint32_t na, const char *a, + uint32_t nb, const char *b); + +/** Convert number to one of 4 options */ +const char *str_3(uint32_t n, + uint32_t na, const char *a, + uint32_t nb, const char *b, + uint32_t nc, const char *c); + +/** Convert number to one of 4 options */ +const char *str_4(uint32_t n, + uint32_t na, const char *a, + uint32_t nb, const char *b, + uint32_t nc, const char *c, + uint32_t nd, const char *d); + +uint32_t str_parse_2(const char *tpl, + const char *a, uint32_t na, + const char *b, uint32_t nb, + bool *suc); + +uint32_t str_parse_3(const char *tpl, + const char *a, uint32_t na, + const char *b, uint32_t nb, + const char *c, uint32_t nc, + bool *suc); + +uint32_t str_parse_4(const char *tpl, + const char *a, uint32_t na, + const char *b, uint32_t nb, + const char *c, uint32_t nc, + const char *d, uint32_t nd, + bool *suc); /** Convert bool to Y or N */ #define str_yn(cond) ((cond) ? ("Y") : ("N"))