Cypress EZ-USB FX3 DMA模式下的串口通讯

  

  由于公司设备升级后出了问题,需要对USB驱动进行修改,原本使用的是寄存器模式进行UART传输,但是由于FX3寄存器模式会出现长时间延时等待的问题,不得不对其传输模式进行修改。虽然赛普拉斯的EZ-USB FX3系列芯片功能强大,成本适中,但共享资源太少,API参考手册里面的干货不多,直接导致开发困难,出现问题只能去官方社区寻找答案。新模式的开发也不是一帆风顺,找来找去,只有在固件库中找到了UartLpDmaMode这个例程还比较相似。于是便在其基础上进行修改。

  在UartLpDmaMode例程中,其数据流通方向是这样的:

  只是从将接收到的数据进行了循环发送,这样一来,其生产者和消费者ID便很好设置,但是你无法对DMA通道进行直接操作,换句话说,你无法发送你想要发送的数据,也无法将你接收到的数据存入自己开辟的缓冲区中进行存储使用,当然这样并不是我想要的。

  我想要操作的数据传输是能够实现想传什么传什么,接收到的数据能想什么时候用就可以什么时候用。其数据流通就如同下图:

但是,我在初期对FX3的DMA消费者生产者理解不深,一度认为这是不能实现的,但经过几天的社区询问以及个人摸索,发现可以这样使用!由于期间走了很多弯路,深知百度找不到任何有关赛普拉斯有用资料的苦衷,现在把这段代码分享出来。

开发环境:EZ-USB FX3 Development Kit SDK1.3.4

开发板型号:CYUSB3KIT-003(CYUSB3014)

开发目的:实现串口DMA模式的数据发送以及接收,能够随意发送自己缓冲区中的数据,接收到的数据能够储存在个人开辟的缓冲区中

  1 /*
  2  ## Cypress USB 3.0 Platform source file (cyfxuartlpdmamode.c)
  3  ## ===========================
  4  ##
  5  ##  Copyright Cypress Semiconductor Corporation, 2010-2018,
  6  ##  All Rights Reserved
  7  ##  UNPUBLISHED, LICENSED SOFTWARE.
  8  ##
  9  ##  CONFIDENTIAL AND PROPRIETARY INFORMATION
 10  ##  WHICH IS THE PROPERTY OF CYPRESS.
 11  ##
 12  ##  Use of this file is governed
 13  ##  by the license agreement included in the file
 14  ##
 15  ##     <install>/license/license.txt
 16  ##
 17  ##  where <install> is the Cypress software
 18  ##  installation root directory path.
 19  ##
 20  ## ===========================
 21 */
 22
 23 /* This file implements a simple UART (DMA mode) loopback application example */
 24
 25 /*此DEMO使用DMA模式,可以发送自己缓冲区中的数据,接收到数据后,可将接收到的数据存入全局变量glRxBuffer->buffer中。
 26  *注意:
 27  *    赛普拉斯FX3的DMA缓冲区大小最小是16个字节,缓冲区大小必须是16的倍数,也就是说,发送数据至少发送16个字节,发送的数据最大不能超过缓冲区的设定值,接收也一样,否则缓冲区未满,无法触发接收和发送!
 28  *如果与其他设备通讯,可以让其他设备强制发送16个字节的数据,自己取有效位使用。如果想一个字节一个字节的发送和接收,可以使用寄存器模式。
 29  */
 30
 31 #include <cyu3system.h>
 32 #include <cyu3os.h>
 33 #include <cyu3error.h>
 34 #include <cyu3uart.h>
 35
 36 #define CY_FX_UARTLP_THREAD_STACK       (0x0400)  /* UART application thread stack size */
 37 #define CY_FX_UARTLP_THREAD_PRIORITY    (8)       /* UART application thread priority */
 38 #define CY_FX_UART_DMA_TX_SIZE    (0)               /* DMA transfer size */
 39 #define CY_FX_UART_DMA_BUF_SIZE (16)              /* Buffer size */
 40
 41 CyU3PThread UartLpAppThread;                      /* UART Example application thread structure */
 42
 43 uint8_t testBuffer[16] = {0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0xff};
 44
 45 CyU3PDmaChannel glUartRXChHandle;
 46 CyU3PDmaChannel glUartTXChHandle;
 47 CyU3PDmaBuffer_t* glTxBuffer;
 48 CyU3PDmaBuffer_t* glRxBuffer;
 49 uint8_t ClearFlag = 0;
 50
 51 /* Application error handler */
 52 void
 53 CyFxAppErrorHandler (
 54         CyU3PReturnStatus_t apiRetStatus    /* API return status */
 55         )
 56 {
 57     /* Application failed with the error code apiRetStatus */
 58
 59     /* Add custom debug or recovery actions here */
 60
 61     /* Loop indefinitely */
 62     for (;;)
 63     {
 64         /* Thread sleep : 100 ms */
 65         CyU3PThreadSleep (100);
 66     }
 67 }
 68 /***********************************************************************************************
 69 *函数名 : SendData
 70 *函数功能描述 : 通过DMA模式 由串口发送数据
 71 *函数参数 : buffer-所需要发送的数据    len-发送数据的长度
 72 *函数返回值 : 无
 73 *注意:len最小为16
 74 ***********************************************************************************************/
 75 void SendData(uint8_t * buffer, unsigned int len)
 76 {
 77     CyU3PReturnStatus_t status;
 78     unsigned int i = 0;
 79     CyU3PDmaChannelGetBuffer(&glUartTXChHandle, glTxBuffer, 0);
 80     for(i = 0; i < len; i++)
 81     {
 82         glTxBuffer->buffer[i] = buffer[i];
 83     }
 84     CyU3PDmaChannelSetupSendBuffer(&glUartTXChHandle,glTxBuffer);
 85     status = CyU3PDmaChannelCommitBuffer(&glUartTXChHandle, 16, 0);
 86     if (status == CY_U3P_SUCCESS)
 87     {
 88
 89     }
 90 }
 91
 92 /***********************************************************************************************
 93 *函数名 : ReceivedDataCallBack
 94 *函数功能描述 : 接收缓冲区充满后的回调函数
 95 *函数参数 : chHandle-DMA通道的句柄    type-事件类型    input-输入
 96 *函数返回值 : 无
 97 *注意:形参已经被设置好,直接可以使用
 98 ***********************************************************************************************/
 99 void ReceivedDataCallBack(
100         CyU3PDmaChannel   *chHandle, /* Handle to the DMA channel. */
101         CyU3PDmaCbType_t  type,      /* Callback type.             */
102         CyU3PDmaCBInput_t *input)
103 {
104     CyU3PReturnStatus_t status;
105     if(type == CY_U3P_DMA_CB_PROD_EVENT)
106     {
107         //CyU3PDmaChannelSetWrapUp(&glUartRXChHandle);
108         status = CyU3PDmaChannelGetBuffer(&glUartRXChHandle, glRxBuffer, 0);
109         //测试用,将收到的信息在发送出去,此时测试为接收到16个字节的数据
110         SendData(glRxBuffer->buffer, 16);
111         //SendData(testBuffer, 16);
112         ClearFlag = 1;
113         if (status == CY_U3P_SUCCESS)
114         {
115             CyU3PDmaChannelDiscardBuffer(&glUartRXChHandle);
116         }
117     }
118 }
119
120 /* This function initializes the UART module */
121 void
122 CyFxUartDMAlnInit (void)
123 {
124     CyU3PUartConfig_t uartConfig;
125     CyU3PDmaChannelConfig_t dmaConfig;
126     CyU3PReturnStatus_t apiRetStatus = CY_U3P_SUCCESS;
127
128     //开启DCache后 一定设置为32,未开启最好也设置成32,但也可设置为16,不影响使用
129     glTxBuffer = (CyU3PDmaBuffer_t*)CyU3PDmaBufferAlloc (32);
130     glRxBuffer = (CyU3PDmaBuffer_t*)CyU3PDmaBufferAlloc (32);
131
132     /* Initialize the UART module */
133     apiRetStatus = CyU3PUartInit ();
134     if (apiRetStatus != CY_U3P_SUCCESS)
135     {
136         /* Error handling */
137         CyFxAppErrorHandler(apiRetStatus);
138     }
139
140     /* Configure the UART
141        Baudrate = 115200, One stop bit, No parity, Hardware flow control enabled.
142      */
143     CyU3PMemSet ((uint8_t *)&uartConfig, 0, sizeof(uartConfig));
144     uartConfig.baudRate = CY_U3P_UART_BAUDRATE_115200;
145     uartConfig.stopBit = CY_U3P_UART_ONE_STOP_BIT;
146     uartConfig.parity = CY_U3P_UART_NO_PARITY;
147     uartConfig.flowCtrl = CyFalse;             //一定不能为真
148     uartConfig.txEnable = CyTrue;
149     uartConfig.rxEnable = CyTrue;
150     uartConfig.isDma = CyTrue; /* DMA mode */
151
152     /* Set the UART configuration */
153     apiRetStatus = CyU3PUartSetConfig (&uartConfig, NULL);
154     if (apiRetStatus != CY_U3P_SUCCESS )
155     {
156         /* Error handling */
157         CyFxAppErrorHandler(apiRetStatus);
158     }
159
160     /* Create a DMA Manual channel between UART producer socket
161        and UART consumer socket */
162     CyU3PMemSet ((uint8_t *)&dmaConfig, 0, sizeof(dmaConfig));
163     dmaConfig.size = CY_FX_UART_DMA_BUF_SIZE;
164     dmaConfig.count = 1;
165     dmaConfig.prodSckId = CY_U3P_LPP_SOCKET_UART_PROD;   //生产者为RX
166     dmaConfig.consSckId = CY_U3P_CPU_SOCKET_CONS;        //消费者
167     dmaConfig.dmaMode = CY_U3P_DMA_MODE_BYTE;
168     dmaConfig.notification = CY_U3P_DMA_CB_PROD_EVENT;   //缓冲区充满产生的事件,此事件触发回调函数
169     dmaConfig.cb = ReceivedDataCallBack;
170     dmaConfig.prodHeader = 0;
171     dmaConfig.prodFooter = 0;
172     dmaConfig.consHeader = 0;
173     dmaConfig.prodAvailCount = 0;
174     /* Create the channel */
175     apiRetStatus = CyU3PDmaChannelCreate (&glUartRXChHandle,
176             CY_U3P_DMA_TYPE_MANUAL_IN, &dmaConfig);
177
178     if (apiRetStatus != CY_U3P_SUCCESS)
179     {
180         /* Error handling */
181         CyFxAppErrorHandler(apiRetStatus);
182     }
183
184     dmaConfig.size = CY_FX_UART_DMA_BUF_SIZE;
185     dmaConfig.count = 1;
186     dmaConfig.prodSckId = CY_U3P_CPU_SOCKET_PROD;               //生产者CPU
187     dmaConfig.consSckId = CY_U3P_LPP_SOCKET_UART_CONS;          //消费者为TX
188     dmaConfig.dmaMode = CY_U3P_DMA_MODE_BYTE;
189     dmaConfig.notification = 0;
190     dmaConfig.cb = NULL;
191     dmaConfig.prodHeader = 0;
192     dmaConfig.prodFooter = 0;
193     dmaConfig.consHeader = 0;
194     dmaConfig.prodAvailCount = 0;
195
196     /* Create the channel */
197     apiRetStatus = CyU3PDmaChannelCreate (&glUartTXChHandle,
198             CY_U3P_DMA_TYPE_MANUAL_OUT, &dmaConfig);
199
200     if (apiRetStatus != CY_U3P_SUCCESS)
201     {
202         /* Error handling */
203         CyFxAppErrorHandler(apiRetStatus);
204     }
205     /* Set UART Tx and Rx transfer Size to infinite */
206     apiRetStatus = CyU3PUartTxSetBlockXfer(0xFFFFFFFF);
207     if (apiRetStatus != CY_U3P_SUCCESS)
208     {
209         /* Error handling */
210         CyFxAppErrorHandler(apiRetStatus);
211     }
212
213     apiRetStatus = CyU3PUartRxSetBlockXfer(0xFFFFFFFF);
214     if (apiRetStatus != CY_U3P_SUCCESS)
215     {
216         /* Error handling */
217         CyFxAppErrorHandler(apiRetStatus);
218     }
219
220     /* Set DMA Channel transfer size */
221     apiRetStatus = CyU3PDmaChannelSetXfer (&glUartRXChHandle, 0);
222     if (apiRetStatus != CY_U3P_SUCCESS)
223     {
224             /* Error handling */
225         CyFxAppErrorHandler(apiRetStatus);
226     }
227
228     apiRetStatus = CyU3PDmaChannelSetXfer (&glUartTXChHandle, 0);
229     if (apiRetStatus != CY_U3P_SUCCESS)
230     {
231         /* Error handling */
232         CyFxAppErrorHandler(apiRetStatus);
233     }
234 }
235
236 /* Entry function for the UartLpAppThread */
237 void
238 UartLpAppThread_Entry (
239         uint32_t input)
240 {
241     /* Initialize the UART Example Application */
242     CyFxUartDMAlnInit();
243
244     //uint8_t testBuffer[8] = {0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8};
245     for (;;)
246     {
247
248         //if中的语句,是为了接收完毕后清除缓冲区,如果不清除缓冲区,如果所发数据超过缓冲区长度,第二次发送时会将上次未发送完的数据发送过来。
249         if(ClearFlag == 1)
250         {
251             //SendData(glRxBuffer->buffer, 16);
252             CyU3PDmaChannelReset(&glUartRXChHandle);
253             CyU3PThreadSleep(10);
254             CyU3PDmaChannelSetXfer(&glUartRXChHandle,0);
255             ClearFlag = 0;
256         }
257         /* No operation in the thread */
258         CyU3PThreadSleep (100);
259     }
260 }
261
262 /* Application define function which creates the threads. */
263 void
264 CyFxApplicationDefine (
265         void)
266 {
267     void *ptr = NULL;
268     uint32_t retThrdCreate = CY_U3P_SUCCESS;
269
270     /* Allocate the memory for the threads */
271     ptr = CyU3PMemAlloc (CY_FX_UARTLP_THREAD_STACK);
272
273     /* Create the thread for the application */
274     retThrdCreate = CyU3PThreadCreate (&UartLpAppThread,           /* UART Example App Thread structure */
275                           "21:UART_loopback_DMA_mode",             /* Thread ID and Thread name */
276                           UartLpAppThread_Entry,                   /* UART Example App Thread Entry function */
277                           0,                                       /* No input parameter to thread */
278                           ptr,                                     /* Pointer to the allocated thread stack */
279                           CY_FX_UARTLP_THREAD_STACK,               /* UART Example App Thread stack size */
280                           CY_FX_UARTLP_THREAD_PRIORITY,            /* UART Example App Thread priority */
281                           CY_FX_UARTLP_THREAD_PRIORITY,            /* UART Example App Thread priority */
282                           CYU3P_NO_TIME_SLICE,                     /* No time slice for the application thread */
283                           CYU3P_AUTO_START                         /* Start the Thread immediately */
284                           );
285
286     /* Check the return code */
287     if (retThrdCreate != 0)
288     {
289         /* Thread Creation failed with the error code retThrdCreate */
290
291         /* Add custom recovery or debug actions here */
292
293         /* Application cannot continue */
294         /* Loop indefinitely */
295         while(1);
296     }
297 }
298
299 /*
300  * Main function
301  */
302 int
303 main (void)
304 {
305     CyU3PIoMatrixConfig_t io_cfg;
306     CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
307
308     /* Initialize the device */
309     status = CyU3PDeviceInit (0);
310     if (status != CY_U3P_SUCCESS)
311     {
312         goto handle_fatal_error;
313     }
314
315     /* Initialize the caches. Enable both Instruction and Data Caches. */
316     status = CyU3PDeviceCacheControl (CyTrue, CyTrue, CyTrue);
317     if (status != CY_U3P_SUCCESS)
318     {
319         goto handle_fatal_error;
320     }
321
322     /* Configure the IO matrix for the device. On the FX3 DVK board, the COM port
323      * is connected to the IO(53:56). This means that either DQ32 mode should be
324      * selected or lppMode should be set to UART_ONLY. Here we are choosing
325      * UART_ONLY configuration. */
326     CyU3PMemSet ((uint8_t *)&io_cfg, 0, sizeof(io_cfg));
327     io_cfg.isDQ32Bit = CyFalse;
328     io_cfg.s0Mode = CY_U3P_SPORT_INACTIVE;
329     io_cfg.s1Mode = CY_U3P_SPORT_INACTIVE;
330     io_cfg.useUart   = CyTrue;
331     io_cfg.useI2C    = CyFalse;
332     io_cfg.useI2S    = CyFalse;
333     io_cfg.useSpi    = CyFalse;
334     io_cfg.lppMode   = CY_U3P_IO_MATRIX_LPP_UART_ONLY;
335     /* No GPIOs are enabled. */
336     io_cfg.gpioSimpleEn[0]  = 0;
337     io_cfg.gpioSimpleEn[1]  = 0;
338     io_cfg.gpioComplexEn[0] = 0;
339     io_cfg.gpioComplexEn[1] = 0;
340     status = CyU3PDeviceConfigureIOMatrix (&io_cfg);
341     if (status != CY_U3P_SUCCESS)
342     {
343         goto handle_fatal_error;
344     }
345
346     /* This is a non returnable call for initializing the RTOS kernel */
347     CyU3PKernelEntry ();
348
349     /* Dummy return to make the compiler happy */
350     return 0;
351
352 handle_fatal_error:
353     /* Cannot recover from this error. */
354     while (1);
355
356 }
357
358 /* [ ] */

实验效果:能够实现发送和接收,FX3将接收到的数据再发送给主机,如图:

将110行的 SendData(glRxBuffer->buffer, 16);改为111行的SendData(testBuffer, 16);能够实现,接收16位数据后,将testBuffer中的数据返回给主机,效果如图:

需要注意的是:DMA_BUFFER_SIZE的大小必须为16的倍数!!最小为16!!也就是说,一次至少需要发送或者接收16个字节的数据,或者说是将缓冲区填满的数据!!

原文地址:https://www.cnblogs.com/Lxk0825/p/9632830.html

时间: 2024-10-10 16:51:55

Cypress EZ-USB FX3 DMA模式下的串口通讯的相关文章

【转载】使用Win32API实现Windows下异步串口通讯

一,异步非阻塞串口通讯的优点 读写串行口时,既可以同步执行,也可以重叠(异步)执行.在同步执行时,函数直到操作完成后才返回.这意味着在同步执行时线程会被阻塞,从而导致效率下降.在重叠执行时,即使操作还未完成,调用的函数也会立即返回.费时的I/O操作在后台进行,这样线程就可以干别的事情.例如,线程可以在不同的句柄上同时执行I/O操作,甚至可以在同一句柄上同时进行读写操作."重叠"一词的含义就在于此. 二,异步非阻塞串口通讯的基本原理首先,确定要打开的串口名.波特率.奇偶校验方式.数据位.

CC2540 低功耗 POWER_SAVING 模式 下 串口 0 的使用

低功耗 模式 下 使用 串口 ,  因为 PM2 或者 PM3 状态下  32M晶振 是不工作 的,根据手册得知没有32M晶振, 串口是不能工作的,但是可以使用 外部中断,因此,我把  串口的接收引脚设置为外部中断,这样 来唤醒BLE. 这样就牵扯到 串口 和 外设中断  的 来回切换  ,具体操作方法如下: 协议栈版本: ble_sdk_1.4.2.2   simpleBLEPeripheral 1.   工程 配置 如下 INT_HEAP_LEN=3072 HALNODEBUG OSAL_C

电脑如何进入BIOS?在BIOS模式下USB的启动热键是什么?

组装机主板 品牌笔记本 品牌台式机 主板品牌 启动按键 笔记本品牌 启动按键 台式机品牌 启动按键 华硕主板 F8 联想笔记本 F12 联想台式机 F12 技嘉主板 F12 宏基笔记本 F12 惠普台式机 F12 微星主板 F11 华硕笔记本 ESC 宏基台式机 F12 映泰主板 F9 惠普笔记本 F9 戴尔台式机 ESC 梅捷主板 ESC或F12 联想Thinkpad F12 神舟台式机 F12 七彩虹主板 ESC或F11 戴尔笔记本 F12 华硕台式机 F8 华擎主板 F11 神舟笔记本 F

USB小白学习之路(9) CY7C68013A Slave FIFO模式下与FPGA通信

CY7C68013A Slave FIFO模式下与FPGA通信 CY7C68013A的时钟是由FPGA提供的24MHz,RESET引脚也是由FPGA控制. 1.开始时没有给FPGA烧录程序,将CY7C68013A接到PC上,安装驱动后,是检测不到device的,经查找,原因有两个: ①没有时钟,这种情况下需要先让FPGA跑起来,为CY7C68013A提供时钟 ②复位引脚没有控制,因为CY7C68013A的复位时低有效,如果FPGA的引脚不控制,就会使得此引脚电平不固定,CY7C68013A处于复

[Kali_USB Live模式下网卡加载安装问题]针对ASUS X202E笔记本配置的本地Broadcom43142无线网卡启动并显示wifi功能

Thank you "kali75" for your time.Although the links didn't work for me because the "link to the patch file" was dead.However after this I googled and have found the following solution working for me.I'm telling it here because if someo

android里面的USB功能-----Accessory模式

USB Accessory 原文链接地址  http://developer.android.com/intl/zh-cn/guide/topics/connectivity/usb/accessory.html#manifest USB附件模式允许用户连接 USB主机硬件专门为android设备. 配件必须遵循 Android附属协议中列出 Android配件开发工具包文档. 这允许android设备仍不能作为USB主机与USB接口进行交互 硬件. 当一个Android设备在USB附件模式中,

串口通讯(DMA模式)

在高级语言中,I/O 流输入(input)操作一般都要求指定要读取的数据的最大长度(字节数).当接收到至少1字节.最多所指定的字节数时,函数返回. STM32 串口接收数据时,HAL API 要求指定数据长度.但无论轮询.中断或是DMA方式,都必须完整地接收到这么多字节,程序流程才继续.如何接收变长消息,我想不到特别好的实现方式.一种方式是,轮询加超时.另一种方式是,设计消息协议,使消息头为定长,且消息头内包含消息体的长度.但是,如果通讯异常,导致消息数据错误或丢失,那么,还是缺少"提前返回&q

[PHP] swoole在daemonize模式下,chdir失效问题

swoole version: 1.9.6 其实跟swoole的版本无关,因为原代码体系,fpm模式下,在启动的时候,是使用 chdir 函数改变了当前目录的,而其它代码在做类的自动加载的时候,都是写的相对地址,而不是绝对地址. 问题就来了,swoole是多进程的,在daemonize模式下,chdir改变当前目录,在其它进程下是不生效的,所以有时候,不使用daemonize没问题,而使用daemonize会莫名的出现找不到类的情况. 解决方法是,在几个启动的回调里面同时也改变一下目录 $ser

Spark sql 在yarn-cluster模式下找不到表

在hive里建一个数据库test,在数据库里建了一张表user,然后在Spark程序中使用Spark sql读取这张表 "select * form test.user" 当部署模式是spark stand模式和yarn-client模式时,程序可以正常运行,但yarn-cluster模式就报了找不到"test.user"表的错误. 解决办法: spark和hive整合,把hive-site.xml加到spark根目录的conf下,所以,要在提交Spark任务的时候