added uart init (untested) and more config option

sipo
Ondřej Hruška 7 years ago
parent e88bf84ea1
commit 29264540f7
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 10
      units/spi/unit_spi.c
  2. 508
      units/usart/unit_uart.c
  3. 72
      utils/str_utils.c
  4. 52
      utils/str_utils.h

@ -97,8 +97,8 @@ static error_t USPI_loadIni(Unit *unit, const char *key, const char *value)
else if (streq(key, "tx-only")) { else if (streq(key, "tx-only")) {
priv->tx_only = str_parse_yn(value, &suc); priv->tx_only = str_parse_yn(value, &suc);
} }
else if (streq(key, "lsb-first")) { else if (streq(key, "first-bit")) {
priv->lsb_first = str_parse_yn(value, &suc); priv->lsb_first = (bool)str_parse_2(value, "MSB", 0, "LSB", 1, &suc);
} }
else if (streq(key, "port")) { else if (streq(key, "port")) {
suc = parse_port(value, &priv->ssn_port_name); 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_comment(iw, "Transmit only, disable MISO");
iw_entry(iw, "tx-only", str_yn(priv->tx_only)); iw_entry(iw, "tx-only", str_yn(priv->tx_only));
iw_comment(iw, "Use LSB-first bit order"); iw_comment(iw, "Bit order (LSB or MSB first)");
iw_entry(iw, "lsb-first", str_yn(priv->lsb_first)); iw_entry(iw, "first-bit", str_2((uint32_t)priv->lsb_first,
0, "MSB",
1, "LSB"));
iw_cmt_newline(iw); iw_cmt_newline(iw);
iw_comment(iw, "SS port name"); iw_comment(iw, "SS port name");

@ -15,20 +15,26 @@ struct priv {
uint8_t periph_num; //!< 1-6 uint8_t periph_num; //!< 1-6
uint8_t remap; //!< UART remap option 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 parity; //!< 0-none, 1-odd, 2-even
uint8_t stopbits; //!< 1-one, 2-2, 3-1.5 uint8_t stopbits; //!< 0-half, 1-one, 2-one-and-half, 3-two (halves - 1)
bool enable_rx; //!< Configure and enable the Rx line uint8_t direction; //!< 1-RX, 2-TX, 3-RXTX
bool enable_tx; //!< Configure and enable the Tx line
uint8_t hw_flow_control; //!< HW flow control 0-none, 1-RTX, 2-CTS, 3-both uint8_t hw_flow_control; //!< HW flow control 0-none, 1-RTC, 2-CTS, 3-full
bool clock_output; //!< Output serial clock bool clock_output; //!< Output serial clock
bool cpol; //!< clock CPOL setting bool cpol; //!< clock CPOL setting
bool cpha; //!< clock CPHA 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 bool data_inv; //!< Invert data bytes
uint32_t rx_full_thr; //!< Receive buffer full threshold (will be sent to PC) bool rx_inv; //!< Invert the RX pin levels
uint16_t rx_timeout; //!< Receive timeout (time of inactivity before flushing to PC) 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; USART_TypeDef *periph;
}; };
@ -46,18 +52,25 @@ static error_t UUSART_preInit(Unit *unit)
priv->baudrate = 115200; priv->baudrate = 115200;
priv->parity = 0; //!< 0-none, 1-odd, 2-even priv->parity = 0; //!< 0-none, 1-odd, 2-even
priv->stopbits = 1; //!< 1-one, 2-2, 3-1.5 priv->stopbits = 1; //!< 0-half, 1-one, 2-1.5, 3-two
priv->enable_rx = true; priv->direction = 3; // RXTX
priv->enable_tx = true;
priv->hw_flow_control = false; priv->hw_flow_control = false;
priv->clock_output = false; priv->clock_output = false;
priv->cpol = 0; priv->cpol = 0;
priv->cpha = 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->de_output = false;
priv->rx_full_thr = 90; priv->de_polarity = 1; // active high
priv->rx_timeout = 3; // ms // 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; return E_SUCCESS;
} }
@ -78,17 +91,23 @@ static void UUSART_loadBinary(Unit *unit, PayloadParser *pp)
priv->baudrate = pp_u32(pp); priv->baudrate = pp_u32(pp);
priv->parity = pp_u8(pp); priv->parity = pp_u8(pp);
priv->stopbits = pp_u8(pp); priv->stopbits = pp_u8(pp);
priv->enable_rx = pp_bool(pp); priv->direction = pp_u8(pp);
priv->enable_tx = pp_bool(pp);
priv->hw_flow_control = pp_u8(pp); priv->hw_flow_control = pp_u8(pp);
priv->clock_output = pp_bool(pp); priv->clock_output = pp_bool(pp);
priv->cpol = pp_bool(pp); priv->cpol = pp_bool(pp);
priv->cpha = pp_bool(pp); priv->cpha = pp_bool(pp);
priv->lsb_first = pp_bool(pp);
priv->width = pp_u8(pp);
priv->rx_buf_size = pp_u32(pp); priv->data_inv = pp_bool(pp);
priv->rx_full_thr = pp_u32(pp); priv->rx_inv = pp_bool(pp);
priv->rx_timeout = pp_u16(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 */ /** 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_u32(pb, priv->baudrate);
pb_u8(pb, priv->parity); pb_u8(pb, priv->parity);
pb_u8(pb, priv->stopbits); pb_u8(pb, priv->stopbits);
pb_bool(pb, priv->enable_rx); pb_u8(pb, priv->direction);
pb_bool(pb, priv->enable_tx);
pb_u8(pb, priv->hw_flow_control); pb_u8(pb, priv->hw_flow_control);
pb_bool(pb, priv->clock_output); pb_bool(pb, priv->clock_output);
pb_bool(pb, priv->cpol); pb_bool(pb, priv->cpol);
pb_bool(pb, priv->cpha); 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_bool(pb, priv->de_output);
pb_u32(pb, priv->rx_full_thr); pb_bool(pb, priv->de_polarity);
pb_u16(pb, priv->rx_timeout); 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); priv->baudrate = (uint32_t ) avr_atoi(value);
} }
else if (streq(key, "parity")) { 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")) { 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")) { else if (streq(key, "direction")) {
priv->enable_rx = str_parse_yn(value, &suc); priv->direction = (uint8_t) str_parse_3(value,
} "RX", 1,
else if (streq(key, "enable-tx")) { "TX", 2,
priv->enable_tx = str_parse_yn(value, &suc); "RXTX", 3, &suc);
} }
else if (streq(key, "hw-flow-control")) { 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")) { else if (streq(key, "clock-output")) {
priv->clock_output = (bool) avr_atoi(value); priv->clock_output = str_parse_yn(value, &suc);
} }
else if (streq(key, "cpol")) { else if (streq(key, "cpol")) {
priv->cpol = (bool) avr_atoi(value); 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")) { else if (streq(key, "cpha")) {
priv->cpha = (bool) avr_atoi(value); priv->cpha = (bool) avr_atoi(value);
} }
else if (streq(key, "rx-buffer")) { else if (streq(key, "de-output")) {
priv->rx_buf_size = (uint32_t ) avr_atoi(value); priv->de_output = str_parse_yn(value, &suc);
} }
else if (streq(key, "rx-full-theshold")) { else if (streq(key, "de-polarity")) {
priv->rx_full_thr = (uint32_t ) avr_atoi(value); priv->de_polarity = (bool) avr_atoi(value);
} }
else if (streq(key, "rx-timeout")) { else if (streq(key, "de-assert-time")) {
priv->rx_timeout = (uint16_t ) avr_atoi(value); 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 { else {
return E_BAD_KEY; return E_BAD_KEY;
@ -180,14 +225,16 @@ static void UUSART_writeIni(Unit *unit, IniWriter *iw)
{ {
struct priv *priv = unit->data; 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_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 #if GEX_PLAT_F072_DISCOVERY
// TODO // TODO
// iw_comment(iw, " SPI1: (0) A5,A6,A7 (1) B3,B4,B5 (2) E13,E14,E15"); iw_comment(iw, " USART1: (0) A9,A10,A8,A11,A12 (1) B6,B7,A8,A11,A12");
// iw_comment(iw, " SPI2: (0) B13,B14,B15 (1) D1,D3,D4"); 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 #elif GEX_PLAT_F103_BLUEPILL
#error "NO IMPL" #error "NO IMPL"
#elif GEX_PLAT_F303_DISCOVERY #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_entry(iw, "remap", "%d", (int)priv->remap);
iw_cmt_newline(iw); 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_entry(iw, "baud-rate", "%d", (int)priv->baudrate);
iw_comment(iw, "Parity (0-none, 1-odd, 2-even)"); iw_comment(iw, "Parity type (NONE, ODD, EVEN)");
iw_entry(iw, "parity", "%d", (int)priv->parity); iw_entry(iw, "parity", "%s", str_3(priv->parity,
0, "NONE",
iw_comment(iw, "Stop-bits (1, 1.5, 2)"); 1, "ODD",
iw_entry(iw, "stop-bits", "%s", (priv->stopbits==3)?"1.5":(priv->stopbits==2?"2":"1")); 2, "EVEN"));
iw_comment(iw, "Enable the RX / TX lines"); iw_comment(iw, "Number of stop bits (0.5, 1, 1.5, 2)");
iw_entry(iw, "exable-rx", str_yn(priv->enable_rx)); iw_entry(iw, "stop-bits", "%s", str_4(priv->stopbits,
iw_entry(iw, "exable-tx", str_yn(priv->enable_tx)); 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_cmt_newline(iw);
iw_entry(iw, "hw-flow-control", "%s", str_4(priv->hw_flow_control, 0, "NONE", 1, "RTS", 2, "CTS", 3, "ALL")); iw_comment(iw, "Generate serial clock (Y,N)");
iw_comment(iw, "Clock output (Y,N) - N for async");
iw_entry(iw, "clock-output", str_yn(priv->clock_output)); 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_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_entry(iw, "cpha", "%d", (int)priv->cpha);
iw_comment(iw, "Receive buffer capacity, full threshold and flush timeout"); iw_cmt_newline(iw);
iw_entry(iw, "rx-buffer", "%d", (int)priv->rx_buf_size); iw_comment(iw, "Generate RS485 Driver Enable signal (Y,N) - uses RTS pin");
iw_entry(iw, "rx-full-theshold", "%d", (int)priv->rx_full_thr); iw_entry(iw, "de-output", str_yn(priv->de_output));
iw_entry(iw, "rx-timeout", "%d", (int)priv->rx_timeout); 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 */ /** Finalize unit set-up */
static error_t UUSART_init(Unit *unit) static error_t UUSART_init(Unit *unit)
@ -239,8 +318,7 @@ static error_t UUSART_init(Unit *unit)
struct priv *priv = unit->data; struct priv *priv = unit->data;
if (!(priv->periph_num >= 1 && priv->periph_num <= 4)) { if (!(priv->periph_num >= 1 && priv->periph_num <= 4)) {
dbg("!! Bad UART periph"); dbg("!! Bad USART periph");
// TODO count based on platform chip
return E_BAD_CONFIG; return E_BAD_CONFIG;
} }
@ -249,49 +327,124 @@ static error_t UUSART_init(Unit *unit)
TRY(rsc_claim(unit, R_USART1)); TRY(rsc_claim(unit, R_USART1));
priv->periph = USART1; priv->periph = USART1;
} }
#if defined(USART2)
else if (priv->periph_num == 2) { else if (priv->periph_num == 2) {
TRY(rsc_claim(unit, R_USART2)); TRY(rsc_claim(unit, R_USART2));
priv->periph = USART2; priv->periph = USART2;
} }
#endif
#if defined(USART3)
else if (priv->periph_num == 3) { else if (priv->periph_num == 3) {
TRY(rsc_claim(unit, R_USART3)); TRY(rsc_claim(unit, R_USART3));
priv->periph = USART3; priv->periph = USART3;
} }
#endif
#if defined(USART4)
else if (priv->periph_num == 4) { else if (priv->periph_num == 4) {
TRY(rsc_claim(unit, R_USART4)); TRY(rsc_claim(unit, R_USART4));
priv->periph = USART4; priv->periph = USART4;
} }
#endif
else return E_BAD_CONFIG;
// This is written for F072, other platforms will need adjustments // This is written for F072, other platforms will need adjustments
// Configure UART pins (AF) // Configure UART pins (AF)
char uart_portname; const struct paf *mappings = NULL;
uint8_t pin_rx;
uint8_t pin_tx;
uint8_t pin_clk;
uint8_t pin_rts;
uint8_t pin_cts;
uint32_t af_uart;
// TODO // TODO
#if GEX_PLAT_F072_DISCOVERY #if GEX_PLAT_F072_DISCOVERY
// SPI1 - many options const struct paf mapping_1_0[5] = {
// sck, miso, mosi, af {'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) { if (priv->periph_num == 1) {
// SPI1 // USART1
if (priv->remap == 0) { if (priv->remap == 0) mappings = &mapping_1_0[0];
uart_portname = 'A'; else if (priv->remap == 1) mappings = &mapping_1_1[0];
// af_spi = LL_GPIO_AF_0; else return E_BAD_CONFIG;
// pin_sck = 5;
// pin_miso = 6;
// pin_mosi = 7;
} }
else { else if (priv->periph_num == 2) {
return E_BAD_CONFIG; // 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 // TODO other periphs
#elif GEX_PLAT_F103_BLUEPILL #elif GEX_PLAT_F103_BLUEPILL
@ -303,54 +456,117 @@ static error_t UUSART_init(Unit *unit)
#else #else
#error "BAD PLATFORM!" #error "BAD PLATFORM!"
#endif #endif
//
// // first, we have to claim the pins // CK
// TRY(rsc_claim_pin(unit, uart_portname, pin_mosi)); if (priv->clock_output) {
// TRY(rsc_claim_pin(unit, uart_portname, pin_miso)); TRY(rsc_claim_pin(unit, mappings[0].port, mappings[0].pin));
// TRY(rsc_claim_pin(unit, uart_portname, pin_sck)); configure_gpio_alternate( mappings[0].port, mappings[0].pin, mappings[0].af);
// }
// configure_gpio_alternate(uart_portname, pin_mosi, af_spi); // TX
// configure_gpio_alternate(uart_portname, pin_miso, af_spi); if (priv->direction & 2) {
// configure_gpio_alternate(uart_portname, pin_sck, af_spi); TRY(rsc_claim_pin(unit, mappings[1].port, mappings[1].pin));
// configure_gpio_alternate( mappings[1].port, mappings[1].pin, mappings[1].af);
// if (priv->periph_num == 1) { }
// __HAL_RCC_SPI1_CLK_ENABLE(); // RX
// } else { if (priv->direction & 1) {
// __HAL_RCC_SPI2_CLK_ENABLE(); TRY(rsc_claim_pin(unit, mappings[2].port, mappings[2].pin));
// } configure_gpio_alternate( mappings[2].port, mappings[2].pin, mappings[2].af);
// }
// // configure SSN GPIOs // CTS
// { if (priv->hw_flow_control==2 || priv->hw_flow_control==3) {
// // Claim all needed pins TRY(rsc_claim_pin(unit, mappings[4].port, mappings[4].pin));
// TRY(rsc_claim_gpios(unit, priv->ssn_port_name, priv->ssn_pins)); configure_gpio_alternate( mappings[4].port, mappings[4].pin, mappings[4].af);
// TRY(configure_sparse_pins(priv->ssn_port_name, priv->ssn_pins, &priv->ssn_port, }
// LL_GPIO_MODE_OUTPUT, LL_GPIO_OUTPUT_PUSHPULL)); // RTS
// // Set the initial state - all high if (priv->de_output || priv->hw_flow_control==1 || priv->hw_flow_control==3) {
// priv->ssn_port->BSRR = priv->ssn_pins; TRY(rsc_claim_pin(unit, mappings[5].port, mappings[5].pin));
// } configure_gpio_alternate( mappings[5].port, mappings[5].pin, mappings[5].af);
// }
// // Configure SPI - must be configured under reset
// LL_SPI_Disable(priv->periph); if (priv->periph_num == 1) {
// { __HAL_RCC_USART1_CLK_ENABLE();
// uint32_t presc = priv->prescaller; } else if (priv->periph_num == 2) {
// uint32_t lz = __CLZ(presc); __HAL_RCC_USART2_CLK_ENABLE();
// if (lz < 23) lz = 23; } else if (priv->periph_num == 3) {
// if (lz > 30) lz = 30; __HAL_RCC_USART3_CLK_ENABLE();
// presc = (32 - lz - 2); } else if (priv->periph_num == 4) {
// LL_SPI_SetBaudRatePrescaler(priv->periph, (presc<<SPI_CR1_BR_Pos)&SPI_CR1_BR_Msk); __HAL_RCC_USART4_CLK_ENABLE();
// }
// LL_SPI_SetClockPolarity(priv->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_USART_Disable(priv->periph);
// 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_USART_DeInit(priv->periph);
// LL_USART_SetBaudRate(priv->periph,
// LL_SPI_SetNSSMode(priv->periph, LL_SPI_NSS_SOFT); PLAT_AHB_MHZ/2,//FIXME this isn't great ...
// LL_SPI_SetDataWidth(priv->periph, LL_SPI_DATAWIDTH_8BIT); LL_USART_OVERSAMPLING_16,
// LL_SPI_SetRxFIFOThreshold(priv->periph, LL_SPI_RX_FIFO_TH_QUARTER); // trigger RXNE on 1 byte priv->baudrate);
//
// LL_SPI_SetMode(priv->periph, LL_SPI_MODE_MASTER); LL_USART_SetParity(priv->periph,
// } priv->parity == 0 ? LL_USART_PARITY_NONE :
// LL_SPI_Enable(priv->periph); 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; return E_SUCCESS;
} }
@ -360,18 +576,22 @@ static void UUSART_deInit(Unit *unit)
{ {
struct priv *priv = unit->data; struct priv *priv = unit->data;
// // de-init the pins & peripheral only if inited correctly // de-init the pins & peripheral only if inited correctly
// if (unit->status == E_SUCCESS) { if (unit->status == E_SUCCESS) {
// assert_param(priv->periph); assert_param(priv->periph);
//
// LL_SPI_DeInit(priv->periph); LL_USART_DeInit(priv->periph);
//
// if (priv->periph_num == 1) { if (priv->periph_num == 1) {
// __HAL_RCC_SPI1_CLK_DISABLE(); __HAL_RCC_USART1_CLK_DISABLE();
// } else { } else if (priv->periph_num == 2) {
// __HAL_RCC_SPI2_CLK_DISABLE(); __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 // Release all resources
rsc_teardown(unit); rsc_teardown(unit);

@ -40,3 +40,75 @@ uint8_t str_parse_012(const char *str, const char *a, const char *b, const char
*suc = false; *suc = false;
return 0; 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;
}

@ -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 */ /** Compare string with three options */
uint8_t str_parse_012(const char *str, const char *a, const char *b, const char *c, bool *suc); 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 */ /** Convert number to one of 4 options */
#define str_01(cond, a, b) ((cond) ? (b) : (a)) const char *str_2(uint32_t n,
uint32_t na, const char *a,
/** Convert number to one of three options */ uint32_t nb, const char *b);
#define str_3(cond, na, a, nb, b, nc, c) (\
((cond)==(na)) ? (a) : \ /** Convert number to one of 4 options */
((cond)==(nb)) ? (b) : \ const char *str_3(uint32_t n,
(c) \ uint32_t na, const char *a,
) uint32_t nb, const char *b,
uint32_t nc, const char *c);
/** Convert number to one of three options */
#define str_4(cond, na, a, nb, b, nc, c, nd, d) (\ /** Convert number to one of 4 options */
((cond)==(na)) ? (a) : \ const char *str_4(uint32_t n,
((cond)==(nb)) ? (b) : \ uint32_t na, const char *a,
((cond)==(nc)) ? (c) : \ uint32_t nb, const char *b,
(d) \ 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 */ /** Convert bool to Y or N */
#define str_yn(cond) ((cond) ? ("Y") : ("N")) #define str_yn(cond) ((cond) ? ("Y") : ("N"))

Loading…
Cancel
Save