refactor: adjust SPI transaction queue size and improve read_stream validation

This commit is contained in:
2025-08-07 11:06:03 +08:00
parent ffcaba10fd
commit 249c125447
2 changed files with 69 additions and 32 deletions

View File

@ -118,7 +118,7 @@ struct transmit_state_t {
* @brief private namespace; Don't use anything in this namespace outside of this file * @brief private namespace; Don't use anything in this namespace outside of this file
*/ */
namespace details { namespace details {
extern uint32_t __tcxo_delay__; inline uint32_t __tcxo_delay__;
} }
constexpr auto delay_ms = app::utils::delay_ms; constexpr auto delay_ms = app::utils::delay_ms;
@ -141,9 +141,9 @@ reset() {
} }
gpio::set_mode(RST_PIN, gpio::Mode::OUTPUT); gpio::set_mode(RST_PIN, gpio::Mode::OUTPUT);
gpio::digital_write(RST_PIN, false); gpio::digital_write(RST_PIN, false);
delay_ms(100); delay_ms(250);
gpio::digital_write(RST_PIN, true); gpio::digital_write(RST_PIN, true);
delay_ms(100); delay_ms(1'000);
const auto instant = Instant<>{}; const auto instant = Instant<>{};
constexpr auto INTERVAL = std::chrono::duration<uint16_t, std::milli>{spi::DEFAULT_TIMEOUT_MS}; constexpr auto INTERVAL = std::chrono::duration<uint16_t, std::milli>{spi::DEFAULT_TIMEOUT_MS};
decltype(standby()) res = ue_t{error_t{error::FAILED}}; decltype(standby()) res = ue_t{error_t{error::FAILED}};
@ -833,7 +833,7 @@ set_tx_params(const uint8_t pwr, const uint8_t ramp_time = RADIOLIB_SX126X_PA_RA
\param sync_word LoRa sync word to be set. \param sync_word LoRa sync word to be set.
\param control_bits Undocumented control bits, required for compatibility purposes. \param control_bits Undocumented control bits, required for compatibility purposes.
*/ */
inline Result<Unit, error_t> set_sync_word(const uint8_t sync_word = RADIOLIB_SX126X_SYNC_WORD_PRIVATE, const uint8_t control_bits = 0x44) { inline Result<Unit, error_t> set_lora_sync_word(const uint8_t sync_word = RADIOLIB_SX126X_SYNC_WORD_PRIVATE, const uint8_t control_bits = 0x44) {
const auto pkt_type = get_packet_type(); const auto pkt_type = get_packet_type();
APP_RADIO_RETURN_ERR(pkt_type); APP_RADIO_RETURN_ERR(pkt_type);
if (*pkt_type != RADIOLIB_SX126X_PACKET_TYPE_LORA) { if (*pkt_type != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
@ -1062,16 +1062,16 @@ kick_inf_rx(const modulation_params_t &mod_params, const packet_params_t &packet
}; };
res = set_modulation_params(mod_params.sf, mod_params.bw, mod_params.cr, mod_params.ldr_optimize); res = set_modulation_params(mod_params.sf, mod_params.bw, mod_params.cr, mod_params.ldr_optimize);
APP_RADIO_RETURN_ERR_CTX(res, "failed to set modulation params"); APP_RADIO_RETURN_ERR_CTX(res, "modulation params");
res = set_packet_params(packet_params.preamble_len, packet_params.payload_len, packet_params.crc_type, packet_params.hdr_type); res = set_packet_params(packet_params.preamble_len, packet_params.payload_len, packet_params.crc_type, packet_params.hdr_type);
APP_RADIO_RETURN_ERR_CTX(res, "failed to set packet params"); APP_RADIO_RETURN_ERR_CTX(res, "packet params");
res = set_dio_irq_params(irq_params); res = set_dio_irq_params(irq_params);
APP_RADIO_RETURN_ERR_CTX(res, "failed to set dio irq params"); APP_RADIO_RETURN_ERR_CTX(res, "dio irq params");
res = clear_irq_status(); res = clear_irq_status();
APP_RADIO_RETURN_ERR_CTX(res, "failed to clear irq status"); APP_RADIO_RETURN_ERR_CTX(res, "clear irq status");
res = rx(RADIOLIB_SX126X_RX_TIMEOUT_INF); res = rx(RADIOLIB_SX126X_RX_TIMEOUT_INF);
APP_RADIO_RETURN_ERR_CTX(res, "failed to set rx"); APP_RADIO_RETURN_ERR_CTX(res, "set rx");
return {}; return {};
} }
@ -1172,6 +1172,31 @@ async_transmit(const std::span<const uint8_t> data,
} }
/**
* @brief initialize TX & RX enable pins and put them in high level
* @note I'm not sure if this is necessary anymore, just in case
*/
static constexpr auto init_tx_rx_en = [] {
constexpr auto TX_EN_PIN = app::driver::llcc68::TX_EN_PIN;
constexpr auto RX_EN_PIN = app::driver::llcc68::RX_EN_PIN;
// both pins must be defined
if (TX_EN_PIN == GPIO_NUM_NC or RX_EN_PIN == GPIO_NUM_NC) {
return;
}
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << TX_EN_PIN) | (1ULL << RX_EN_PIN),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE,
};
ESP_ERROR_CHECK(gpio_config(&io_conf));
ESP_ERROR_CHECK(gpio_set_level(TX_EN_PIN, true));
ESP_ERROR_CHECK(gpio_set_level(RX_EN_PIN, true));
};
static constexpr auto init_pins = [](void (*isr)(void *), void *arg) { static constexpr auto init_pins = [](void (*isr)(void *), void *arg) {
if (RST_PIN != GPIO_NUM_NC) { if (RST_PIN != GPIO_NUM_NC) {
gpio::set_mode(RST_PIN, gpio::Mode::OUTPUT); gpio::set_mode(RST_PIN, gpio::Mode::OUTPUT);
@ -1196,6 +1221,9 @@ static constexpr auto init_pins = [](void (*isr)(void *), void *arg) {
} }
gpio_isr_handler_add(pin, isr, arg); gpio_isr_handler_add(pin, isr, arg);
} }
// initialize TX & RX enable pins
init_tx_rx_en();
}; };
static constexpr auto begin = [](const lora_parameters_t &params) -> Result<Unit, error_t> { static constexpr auto begin = [](const lora_parameters_t &params) -> Result<Unit, error_t> {
@ -1215,66 +1243,69 @@ static constexpr auto begin = [](const lora_parameters_t &params) -> Result<Unit
/* explicit not reset the chip by pin, due to unexpected side effect */ /* explicit not reset the chip by pin, due to unexpected side effect */
res = standby(); res = standby();
APP_RADIO_RETURN_ERR_CTX(res, "failed to standby"); APP_RADIO_RETURN_ERR_CTX(res, "standby");
const auto [ok, chip] = find_chip(); const auto [ok, chip] = find_chip();
if (not ok) { if (not ok) {
return ue_t{error_t{error::RADIO_CHIP_NOT_FOUND}}; return ue_t{error_t{error::RADIO_CHIP_NOT_FOUND}};
} }
if (not USE_XTAL) { // FIXME
// according to https://github.com/nopnop2002/esp-idf-sx126x
// we should set TCXO voltage
if constexpr (not USE_XTAL) {
const auto voltage_ = set_TCXO(DEFAULT_TCXO_VOLTAGE); const auto voltage_ = set_TCXO(DEFAULT_TCXO_VOLTAGE);
details::__tcxo_delay__ = *voltage_; details::__tcxo_delay__ = *voltage_;
APP_RADIO_RETURN_ERR_CTX(res, "failed to set TCXO"); APP_RADIO_RETURN_ERR_CTX(res, "set TCXO");
} }
const auto &mod_params = params.mod_params; const auto &mod_params = params.mod_params;
const auto &packet_params = params.packet_params; const auto &packet_params = params.packet_params;
// SetPacketType // SetPacketType
res = config_packet_type(mod_params.sf); res = config_packet_type(mod_params.sf);
APP_RADIO_RETURN_ERR_CTX(res, "failed to config packet type"); APP_RADIO_RETURN_ERR_CTX(res, "config packet type");
res = set_modulation_params(mod_params.sf, res = set_modulation_params(mod_params.sf,
mod_params.bw, mod_params.bw,
mod_params.cr, mod_params.cr,
mod_params.ldr_optimize); mod_params.ldr_optimize);
APP_RADIO_RETURN_ERR_CTX(res, "failed to set modulation params"); APP_RADIO_RETURN_ERR_CTX(res, "set modulation params");
res = set_sync_word(params.sync_word); res = set_lora_sync_word(params.sync_word);
APP_RADIO_RETURN_ERR_CTX(res, "failed to set sync word"); APP_RADIO_RETURN_ERR_CTX(res, "sync word");
if constexpr (USE_REGULATOR_LDO) { if constexpr (USE_REGULATOR_LDO) {
res = set_regulator_ldo(); res = set_regulator_ldo();
APP_RADIO_RETURN_ERR_CTX(res, "failed to set regulator LDO"); APP_RADIO_RETURN_ERR_CTX(res, "regulator LDO");
} else { } else {
res = set_regulator_dc_dc(); res = set_regulator_dc_dc();
APP_RADIO_RETURN_ERR_CTX(res, "failed to set regulator DC-DC"); APP_RADIO_RETURN_ERR_CTX(res, "regulator DC-DC");
} }
res = set_current_limit<60.0f>(); res = set_current_limit<60.0f>();
APP_RADIO_RETURN_ERR_CTX(res, "failed to set current limit"); APP_RADIO_RETURN_ERR_CTX(res, "current limit");
res = set_dio2_as_rf_switch(false); res = set_dio2_as_rf_switch(false);
APP_RADIO_RETURN_ERR_CTX(res, "failed to set dio2 as rf switch"); APP_RADIO_RETURN_ERR_CTX(res, "set dio2 as rf switch");
res = set_frequency(params.frequency); res = set_frequency(params.frequency);
APP_RADIO_RETURN_ERR_CTX(res, "failed to set frequency"); APP_RADIO_RETURN_ERR_CTX(res, "set frequency");
// SetPacketParams // SetPacketParams
res = set_packet_params(packet_params.preamble_len, res = set_packet_params(packet_params.preamble_len,
packet_params.payload_len, packet_params.payload_len,
packet_params.crc_type, packet_params.crc_type,
packet_params.hdr_type); packet_params.hdr_type);
APP_RADIO_RETURN_ERR_CTX(res, "failed to set packet params"); APP_RADIO_RETURN_ERR_CTX(res, "set packet params");
res = set_output_power(chip_type_to_max_tx_power(chip)); res = set_output_power(chip_type_to_max_tx_power(chip));
APP_RADIO_RETURN_ERR_CTX(res, "failed to set output power"); APP_RADIO_RETURN_ERR_CTX(res, "set output power");
res = fix_pa_clamping(); res = fix_pa_clamping();
APP_RADIO_RETURN_ERR_CTX(res, "failed to fix pa clamping"); APP_RADIO_RETURN_ERR_CTX(res, "fix pa clamping");
res = standby(); res = standby();
APP_RADIO_RETURN_ERR_CTX(res, "failed to standby"); APP_RADIO_RETURN_ERR_CTX(res, "standby");
return {}; return {};
}; };
} }

View File

@ -87,7 +87,7 @@ void init(spi_config_t config) {
.clock_speed_hz = config.clock_speed_hz, .clock_speed_hz = config.clock_speed_hz,
.spics_io_num = CS_PIN, .spics_io_num = CS_PIN,
.flags = SPI_DEVICE_NO_DUMMY, .flags = SPI_DEVICE_NO_DUMMY,
.queue_size = 2, .queue_size = 1,
}; };
ESP_ERROR_CHECK(spi_bus_initialize(config.host_id, &bus_config, SPI_DMA_CH_AUTO)); ESP_ERROR_CHECK(spi_bus_initialize(config.host_id, &bus_config, SPI_DMA_CH_AUTO));
@ -158,7 +158,7 @@ read_stream(uint8_t cmd, std::span<uint8_t> data, const size_t timeout_ms) {
std::array<uint8_t, STACK_BUFFER_SIZE> _rx_buf; std::array<uint8_t, STACK_BUFFER_SIZE> _rx_buf;
std::array<uint8_t, STACK_BUFFER_SIZE> _tx_buf; std::array<uint8_t, STACK_BUFFER_SIZE> _tx_buf;
if (data.size() > STACK_BUFFER_SIZE - 1) { if (data.empty() or data.size() > STACK_BUFFER_SIZE - 1) {
return ue_t{error::INVALID_SIZE}; return ue_t{error::INVALID_SIZE};
} }
@ -170,12 +170,18 @@ read_stream(uint8_t cmd, std::span<uint8_t> data, const size_t timeout_ms) {
auto tx_buffer = std::span{_tx_buf}.subspan(0, rx_buffer.size()); auto tx_buffer = std::span{_tx_buf}.subspan(0, rx_buffer.size());
std::ranges::fill(tx_buffer, PADDING); std::ranges::fill(tx_buffer, PADDING);
spi_transaction_ext_t transaction; spi_transaction_ext_t transaction{};
// during the Command and Address phases, the members spi_transaction_t::cmd
// and spi_transaction_t::addr are sent to the bus, nothing is read at this
// time.
transaction = spi_transaction_ext_t{ transaction = spi_transaction_ext_t{
.base = { .base = {
.flags = SPI_TRANS_VARIABLE_CMD, .flags = SPI_TRANS_VARIABLE_CMD,
.cmd = cmd, .cmd = cmd,
// total data length, in bits
.length = static_cast<size_t>(rx_buffer.size() * 8), .length = static_cast<size_t>(rx_buffer.size() * 8),
// total data length received, should be not greater than length in
// full-duplex mode (0 defaults this to the value of length).
.rxlength = static_cast<size_t>(rx_buffer.size() * 8), .rxlength = static_cast<size_t>(rx_buffer.size() * 8),
.tx_buffer = tx_buffer.data(), .tx_buffer = tx_buffer.data(),
.rx_buffer = rx_buffer.data(), .rx_buffer = rx_buffer.data(),
@ -215,7 +221,7 @@ write_stream(uint8_t cmd, std::span<const uint8_t> data, const size_t timeout_ms
} }
const auto rx_buffer = std::span{_rx_buf}.subspan(0, data.size()); const auto rx_buffer = std::span{_rx_buf}.subspan(0, data.size());
spi_transaction_ext_t transaction; spi_transaction_ext_t transaction{};
transaction = spi_transaction_ext_t{ transaction = spi_transaction_ext_t{
.base = { .base = {
.flags = SPI_TRANS_VARIABLE_CMD, .flags = SPI_TRANS_VARIABLE_CMD,