sync lr2021 with radiolib commits

This commit is contained in:
liquidraver
2026-08-07 14:17:05 +02:00
parent e76439c2e8
commit 17dfa78629
@@ -213,6 +213,50 @@ lr20xx_hal_status_t lr20xx_hal_write(const void *context, const uint8_t *command
return wait_on_busy(ctx);
}
/* LR2021 prepends a 2-byte stat header before response data (datasheet §5.4.1.2) */
#define LR20XX_STAT_LEN 2
/**
* @brief Clock one command-and-response frame inside a single NSS assertion.
*
* The LR2021 streams the whole answer within the NSS window that carried the
* command:
*
* MOSI [ command_length ][ LR20XX_STAT_LEN + data_length ]
* MISO [ undefined ][ stat header ][ payload ]
*
* Releasing NSS between the command and the payload ends the frame, so the
* following read starts a fresh one and the chip answers it with the status /
* IRQ word rather than the payload the caller asked for. That misread is not
* obviously wrong at the call site — it is a plausible-looking short integer —
* so it surfaces as nonsense lengths and all-zero status reads rather than as
* an SPI error. Keep every read in one transaction.
*
* NULL buffers clock 0x00 (the LR2021 NOP opcode) on MOSI and discard on MISO,
* so no scratch buffer is needed regardless of length.
*/
static int lr20xx_spi_read_frame(struct lr20xx_hal_context *ctx, const uint8_t *command,
uint16_t command_length, uint8_t *data, uint16_t data_length)
{
const struct spi_buf tx_bufs[] = {
{ .buf = (uint8_t *)command, .len = command_length },
{ .buf = NULL, .len = LR20XX_STAT_LEN + data_length },
};
const struct spi_buf rx_bufs[] = {
{ .buf = NULL, .len = command_length + LR20XX_STAT_LEN },
{ .buf = data, .len = data_length },
};
const struct spi_buf_set tx = { .buffers = tx_bufs, .count = 2 };
const struct spi_buf_set rx = { .buffers = rx_bufs, .count = 2 };
int ret;
gpio_pin_set_dt(&ctx->nss, 1);
ret = spi_transceive(ctx->spi_dev, &ctx->spi_cfg, &tx, &rx);
gpio_pin_set_dt(&ctx->nss, 0);
return ret;
}
lr20xx_hal_status_t lr20xx_hal_read(const void *context, const uint8_t *command,
const uint16_t command_length,
uint8_t *data, const uint16_t data_length)
@@ -231,38 +275,27 @@ lr20xx_hal_status_t lr20xx_hal_read(const void *context, const uint8_t *command,
return LR20XX_HAL_STATUS_ERROR;
}
const struct spi_buf tx_buf = { .buf = (uint8_t *)command, .len = command_length };
const struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1 };
gpio_pin_set_dt(&ctx->nss, 1);
ret = spi_write(ctx->spi_dev, &ctx->spi_cfg, &tx);
gpio_pin_set_dt(&ctx->nss, 0);
if (ret < 0) {
LOG_ERR("SPI write (cmd) failed: %d", ret);
return LR20XX_HAL_STATUS_ERROR;
}
/* No response requested — this is a plain command write. */
if (data_length == 0) {
const struct spi_buf tx_buf = {
.buf = (uint8_t *)command,
.len = command_length,
};
const struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1 };
gpio_pin_set_dt(&ctx->nss, 1);
ret = spi_write(ctx->spi_dev, &ctx->spi_cfg, &tx);
gpio_pin_set_dt(&ctx->nss, 0);
if (ret < 0) {
LOG_ERR("SPI write (cmd) failed: %d", ret);
return LR20XX_HAL_STATUS_ERROR;
}
return wait_on_busy(ctx);
}
if (check_device_ready(ctx) != LR20XX_HAL_STATUS_OK) {
return LR20XX_HAL_STATUS_ERROR;
}
/* LR2021 prepends 2-byte stat header before response data (datasheet §5.4.1.2) */
uint8_t dummy[2];
const struct spi_buf rx_bufs[] = {
{ .buf = dummy, .len = sizeof(dummy) },
{ .buf = data, .len = data_length },
};
const struct spi_buf_set rx = { .buffers = rx_bufs, .count = 2 };
gpio_pin_set_dt(&ctx->nss, 1);
ret = spi_read(ctx->spi_dev, &ctx->spi_cfg, &rx);
gpio_pin_set_dt(&ctx->nss, 0);
ret = lr20xx_spi_read_frame(ctx, command, command_length, data, data_length);
if (ret < 0) {
LOG_ERR("SPI read failed: %d", ret);
return LR20XX_HAL_STATUS_ERROR;
@@ -309,23 +342,11 @@ lr20xx_hal_status_t lr20xx_hal_direct_read_fifo(const void *context,
return LR20XX_HAL_STATUS_ERROR;
}
/* Single NSS assertion: command on MOSI, data on MISO, overlapped.
* NULL tx buf causes nRF SPIM to send 0x00 during data phase. */
const struct spi_buf tx_bufs[] = {
{ .buf = (uint8_t *)command, .len = command_length },
{ .buf = NULL, .len = data_length },
};
const struct spi_buf rx_bufs[] = {
{ .buf = NULL, .len = command_length },
{ .buf = data, .len = data_length },
};
const struct spi_buf_set tx_set = { .buffers = tx_bufs, .count = 2 };
const struct spi_buf_set rx_set = { .buffers = rx_bufs, .count = 2 };
gpio_pin_set_dt(&ctx->nss, 1);
ret = spi_transceive(ctx->spi_dev, &ctx->spi_cfg, &tx_set, &rx_set);
gpio_pin_set_dt(&ctx->nss, 0);
/* The RX FIFO answers with the same [stat header][payload] framing as
* every other read — it is not a raw byte stream. Skipping the header
* here is what keeps the returned packet aligned; consuming it as
* payload shifts the whole frame two bytes and corrupts every receive. */
ret = lr20xx_spi_read_frame(ctx, command, command_length, data, data_length);
if (ret < 0) {
LOG_ERR("SPI FIFO read failed: %d", ret);
return LR20XX_HAL_STATUS_ERROR;