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