我使用STM32F407VTG6控制器并尝试使用DMA从SPI接收数据.然后我想在DMA完全传输中断上处理数据.但是当发生完全传输中断时,我看到TEIF(传输错误中断标志)已设置.此DMA无法启动.这是我的代码的一部分:
static void DmaInit()
{
 DMA_InitTypeDef dma;
 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
 // DMA for Rx
 dma.DMA_Channel = DMA_Channel_3;
 dma.DMA_PeripheralBaseAddr = (uint32_t)&SPI1->DR;
 dma.DMA_Memory0BaseAddr = 0; // will be set later
 dma.DMA_DIR = DMA_DIR_PeripheralToMemory;
 dma.DMA_BufferSize = 1; // will be set later
 dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
 dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
 dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
 dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
 dma.DMA_Mode = DMA_Mode_Normal;
 dma.DMA_Priority = DMA_Priority_High;
 dma.DMA_FIFOMode = DMA_FIFOMode_Disable;
 dma.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
 dma.DMA_MemoryBurst = DMA_MemoryBurst_Single;
 dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
 DMA_DeInit(DMA2_Stream2);
 DMA_Init(DMA2_Stream2, &dma);
 // Enable DMA Interrupt on complete transfer
 NVIC_EnableIRQ(DMA2_Stream2_IRQn);
 DMA_ITConfig(DMA2_Stream2, …我有一个微控制器必须从PC串口(115200波特)下载大文件,并通过SPI(~2 MHz)将其写入串行闪存.闪存写入必须是256字节块,然后是写入命令和页面地址.系统上可用的总RAM为1 kB,堆栈大小为80字节.
目前这是通过从UART填充256字节缓冲区然后通过ping到ponging到另一个256字节缓冲区来填充另一个256字节缓冲区由RX缓冲区就绪信号上的中断填充,同时使用忙写入写入闪存.重复缓冲区交换,直到操作完成.
我更喜欢为在单独的循环缓冲区上运行的SPI和UART端口设置TX/RX中断处理程序.因此,我可以简单地填充TX缓冲区并启用中断或检查缓冲区是否有输入数据,而不是轮询新字节并等待操作完成.这将为实际工作提供更多的时钟周期,而不是等待外设.
在使用128字节循环缓冲区实现IRQ之后,我在UART RX缓冲区中查询数据并立即将其放入SPI TX缓冲区以进行文件传输.我使用这种方法的问题是我没有足够的RAM用于缓冲区,并且PC接收缓冲区的填充速度比我将数据传输到闪存传输缓冲区要快.显然,传输速度不是问题(115.2 kHz输入和2 MHz输出),但在每个256字节页面传输后有一个写周期等待.
频繁的SPI中断似乎阻塞了一些UART中断并导致丢失了字节.我选择的解决方案是使用环形缓冲区用于UART接收中断,并将数据馈送到256字节页缓冲区,通过轮询字节传输和写完成将其发送到串行闪存.128个环形缓冲区足以防止SPI写入期间出现溢出.
我正在维护一些通过SPI与FPGA通信的用户空间代码.现在正在轮询,看看是否有数据可以采取行动,我并不感到兴奋.comm线程的(大大简化)结构如下所示:
int spi_fd;
void do_transfer(char *buf, int len)
{
    struct spi_ioc_transfer xfer;
    memset(xfer, 0, sizeof(xfer));
    ioctl_tell_some_fpga_register_heads_up();
    xfer[0].len = len;
    xfer[0].tx_buf = NULL;
    xfer[0].rx_buf = buf;
    ioctl(spi_fd, SPI_IOC_MESSAGE(1), xfer);
    ioctl_tell_some_fpga_register_were_done();
}
void *comm_thread(void arg)
{
    uint8_t config = SPI_MODE_3;
    __u32 speed = 4000000;
    char buffer[5120];
    spi_fd = open("/dev/spidev1.0", O_RDWR);
    ioctl(spi_fd, SPI_IOC_WR_MODE, &config);
    ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
    while(1) {
        sleep(2); //ugh
        if(ioctl_read_some_fpga_register_that_says_if_theres_data())
        {
            do_transfer(buffer, some_small_number_of_bytes());
            do_stuff(buffer); //you get the picture
        }
    }
}
我真的很喜欢在轮询和睡眠的基于事件的解决方案.首先想到的是在spidev文件描述符上执行select()而不是每X秒检查一次寄存器,类似于
fd_set myset;
while(1) {
    FD_ZERO(&myset);
    FD_SET(spi_fd, &myset); …典型的 x86 系统将固件(也称为 BIOS 或 UEFI)存储在基于 SPI 的闪存芯片中。当上电发生时,处理器开始执行复位向量,该向量指向存储 BIOS 的内存映射 SPI 芯片。从这里开始,引导发生在 BIOS 完成平台初始化、加载引导加载程序,然后加载内核时。
但是,处理器如何知道如何从 SPI 芯片中读取数据呢?我的意思是,那时处理器将不知道 SPI 协议,芯片的哪些寄存器写入命令以及哪个寄存器查找读取的数据。读取是如何发生在如此低的水平上的?
我正在尝试使用 z80 制作一台复古计算机,理想情况下希望让它能够从 SD 卡启动。我 100% 决定使用 z80,并且不想使用具有内部 SPI 硬件接口的微控制器。我想了解计算机的硬件和软件方面,因此 arduino 和微控制器不在考虑之列,因为硬件方面在您购买之前就已完成。无论如何,我的主要问题是是否可以将移位寄存器、一些解码逻辑和软件结合起来通过 SPI 模式从 SD 卡读取数据?我在互联网上搜索了几个小时并阅读了几篇文章,但似乎找不到教程。我了解 SPI 协议,但是,缺乏有关硬件方面的信息,因为微控制器往往内置所有硬件。我计划将 SD 卡的 SOMI 连接到移位寄存器 SIMO 的串行输入引脚将SD卡的串行输出引脚连接到移位寄存器的串行输出引脚,然后将一些数据引脚连接到一些触发器,中间有一些解码逻辑,这样如果我输出到特定端口,它将切换触发器。触发器将充当 SD 卡的时钟和芯片使能线。我还将 z80 的一个引脚连接到移位寄存器的锁存器引脚(同样在中间有解码逻辑),这样如果我输出到特定端口,它将锁存移位寄存器的数据。我不关心速度/效率,只要我能准确地从 SD 卡读取数据即可。另外,我是否可以将移位寄存器时钟输入连接到与 SD 卡连接的同一时钟?任何有关如何实现这一点的建议将不胜感激,谢谢!
有谁知道有一家公司销售适用于普通非物联网 Windows 10 PC 的 USB 电缆,该电缆可以将 USB 转换为 40 针 Raspberry pi 接头上的所有以下总线?示例:USB->GPIO、I2C、SPI、UART 等。
我能找到的最接近的是:
这可以将 PC USB 转换为 GPIO/I2C/SPI 等...除了我正在寻找更小、电线更少的东西...只有 40 针接头或更少...类似于树莓派 40 针接头,除了被驱动从连接到 PC 的 USB 改为...有人见过这种类型的待售产品,它可以通过所有列出的总线从 PC-USB 转换为 40 针接头吗?
另外,我希望能够使用“Windows.Devices”Api 而不是专有驱动程序 DLL API 通过Windows UWP对该 USB 转换设备进行编程...还没有真正找到...示例:
// C# Program GPIO connected to USB dongle of regular PC...
using Windows.Devices.GPIO;
...
private void InitGPIO()
{
    var gpio_ctrl = GpioController.GetDefault();
    // Check GPIO state
    if (gpio_ctrl == null)
    {
        this.pin = null; …我正在使用 STM32L476RG 板和 HAL SPI 功能:
HAL_SPI_Transmit(&hspi2, &ReadAddr, 1, HAL_MAX_DELAY);
HAL_SPI_Receive(&hspi2, pBuffer, 4, HAL_MAX_DELAY);
我需要以最大速度从加速度计的缓冲区接收数据,但这些功能存在延迟问题。正如您在示波器屏幕截图中看到的那样,有几微秒没有任何反应。我不知道如何最小化传输间隙。
我尝试使用 HAL_SPI_Receive_DMA 函数,这个延迟更大。您知道如何使用 HAL 函数或有关如何在没有这些延迟的情况下编写 SPI 函数的任何指针来解决此问题吗?
我刚刚为PINE64 ROCK64媒体板编译了U-Boot 2020.04。它编译得很好,没有错误。但当我尝试探测 SPI 闪存时遇到了问题。
U-Boot 命令行的输出:
=> sf probe
Invalid bus 0 (err=-19)
Failed to initialize SPI flash at 0:0 (error -19)
=>
开发板上的设备树 SPI 部分:
&spi0 {
    status = "okay";
    spiflash@0 {
        compatible = "jedec,spi-nor";
        reg = <0>;
        /* maximum speed for Rockchip SPI */
        spi-max-frequency = <50000000>;
    };
};
我还尝试了不同的总线和芯片选择。但没有成功。根据电路板原理图,使用的是 SPI 闪存器件GD25Q128CS。
我如何编译源代码:
$ make rock64-rk3328_defconfig
$ make CROSS_COMPILE=/path/to/gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin/aarch64-none-elf- -j 4
我使用了ARM 网站上的官方GCC端口。
还尝试了旧版本和新版本的 U-Boot。同样的问题。我按照U-Boot文档刷写了microSD卡:
$ dd if=idbloader.img …