spi slave关于DMA模式下收发存在的BUG

Viewed 12

一、描述你遇到的问题

spi slave关于DMA模式下收发存在的BUG
我在linux端开通了spi master,ws63这边开通spi slave,我让spi master这边定时1s与slave通讯256字节,master会发送从0到255递增的数据,slave这边接收正常,我让slave向master发送全是0xAB的数据,master第一帧接收正常,后面就不正常了,体现在前面200多个字节都是0x00,后面30多字节才是0xAB

二、你具体做的所有步骤结果截图

#include "spi_slave.h"
#include "spi_slave_config.h"
#include "pinctrl.h"
#include "osal_debug.h"
#include "securec.h"
#include "watchdog.h"
#include "soc_osal.h"
#include "driver/dma.h"
#include "hal_spi_v151_regs_op.h"
#include <string.h>

#define SPI_SLAVE_TAG           "SPI_SLAVE"

/*
 * 注意: 使用 DMA 模式需要内核使能 CONFIG_SPI_SUPPORT_DMA=y.
 * 请确保在产品的 .config 或 defconfig 中配置:
 *   CONFIG_SPI_SUPPORT_DMA=y
 *   CONFIG_DRIVER_SUPPORT_DMA=y
 *
 * DMA TX 完成中断在最后 1 字节写入 TX FIFO 时触发,
 * 并非串行移出完毕后触发. 因此每次传输后 TX FIFO 中可能有
 * 残留数据 (约 28 字节, 对应 FIFO 深度).
 *
 * 解决方案:
 *   1. 每次传输前做 SSI 复位 (ssienr=0→1), 硬件清零 FIFO
 *   2. SSI 复位会同时清除 DCR.TDEN 和 DCR.RDEN (DMA 使能位)
 *   3. 立即重新使能 DMA, 恢复阈值配置
 *   4. 然后调用 uapi_spi_slave_writeread (路由到 DMA 路径)
 */

/* ---------------------------------------------------------------------------
 * SSI 复位并重新使能 DMA
 *
 * SSI 复位 (ssienr=0→1) 可硬件清空 TX/RX FIFO 中的残留数据,
 * 但会同时清除 DCR 寄存器的 TDEN/RDEN 位. 必须在复位后立即
 * 恢复 DMA 配置, 否则后续 writeread 不经过 DMA 路径.
 * --------------------------------------------------------------------------- */
static void spi_slave_reset_fifo_and_dma(spi_bus_t bus)
{
    /* 关闭 SSI → FIFO 自动复位 */
    hal_spi_ssienr_set_ssi_en(bus, 0U);
    for (volatile uint32_t i = 0; i < 50; i++) {}

    /* 重新使能 DMA: DCR.TDEN=1, DCR.RDEN=1 */
    hal_spi_v151_spi_dcr_set_tden(bus, 1U);
    hal_spi_dmacr_set_rdmae(bus, 1U);

    /* 恢复 DMA 阈值: TX 阈值 4, RX 阈值 0 (与 spi_porting.c 一致) */
    hal_spi_v151_spi_dtdl_data_set_dl(bus, 4U);
    hal_spi_dmardlr_set_dmardl(bus, 0U);

    /* 打开 SSI */
    hal_spi_ssienr_set_ssi_en(bus, 1U);
}

/* ---------------------------------------------------------------------------
 * 引脚配置
 * --------------------------------------------------------------------------- */
static void spi_slave_init_pin(const SpiSlaveConfig_t *config)
{
    if (config == NULL) {
        return;
    }

    uapi_pin_set_mode(config->di_pin, SPI_SLAVE_DATA_PIN_MODE);
    uapi_pin_set_mode(config->do_pin, SPI_SLAVE_DATA_PIN_MODE);
    uapi_pin_set_mode(config->clk_pin, SPI_SLAVE_DATA_PIN_MODE);
    uapi_pin_set_mode(config->cs_pin, SPI_SLAVE_CS_PIN_MODE);

    (void)uapi_pin_set_pull(config->cs_pin, PIN_PULL_TYPE_UP);
    (void)uapi_pin_set_ds(config->do_pin, PIN_DS_7);

    osal_printk("[%s] Pin config: DI=%d, DO=%d, CLK=%d, CS=%d\n",
                SPI_SLAVE_TAG,
                config->di_pin, config->do_pin,
                config->clk_pin, config->cs_pin);
}

/* ---------------------------------------------------------------------------
 * DMA 模式配置
 *
 * 使能 SPI 从机的 DMA 传输, 之后 uapi_spi_slave_writeread 内部将自动
 * 使用 DMA 通道完成读写, 而非 CPU 轮询 FIFO.
 * --------------------------------------------------------------------------- */
static errcode_t spi_slave_enable_dma(spi_bus_t bus)
{
    spi_dma_config_t dma_cfg = {
        .src_width    = SPI_SLAVE_DMA_SRC_WIDTH,
        .dest_width   = SPI_SLAVE_DMA_DEST_WIDTH,
        .burst_length = SPI_SLAVE_DMA_BURST_LENGTH,
        .priority     = SPI_SLAVE_DMA_PRIORITY,
    };

    errcode_t ret = uapi_spi_set_dma_mode(bus, true, &dma_cfg);
    if (ret != ERRCODE_SUCC) {
        osal_printk("[%s] DMA mode enable failed! ret=0x%x\n", SPI_SLAVE_TAG, ret);
        return ret;
    }

    osal_printk("[%s] DMA mode enabled (src_w=%d, dst_w=%d, burst=%d, pri=%d)\n",
                SPI_SLAVE_TAG,
                dma_cfg.src_width, dma_cfg.dest_width,
                dma_cfg.burst_length, dma_cfg.priority);
    return ERRCODE_SUCC;
}

/* ---------------------------------------------------------------------------
 * 公开 API
 * --------------------------------------------------------------------------- */
errcode_t SpiSlave_Init(SpiSlave_t *slave, const SpiSlaveConfig_t *config)
{
    errcode_t ret;

    if (slave == NULL || config == NULL) {
        return ERRCODE_INVALID_PARAM;
    }

    slave->config = *config;
    slave->initialized = false;

    spi_slave_init_pin(config);

    spi_attr_t attr = { 0 };
    attr.is_slave = true;
    attr.slave_num = 1;
    attr.bus_clk = config->bus_clk;
    attr.freq_mhz = config->freq_mhz;
    attr.clk_polarity = config->clk_polarity;
    attr.clk_phase = config->clk_phase;
    attr.frame_format = SPI_SLAVE_FRAME_FORMAT;
    attr.spi_frame_format = SPI_SLAVE_SPI_FRAME_FORMAT;
    attr.frame_size = config->frame_size;
    attr.tmod = config->tmod;
    attr.sste = SPI_SLAVE_SSTE;

    spi_extra_attr_t ext_attr = { 0 };
    ext_attr.qspi_param.wait_cycles = 0x10;

    ret = uapi_spi_init((spi_bus_t)config->bus_id, &attr, &ext_attr);
    if (ret != ERRCODE_SUCC) {
        osal_printk("[%s] SPI slave init failed! ret=0x%x\n", SPI_SLAVE_TAG, ret);
        return ret;
    }

    /* 初始化并打开 DMA 控制器 (幂等, 多次调用安全) */
    ret = uapi_dma_init();
    if (ret != ERRCODE_SUCC) {
        osal_printk("[%s] DMA init failed! ret=0x%x\n", SPI_SLAVE_TAG, ret);
        uapi_spi_deinit((spi_bus_t)config->bus_id);
        return ret;
    }
    ret = uapi_dma_open();
    if (ret != ERRCODE_SUCC) {
        osal_printk("[%s] DMA open failed! ret=0x%x\n", SPI_SLAVE_TAG, ret);
        uapi_spi_deinit((spi_bus_t)config->bus_id);
        return ret;
    }

    /* 使能 SPI DMA 传输模式 */
    ret = spi_slave_enable_dma((spi_bus_t)config->bus_id);
    if (ret != ERRCODE_SUCC) {
        uapi_spi_deinit((spi_bus_t)config->bus_id);
        return ret;
    }

    slave->initialized = true;

    osal_printk("[%s] SPI slave initialized on bus %d (DMA writeread)\n",
                SPI_SLAVE_TAG, config->bus_id);
    return ERRCODE_SUCC;
}

/* ---------------------------------------------------------------------------
 * SPI 从机主循环 (DMA 阻塞模式)
 *
 * 使用 uapi_spi_slave_writeread 阻塞等待 Master 发起 256 字节交互。
 * 驱动层在 DMA 使能后自动使用 DMA 通道完成数据传输, CPU 仅在
 * osal_sem_down_timeout 处等待 DMA 完成中断, 无需轮询 FIFO.
 *
 * 每次完成后调用 rx_cb, 然后进入下一次等待。永不返回。
 * --------------------------------------------------------------------------- */
void SpiSlave_RunLoop(SpiSlave_t *slave, spi_slave_rx_callback_t rx_cb)
{
    spi_bus_t bus;
    spi_xfer_data_t xfer = { 0 };
    uint16_t frame_len = SPI_SLAVE_FRAME_BYTES;
    uint32_t err_cnt = 0;

    if (slave == NULL || !slave->initialized) {
        osal_printk("[%s] RunLoop called without init!\n", SPI_SLAVE_TAG);
        return;
    }

    bus = (spi_bus_t)slave->config.bus_id;

    /* 填充 TX 缓冲区为 0xAB, 从机发给主机的数据 */
    (void)memset_s(slave->tx_buf, sizeof(slave->tx_buf), 0xAB, sizeof(slave->tx_buf));

    osal_printk("[%s] RunLoop start (DMA), frame=%u, timeout=%u\n",
                SPI_SLAVE_TAG, (unsigned)frame_len, (unsigned)SPI_SLAVE_POLL_TIMEOUT);

    xfer.tx_buff = slave->tx_buf;
    xfer.rx_buff = slave->rx_buf;
    xfer.tx_bytes = frame_len;
    xfer.rx_bytes = frame_len;

    while (1) {
        (void)uapi_watchdog_kick();

        /*
         * SSI 复位清零 FIFO 残留 + 重新使能 DMA, 确保每次传输
         * 都从干净的 TX/RX FIFO 状态开始.
         */
        spi_slave_reset_fifo_and_dma(bus);

        /*
         * uapi_spi_slave_writeread 在 DMA 模式下:
         * 1. 配置 DMA 通道 (RX + TX)
         * 2. 启动 DMA 传输
         * 3. 阻塞等待 DMA 完成中断 (osal_sem_down_timeout)
         * 4. 返回传输结果
         */
        errcode_t ret = uapi_spi_slave_writeread(bus, &xfer, SPI_SLAVE_POLL_TIMEOUT);

        if (ret == ERRCODE_SUCC) {
            if (rx_cb != NULL) {
                rx_cb(slave->rx_buf, frame_len);
            }
            err_cnt = 0;
        } else {
            err_cnt++;
            if (err_cnt <= 3U) {
                osal_printk("[%s] DMA xfer failed! ret=0x%x (err_cnt=%u)\n",
                            SPI_SLAVE_TAG, (unsigned)ret, (unsigned)err_cnt);
            }
            /* 连续大量错误时打印警告 */
            if (err_cnt == 50U) {
                osal_printk("[%s] Too many DMA errors, check master connection!\n", SPI_SLAVE_TAG);
            }
        }

        (void)osal_yield();
    }
}

三、当前开发板状态全景照片

请插入图片

四、开发板串口所有日志

下面是ws63端的串口日志

boot.
Flash Init Fail! ret = 0x80001341
verify_public_rootkey secure verify disable!
verify_params_key_area secure verify disable!
verify_params_area_info secure verify disable!
verify_image_key_area secure verify disable!
verify_image_code_info secure verify disable!
SSB Uart Init Succ!
SSB Flash Init Succ!
verify_image_key_area secure verify disable!
verify_image_code_info secure verify disable!
Flashboot Uart Init Succ!
Flashboot Malloc Init Succ!
Flash Init Succ!
No need to fix SR!
io level work in hw mode, level[chip]:0x33
flashboot version : 1.10.102
[UPG] upgrade init OK!
No need to upgrade...
flash_encrypt disable.
verify_image_key_area secure verify disable!
verify_image_code_info secure verify disable!
APP|dbg uart init ok.
[UPG] upgrade init OK!
APP|init_sle_mac, mac_addr:0x50,0x65,0x 7,0xc9,0x**,0x**,
APP|init_dev_addr, mac_addr:0x50,0x65,0x 7,0x64,0x**,0x**,
xo_trim_temp_comp val:0 0
los_at_plt_cmd_register EXCUTE
APP|thread[11] func null
cpu 0 entering scheduler
APP|btc open
[SPI_SLAVE] Pin config: DI=11, DO=9, CLK=7, CS=10
[SPI_SLAVE] DMA mode enabled (src_w=0, dst_w=0, burst=0, pri=0)
[SPI_SLAVE] SPI slave initialized on bus 0 (DMA writeread)
[APP] SpiSlave_Init OK, entering DMA RunLoop...
[SPI_SLAVE] RunLoop start (DMA), frame=256, timeout=3500
[RADAR_LOG] alg ctrl read from nv [1][2][0][0][1][1][20]
device_main_init: 0!
===hal_initialize_phy===226===
device_module_init:: succ!
cali_set_cali_mask:old[0x0] -> new[0x1fa2]

fe_rf_initialize
cali_offline_cali_entry enter
cali_set_cali_done_flag:old[0x0] -> new[0x1]

rf cali OK. time cost:21, ret:0
[SPI_SLAVE] DMA xfer failed! ret=0x80001337 (err_cnt=1)
xo update temp:3,diff:0,xo:0x30000
[APP] RX (256 bytes): 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 
[APP] RX (256 bytes): 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 
[APP] RX (256 bytes): 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 
[APP] RX (256 bytes): 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 
[APP] RX (256 bytes): 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 

下面是linux作为SPI master的打印

root@ATK-DLRK3568:/test# ./spi3_master
[MAIN] SPI opened (2MHz, mode 0), polling slave every 1s...
[0] ---- poll ok, 256 bytes ----
RX [256 bytes]
  0000: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  0010: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  0020: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  0030: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  0040: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  0050: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  0060: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  0070: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  0080: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  0090: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  00a0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  00b0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  00c0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  00d0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  00e0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  00f0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
[1] ---- poll ok, 256 bytes ----
RX [256 bytes]
  0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00d0: 00 00 00 00 00 00 00 00 00 00 00 00 ab ab ab ab
  00e0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  00f0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
[2] ---- poll ok, 256 bytes ----
RX [256 bytes]
  0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00d0: 00 00 00 00 00 00 00 00 00 00 00 00 ab ab ab ab
  00e0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  00f0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
[3] ---- poll ok, 256 bytes ----
RX [256 bytes]
  0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00d0: 00 00 00 00 00 00 00 00 00 00 00 00 ab ab ab ab
  00e0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  00f0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
[4] ---- poll ok, 256 bytes ----
RX [256 bytes]
  0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00d0: 00 00 00 00 00 00 00 00 00 00 00 00 ab ab ab ab
  00e0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  00f0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
[5] ---- poll ok, 256 bytes ----
RX [256 bytes]
  0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00d0: 00 00 00 00 00 00 00 00 00 00 00 00 ab ab ab ab
  00e0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  00f0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
[6] ---- poll ok, 256 bytes ----
RX [256 bytes]
  0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  00d0: 00 00 00 00 00 00 00 00 00 00 00 00 ab ab ab ab
  00e0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  00f0: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
^C
root@ATK-DLRK3568:/test#

1 Answers

1、SSI复位清零FIFO:通过将ssienr寄存器从0设置为1来复位SSI,这会硬件清空TX/RX FIFO中的残留数据。

2、重新使能DMA:SSI复位会同时清除DMA控制寄存器(DCR)中的TDEN/RDEN位。必须在复位后立即重新使能DMA并恢复阈值配置。

3、调用传输接口:最后再调用uapi_spi_slave_writeread进行DMA传输。

试试这三个方法

我的代码就是你说的这个结构,你看一下我的RunLoop里面的while循环