diff --git a/src/common/mode_config.h b/src/common/mode_config.h index c514117..93249e7 100644 --- a/src/common/mode_config.h +++ b/src/common/mode_config.h @@ -98,6 +98,7 @@ typedef struct { uint8_t dev_polarity; uint8_t dev_phase; uint8_t dev_bit_lsb_msb; + uint8_t dev_bidir; } spi_config_t; typedef struct { diff --git a/src/drv/stm32cube/bsp_spi.c b/src/drv/stm32cube/bsp_spi.c index f9a1ca1..24dbfca 100644 --- a/src/drv/stm32cube/bsp_spi.c +++ b/src/drv/stm32cube/bsp_spi.c @@ -186,7 +186,12 @@ bsp_status_t bsp_spi_init(bsp_dev_spi_t dev_num, mode_config_proto_t* mode_conf) /* SW NSS user shall call bsp_spi_select()/bsp_spi_unselect() */ hspi->Init.NSS = SPI_NSS_SOFT; hspi->Init.BaudRatePrescaler = ((7 - mode_conf->config.spi.dev_speed) * SPI_CR1_BR_0); - hspi->Init.Direction = SPI_DIRECTION_2LINES; + /* Half-duplex / bidirectional or normal 2-line */ + if(mode_conf->config.spi.dev_bidir == 0) { + hspi->Init.Direction = SPI_DIRECTION_2LINES; + } else { + hspi->Init.Direction = SPI_DIRECTION_1LINE; + } if(mode_conf->config.spi.dev_phase == 0) cpha = SPI_PHASE_1EDGE; @@ -221,6 +226,11 @@ bsp_status_t bsp_spi_init(bsp_dev_spi_t dev_num, mode_config_proto_t* mode_conf) /* Enable SPI peripheral */ __HAL_SPI_ENABLE(hspi); + /* Enable TX mode to avoid spurious clock output */ + if(mode_conf->config.spi.dev_bidir == 1) { + SPI_1LINE_TX(hspi); + } + return status; } @@ -351,9 +361,21 @@ bsp_status_t bsp_spi_write_read_u8(bsp_dev_spi_t dev_num, uint8_t* tx_data, uint hspi = &spi_handle[dev_num]; bsp_status_t status; - status = (bsp_status_t) HAL_SPI_TransmitReceive(hspi, tx_data, rx_data, nb_data, SPIx_TIMEOUT_MAX); - if(status != BSP_OK) { - spi_error(dev_num); + if(hspi->Init.Direction == SPI_DIRECTION_1LINE) { + status = (bsp_status_t) HAL_SPI_Transmit(hspi, tx_data, nb_data, SPIx_TIMEOUT_MAX); + if(status != BSP_OK) { + spi_error(dev_num); + return status; + } + status = (bsp_status_t) HAL_SPI_Receive(hspi, rx_data, nb_data, SPIx_TIMEOUT_MAX); + if(status != BSP_OK) { + spi_error(dev_num); + } + } else { + status = (bsp_status_t) HAL_SPI_TransmitReceive(hspi, tx_data, rx_data, nb_data, SPIx_TIMEOUT_MAX); + if(status != BSP_OK) { + spi_error(dev_num); + } } return status; } diff --git a/src/hydrabus/commands.c b/src/hydrabus/commands.c index 8cc29db..575e036 100644 --- a/src/hydrabus/commands.c +++ b/src/hydrabus/commands.c @@ -168,6 +168,7 @@ const t_token_dict tl_dict[] = { { T_POKE, "poke" }, { T_SWIO, "swio" }, { T_CONTINUITY, "continuity" }, + { T_BIDIR, "bidir" }, /* Developer warning add new command(s) here */ /* BP-compatible commands */ @@ -1065,7 +1066,10 @@ t_token tokens_i2c[] = { { T_MSB_FIRST, \ .help = "Send/receive MSB first" }, \ { T_LSB_FIRST, \ - .help = "Send/receive LSB first" }, + .help = "Send/receive LSB first" }, \ + { T_BIDIR, \ + .arg_type = T_ARG_UINT, \ + .help = "Bidir mode (0/1)" }, \ t_token tokens_mode_spi[] = { { diff --git a/src/hydrabus/commands.h b/src/hydrabus/commands.h index 46bdefd..996b977 100644 --- a/src/hydrabus/commands.h +++ b/src/hydrabus/commands.h @@ -160,6 +160,7 @@ enum { T_POKE, T_SWIO, T_CONTINUITY, + T_BIDIR, /* Developer warning add new command(s) here */ /* BP-compatible commands */ diff --git a/src/hydrabus/hydrabus_bbio_spi.c b/src/hydrabus/hydrabus_bbio_spi.c index fc2fc99..32321a3 100644 --- a/src/hydrabus/hydrabus_bbio_spi.c +++ b/src/hydrabus/hydrabus_bbio_spi.c @@ -302,6 +302,9 @@ void bbio_mode_spi(t_hydra_console *con) } else { bsp_spi_select(proto->dev_num); } + //Set bidir mode + proto->config.spi.dev_bidir = (bbio_subcommand & 0b100)?1:0; + //Set AUX[0] (PC4) value bbio_aux_write((bbio_subcommand & 0b10)>>1); diff --git a/src/hydrabus/hydrabus_mode_spi.c b/src/hydrabus/hydrabus_mode_spi.c index f546ad1..3ee1c52 100644 --- a/src/hydrabus/hydrabus_mode_spi.c +++ b/src/hydrabus/hydrabus_mode_spi.c @@ -26,10 +26,16 @@ static int exec(t_hydra_console *con, t_tokenline_parsed *p, int token_pos); static int show(t_hydra_console *con, t_tokenline_parsed *p); static const char* str_pins_spi1= { - "CS: PA15\r\nSCK: PB3\r\nMISO: PB4\r\nMOSI: PB5\r\n" + "CS: PA15\r\nSCK: PB3\r\n" }; static const char* str_pins_spi2= { - "CS: PC1 (SW)\r\nSCK: PB10\r\nMISO: PC2\r\nMOSI: PC3\r\n" + "CS: PC1 (SW)\r\nSCK: PB10\r\n" +}; +static const char* str_pins_spi1_io= { + "MISO: PB4\r\nMOSI: PB5\r\n" +}; +static const char* str_pins_spi2_io= { + "MISO: PC2\r\nMOSI: PC3\r\n" }; static const char* str_prompt_spi1= { "spi1" PROMPT }; static const char* str_prompt_spi2= { "spi2" PROMPT }; @@ -75,6 +81,7 @@ static void init_proto_default(t_hydra_console *con) proto->config.spi.dev_polarity = 0; proto->config.spi.dev_phase = 0; proto->config.spi.dev_bit_lsb_msb = DEV_FIRSTBIT_MSB; + proto->config.spi.dev_bidir = 0; } static void show_params(t_hydra_console *con) @@ -82,13 +89,14 @@ static void show_params(t_hydra_console *con) uint8_t i, cnt; mode_config_proto_t* proto = &con->mode->proto; - cprintf(con, "Device: SPI%d\r\nGPIO resistor: %s\r\nMode: %s\r\n" + cprintf(con, "Device: SPI%d\r\nGPIO resistor: %s\r\nMode: %s\r\nBidir: %s\r\n" "Frequency: ", proto->dev_num + 1, proto->config.spi.dev_gpio_pull == MODE_CONFIG_DEV_GPIO_PULLUP ? "pull-up" : proto->config.spi.dev_gpio_pull == MODE_CONFIG_DEV_GPIO_PULLDOWN ? "pull-down" : "floating", - proto->config.spi.dev_mode == DEV_MASTER ? "master" : "slave"); + proto->config.spi.dev_mode == DEV_MASTER ? "master" : "slave", + proto->config.spi.dev_bidir == 0 ? "off" : "on"); print_freq(con, spi_speeds[proto->dev_num][proto->config.spi.dev_speed]); cprintf(con, " ("); @@ -242,6 +250,17 @@ static int exec(t_hydra_console *con, t_tokenline_parsed *p, int token_pos) return t; } break; + case T_BIDIR: + /* Integer parameter. */ + t += 2; + memcpy(&arg_int, p->buf + p->tokens[t], sizeof(int)); + if (arg_int > 1 ) { + cprintf(con, "Bidir must be 0 or 1.\r\n"); + return t; + } + proto->config.spi.dev_bidir = arg_int; + bsp_spi_init(proto->dev_num, proto); + break; default: return t - token_pos; } @@ -357,10 +376,21 @@ static int show(t_hydra_console *con, t_tokenline_parsed *p) tokens_used = 0; if (p->tokens[1] == T_PINS) { tokens_used++; - if (proto->dev_num == 0) + if (proto->dev_num == 0) { cprint(con, str_pins_spi1, strlen(str_pins_spi1)); - else + if (proto->config.spi.dev_bidir == 0) { + cprint(con, str_pins_spi1_io, strlen(str_pins_spi1_io)); + } else { + cprintf(con, "IO: %s\r\n", proto->config.spi.dev_mode == DEV_MASTER ? "PB5" : "PB4"); + } + } else { cprint(con, str_pins_spi2, strlen(str_pins_spi2)); + if (proto->config.spi.dev_bidir == 0) { + cprint(con, str_pins_spi2_io, strlen(str_pins_spi2_io)); + } else { + cprintf(con, "IO: %s\r\n", proto->config.spi.dev_mode == DEV_MASTER ? "PC3" : "PC2"); + } + } } else { show_params(con); } diff --git a/src/hydrabus/hydrabus_serprog.c b/src/hydrabus/hydrabus_serprog.c index b4e7f91..02919be 100644 --- a/src/hydrabus/hydrabus_serprog.c +++ b/src/hydrabus/hydrabus_serprog.c @@ -37,6 +37,7 @@ void bbio_serprog_init_proto_default(t_hydra_console *con) proto->config.spi.dev_polarity = 0; proto->config.spi.dev_phase = 0; proto->config.spi.dev_bit_lsb_msb = DEV_FIRSTBIT_MSB; + proto->config.spi.dev_bidir = 0; } void bbio_mode_serprog(t_hydra_console *con)