1. 程式人生 > >CYPEESS USB3.0程式解讀之---SPI讀寫

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