• 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. ",

                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 ");

                    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 ");

                    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请求的格式是什么即可。

  • 相关阅读:
    CodeForces 1017B
    POJ 1323-Game Prediction(贪心)
    CodeForces 104B-Testing Pants for Sadness(思维题)
    CodeForces 1324D
    UVA 1152-4 Values whose Sum is 0(二分查找)
    POJ 1700-Crossing River(贪心)
    HDU 1789-Doing Homework again(并查集+贪心)
    SDUT 1298-活动选择(贪心)
    HDU 1272-小希的迷宫(带环并查集)
    CodeForces
  • 原文地址:https://www.cnblogs.com/Zoran-/p/5819294.html
Copyright © 2020-2023  润新知