简体   繁体   English

STM32微控制器与其他外设的QSPI连接代替Flash存储器

[英]QSPI connection on STM32 microcontrollers with other peripherals instead of Flash memories

I will start a project which needs a QSPI protocol.我将开始一个需要 QSPI 协议的项目。 The component I will use is a 16-bit ADC which supports QSPI with all combinations of clock phase and polarity.我将使用的组件是一个 16 位 ADC,它支持具有所有时钟相位和极性组合的 QSPI。 Unfortunately, I couldn't find a source on the inte.net that points to QSPI on STM32, which works with other components rather than Flash memories.不幸的是,我在 inte.net 上找不到指向 STM32 上的 QSPI 的源代码,它与其他组件一起工作,而不是 Flash 内存。 Now, my question: Can I use STM32's QSPI protocol to communicate with other devices that support QSPI?现在,我的问题是:我可以使用 STM32 的 QSPI 协议与其他支持 QSPI 的设备通信吗? Or is it just configured to be used for memories?或者它只是被配置为用于记忆? The ADC component I want to use is: ADS9224R (16-bit, 3MSPS) Here is the image of the datasheet that illustrates this device supports the full QSPI protocol.我要使用的 ADC 组件是:ADS9224R(16 位,3MSPS)这是说明该设备支持完整 QSPI 协议的数据表图片。 Many thanks非常感谢

page 33 of the datasheet数据表第 33 页

The STM32 QSPI can work in several modes. STM32 QSPI 可以在多种模式下工作。 The Memory Mapped mode is specifically designed for memories. Memory Mapped 模式专为内存设计。 The Indirect mode however can be used for any peripheral.然而,间接模式可用于任何外设。 In this mode you can specify the format of the commands that are exchanged: presence of an instruction, of an adress, of data, etc... See register QUADSPI_CCR .在这种模式下,您可以指定交换的命令的格式:指令的存在、地址的存在、数据的存在等……参见寄存器QUADSPI_CCR

QUADSPI supports indirect mode, where for each data transaction you manually specify command, number of bytes in address part, number of data bytes, number of lines used for each part of the communication and so on. QUADSPI 支持间接模式,对于每个数据事务,您手动指定命令、地址部分的字节数、数据字节数、通信各部分使用的线路数等。 Don't know whether HAL supports all of that, it would probably be more efficient to work directly with QUADSPI registers - there are simply too many levers and controls you need to set up, and if the library is missing something, things may not work as you want, and QUADSPI is pretty unpleasant to debug.不知道 HAL 是否支持所有这些,直接使用 QUADSPI 寄存器可能会更有效 - 您需要设置的控制杆和控件太多,如果库缺少某些东西,事情可能无法正常工作随心所欲,而且 QUADSPI 很难调试。 Luckily, after initial setup, you probably won't need to change very much in its settings.幸运的是,在初始设置之后,您可能不需要对其设置进行太多更改。

In fact, some time ago, when I was learning QUADSPI, I wrote my own indirect read/write for QUADSPI flash. Purely a demo program for myself.其实前段时间在学习QUADSPI的时候,自己写了自己的QUADSPI flash的间接读/写,纯粹是给自己的demo程序。 With a bit of tweaking it shouldn't be hard to adapt it.通过一些调整,适应它应该不难。 From my personal experience, QUADSPI is a little hard at first, I spent a pair of weeks debugging it with logic analyzer until I got it to work.根据我个人的经验,QUADSPI 一开始有点难,我花了几周的时间用逻辑分析仪调试它,直到我让它工作。 Or maybe it was due to my general inexperience.或者也许是由于我一般缺乏经验。

Below you can find one of my functions, which can be used after initial setup of QUADSPI.您可以在下面找到我的功能之一,可以在 QUADSPI 初始设置后使用。 Other communication functions are around the same length.其他通信功能的长度大致相同。 You only need to set some settings in a few registers.您只需要在几个寄存器中设置一些设置。 Be careful with the order of your register manipulations - there is no "start communication" flag/bit/command.注意寄存器操作的顺序——没有“开始通信”标志/位/命令。 Communication starts automatically when you set some parameters in specific registers.当您在特定寄存器中设置一些参数时,通信会自动开始。 This is explicitly stated in the reference manual, QUADSPI section, which was the only documentation I used to write my code.这在参考手册的 QUADSPI 部分中有明确说明,这是我用来编写代码的唯一文档。 There is surprisingly limited information on QUADSPI available on the Inte.net, even less with registers. Inte.net 上关于 QUADSPI 的信息非常有限,关于寄存器的信息就更少了。

Here is a piece from my basic example code on registers:这是我关于寄存器的基本示例代码中的一段:

void QSPI_readMemoryBytesQuad(uint32_t address, uint32_t length, uint8_t destination[]) {

    while (QUADSPI->SR & QUADSPI_SR_BUSY); //Make sure no operation is going on
    QUADSPI->FCR = QUADSPI_FCR_CTOF | QUADSPI_FCR_CSMF | QUADSPI_FCR_CTCF | QUADSPI_FCR_CTEF; // clear all flags
    QUADSPI->DLR = length - 1U; //Set number of bytes to read
    QUADSPI->CR = (QUADSPI->CR & ~(QUADSPI_CR_FTHRES)) | (0x00 << QUADSPI_CR_FTHRES_Pos); //Set FIFO threshold to 1

    /*
     * Set communication configuration register
     * Functional mode:             Indirect read
     * Data mode:                   4 Lines
     * Instruction mode:            4 Lines
     * Address mode:                4 Lines
     * Address size:                24 Bits
     * Dummy cycles:                6 Cycles
     * Instruction:                 Quad Output Fast Read
     *
     * Set 24-bit Address
     *
     */

    QUADSPI->CCR =
            (QSPI_FMODE_INDIRECT_READ << QUADSPI_CCR_FMODE_Pos)             |
            (QIO_QUAD << QUADSPI_CCR_DMODE_Pos)                             |
            (QIO_QUAD << QUADSPI_CCR_IMODE_Pos)                             |
            (QIO_QUAD << QUADSPI_CCR_ADMODE_Pos)                            |
            (QSPI_ADSIZE_24 << QUADSPI_CCR_ADSIZE_Pos)                      |
            (0x06 << QUADSPI_CCR_DCYC_Pos)                                  |
            (MT25QL128ABA1EW9_COMMAND_QUAD_OUTPUT_FAST_READ << QUADSPI_CCR_INSTRUCTION_Pos);

    QUADSPI->AR = (0xFFFFFF) & address;

    /* ---------- Communication Starts Automatically ----------*/

    while (QUADSPI->SR & QUADSPI_SR_BUSY) {
        if (QUADSPI->SR & QUADSPI_SR_FTF) {
            *destination = *((uint8_t*) &(QUADSPI->DR)); //Read a byte from data register, byte access
            destination++;
        }
    }
    QUADSPI->FCR = QUADSPI_FCR_CTOF | QUADSPI_FCR_CSMF | QUADSPI_FCR_CTCF | QUADSPI_FCR_CTEF; //Clear flags

}

It is a little crude, but it may be a good starting point for you, and it's well-tested and definitely works.它有点粗糙,但对您来说可能是一个很好的起点,而且它经过充分测试并且绝对有效。 You can find all my functions here (GitHub) .您可以在此处 (GitHub)找到我的所有功能。 Combine it with reading the QUADSPI section of the reference manual, and you should start to get a grasp of how to make it work.将其与阅读参考手册的 QUADSPI 部分结合起来,您应该开始掌握如何使其工作。

Your job will be to determine what kind of commands and in what format you need to send to your QSPI slave device.您的工作将是确定您需要将何种命令以何种格式发送到您的 QSPI 从设备。 That information is available in the device's datasheet.该信息可在设备的数据表中找到。 Make sure you send command and address and every other part on the correct number of QUADSPI lines.确保您在正确数量的 QUADSPI 线路上发送命令和地址以及所有其他部分。 For example, sometimes you need to have command on 1 line and data on all 4, all in the same transaction.例如,有时您需要在 1 行上有命令,在所有 4 行上有数据,所有这些都在同一个事务中。 Make sure you set dummy cycles, if they are required for some operation.如果某些操作需要虚拟循环,请确保设置虚拟循环。 Pay special attention at how you read data that you receive via QUADSPI.请特别注意您如何读取通过 QUADSPI 接收的数据。 You can read it in 32-bit words at once (if incoming data is a whole number of 32-bit words).您可以一次读取 32 位字(如果传入数据是 32 位字的整数)。 In my case - in the function provided here - I read it by individual bytes, hence such a scary looking *destination = *((uint8_t*) &(QUADSPI->DR));就我而言——在此处提供的 function 中——我按单个字节读取它,因此看起来很可怕*destination = *((uint8_t*) &(QUADSPI->DR)); , where I take an address of the data register, cast it to pointer to uint8_t and dereference it. ,我在其中获取数据寄存器的地址,将其转换为指向 uint8_t 的指针并取消引用它。 Otherwise, if you read DR just as QUADSPI->DR , your MCU reads 32-bit word for every byte that arrives, and QUADSPI goes crazy and hangs and shows various errors and triggers FIFO threshold flags and stuff.否则,如果您读取 DR 就像QUADSPI->DR一样,您的 MCU 会为每个到达的字节读取 32 位字,并且 QUADSPI 变得疯狂并挂起并显示各种错误并触发 FIFO 阈值标志和东西。 Just be mindful of how you read that register.请注意您如何阅读该寄存器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM