Board logo

标题: CYPEESS USB3.0程序解读之---SPI读写 [打印本页]

作者: look_w    时间: 2017-11-18 14:26     标题: CYPEESS USB3.0程序解读之---SPI读写

前面已经解读了GPIO以及同步FIFO操作,下面我们看一个SPI读写的例子,它是主程序命令从SPI中读写一些数据。
SPI传输子程序看一下: 页地址,字节计数,缓冲区,读写标志
因为只能一页一页的读或写,故读写总是从页地址开始的
/* SPI read / writefor programmer application. */
CyU3PReturnStatus_t
CyFxSpiTransfer (
        uint16_t  pageAddress, //页地址
        uint16_t  byteCount,      //字节计数
        uint8_t *buffer,            //缓冲区
        CyBool_t  isRead)                  //读写标志
{
    CyU3PDmaBuffer_t buf_p;    //DMA buffer
    uint8_t location[4];
    uint32_t byteAddress = 0;
    uint16_t pageCount = (byteCount /glSpiPageSize);
    CyU3PReturnStatus_t status =CY_U3P_SUCCESS;

    if (byteCount == 0)
    {
        return CY_U3P_SUCCESS;
    }
    if ((byteCount % glSpiPageSize) != 0)
    {
        pageCount ++;                ///如果除不尽,则按多一页来读写
    }

    buf_p.buffer = buffer; //地址重载
    buf_p.status = 0;

    byteAddress = pageAddress * glSpiPageSize;                   //页地址*尺寸=实际地址
    CyU3PDebugPrint (2, "SPI access -addr: 0x%x, size: 0x%x, pages: 0x%x.\r\n",
            byteAddress, byteCount, pageCount);

    while (pageCount != 0)
    {
                   //高字节
        location[1] = (byteAddress >> 16)& 0xFF;       /* MS byte */
        location[2] = (byteAddress >> 8)& 0xFF;
        //低字节
        location[3] = byteAddress &0xFF;               /* LS byte */

        if (isRead)
        {
            location[0] = 0x03; /* Read command. *///读命令

            buf_p.size  = glSpiPageSize;
            buf_p.count = glSpiPageSize;

            status = CyFxSpiWaitForStatus ();
            if (status != CY_U3P_SUCCESS)
                return status;

            CyU3PSpiSetSsnLine (CyFalse);
            status = CyU3PSpiTransmitWords(location, 4);
            if (status != CY_U3P_SUCCESS)
            {
                CyU3PDebugPrint (2, "SPIREAD command failed\r\n");
                CyU3PSpiSetSsnLine (CyTrue);
                return status;
            }

            CyU3PSpiSetBlockXfer (0,glSpiPageSize);        //设置传输尺寸

            /// 这个子程序是允许DMA。两个参数一个是TX,一个是RX的个数
            status =CyU3PDmaChannelSetupRecvBuffer (&glSpiRxHandle,
                    &buf_p);
            if (status != CY_U3P_SUCCESS)
            {
                CyU3PSpiSetSsnLine (CyTrue);
                return status;
            }
            status =CyU3PDmaChannelWaitForCompletion (&glSpiRxHandle,
                    CY_FX_USB_SPI_TIMEOUT);
            if (status != CY_U3P_SUCCESS)
            {
                CyU3PSpiSetSsnLine (CyTrue);
                return status;
            }

            CyU3PSpiSetSsnLine (CyTrue);
            CyU3PSpiDisableBlockXfer (CyFalse,CyTrue);
        }
        else /* Write */
        {
            location[0] = 0x02; /* Writecommand */

            buf_p.size  = glSpiPageSize;
            buf_p.count = glSpiPageSize;

            status = CyFxSpiWaitForStatus ();
            if (status != CY_U3P_SUCCESS)
                return status;

            CyU3PSpiSetSsnLine (CyFalse);
            status = CyU3PSpiTransmitWords(location, 4);
            if (status != CY_U3P_SUCCESS)
            {
                CyU3PDebugPrint (2, "SPIWRITE command failed\r\n");
                CyU3PSpiSetSsnLine (CyTrue);
                return status;
            }

            CyU3PSpiSetBlockXfer(glSpiPageSize, 0);

            status =CyU3PDmaChannelSetupSendBuffer (&glSpiTxHandle,
                    &buf_p);
            if (status != CY_U3P_SUCCESS)
            {
                CyU3PSpiSetSsnLine (CyTrue);
                return status;
            }
            status =CyU3PDmaChannelWaitForCompletion(&glSpiTxHandle,
                    CY_FX_USB_SPI_TIMEOUT);
            if (status != CY_U3P_SUCCESS)
            {
                CyU3PSpiSetSsnLine (CyTrue);
                return status;
            }

            CyU3PSpiSetSsnLine (CyTrue);
            CyU3PSpiDisableBlockXfer (CyTrue,CyFalse);
        }

        /* Update the parameters */
        byteAddress  += glSpiPageSize;
        buf_p.buffer += glSpiPageSize;
        pageCount --;

        CyU3PThreadSleep (10);
    }
    return CY_U3P_SUCCESS;
}
在USB的SETUP中回调中( CyFxUSBSetupCB ),有两个参数,一个是setupdat0,一个是setupdat1.
这两个参数是类,VENDOR调用时的回调函数。
如果是请求ID号,则直接往EP0中写入一个字符串。
如果是请求FLASH写,则从EP0中得到相应的数组。后写到SPI中。
如果是请求读,则从SPI中读出指定长度的数,再送到EP0中去。
如果是请求擦除或点名。则如果点名,就送状态过去,如果是擦除,就送一个ACK包给USB即可。
那么就要了解一下类/VENDOR请求的格式是什么即可。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0