搜索
bottom↓
回复: 35

[交流][拍砖]新版驱动接口风格调查(二):DMA

[复制链接]

出0入296汤圆

发表于 2013-11-6 18:07:28 | 显示全部楼层 |阅读模式
本帖最后由 Gorgon_Meducer 于 2013-11-13 17:37 编辑


说在前面的话

    感谢上次大家关于IO口配置的踊跃发言,使我们能够远离闭门造车和自我感觉良好的状态,如大家所见,现在两个帖子
都做了更新,根据大家的意见修正了风格。这次展示的是DMA的接口风格,希望大家踊跃拍砖。
   
   说起DMA,本质来说就是替代内核去完成 存储器之间,存储器与外设之间,外设与外设之间的数据搬运。这里面涉及到
地址的问题,数据大小的问题,大小端的问题,等等原本简单的工作一下就复杂起来了。我们试图在两个层面上提供一个比
较容易使用的接口:从灵活性上说,如果你是DMA的使用高手,那么我们的接口不应该限制你的发挥;如果你是DMA的普通
使用者,虽然不太熟悉,但是对这种“高上大”的“新事物”还是有几分向往的,我们希望为你们提供套餐式的服务,比如
后面例子展示的4种常见套餐:存储器到存储器,外设到存储器,存储器到外设和外设到外设。
   另外,得益于DMA的强大,它提供一种叫做链表的模式,就是DMA的传输控制是像普通节点一样保存在SRAM里的,这个
节点实际上是一个结构体,结构体有一个NEXT指针,也就是说DMA允许你把一系列想做的操作都通过这样一个链表记录下来
然后他会勤勤恳恳的替你一个一个的完成而基本不用干预——想到能做什么了吧?是的,DMA甚至可以帮你完成12864的数据
刷新,你只要在SRAM里面保存一个显存,然后你用链表描述好IO操作的过程,剩下就什么都不用管了,是不是很方便,很强
大?一般来说,普通外设的寄存器设置和数据搬运都不在话下。

   说了这么多,主要还是想让大家从如何简化DMA操作的接口出发来吐槽。来吧,让搬砖拍的更猛烈吧!



    这是新版本编码规范的一个范例代码,包含对应的驱动模型和接口规范,我希望在不提供进一步解说的情况下听听大家
的意见,并提供以下信息:
1、第一眼给你的感受,是喜欢 恐惧 还是 茫然无措
2、顺次阅读代码后,代码要表达的意思你是否已经了解大概,表意是否清晰
3、有什么你觉得疑惑的地方?
4、有什么改进意见?
5、任何批评意见都是非常欢迎的

如果可能,希望大家能在回帖中描述下你理解的代码的行为。

这个库的目标就是要让代码使用起来简单,不仅仅要屏蔽底层的寄存器操作,还要做到功能和意义一目了然
参与的人,即便自觉是菜鸟,也不用觉得自己水平不够之类的,因为你们就是最终的用户,你们是最有发言权的!
非常感谢大家的参与。


P.S: 这个库将是未来一个实质性的半导体产品的系统库。




范例一:Memory 到 Memory的数据搬运

  1.     static volatile uint8_t chSource[]  = {                 //!< 测试用的数据源 source data
  2.         MREPEAT(TEST_COUNT, SOURCE_DATA, 0)
  3.     };   
  4.     static volatile uint8_t chTarget[] = {                  //!< 测试用的目标地址 destination data
  5.         MREPEAT(TEST_COUNT, TARGET_DATA, 0)
  6.     };     
  7.             
  8.     DMA_CHN_CFG(
  9.         DMA_CHANNEL0,                                       //!< channel 0
  10.         
  11.         DMA_TSF_CFG(
  12.             DMA_MANUAL_TRIGGER_NEXT,                        //!< 手动触发 Manual Trigger next block
  13.             DMA_MODE_MEMORY_TO_MEMORY,                      //!< 使用Memory到Memory传输的模板 momory to momory mode
  14.             DMA_DATA_BITS_8,                                //!< 要传输数据的数据类型 data bits size

  15.             UBOUND(chSource),                               //!< 要传输多少个数据 data size
  16.             &chSource[0],                                   //!< 源数据地址 source address
  17.             &chTarget[0]                                    //!< 目标地址 destination address
  18.         ),
  19.     );

  20.     DMA0.Trigger(DMA_CHANNEL0_MASK);                        //!< 触发传输 set trigger

  21.     //! 等待传输完成
  22.     while (!DMA_IS_CHN_TSF_CPL(DMA_CHANNEL0));         
复制代码

范例二:外设  到 存储器 的数据搬运

  1.     static volatile uint32_t wTarget[TEST_COUNT];           //!< 目标缓冲区 destination data
  2.             
  3.     DMA_CHN_CFG(
  4.         DMA_CHANNEL1,                                       //!< channel 1
  5.         
  6.         DMA_TSF_CFG(
  7.             DMA_MANUAL_TRIGGER_NEXT,                        //!< 手动触发模式 Manual Trigger next block
  8.             DMA_MODE_PERIPHRAL_TO_MEMORY,                   //!< 使用从外设搬运数据到存储器的模板 peripheral to memory mode
  9.             DMA_DATA_BITS_32,                               //!< 数据类型 data bits size

  10.             TEST_COUNT,                                     //!< 要传输多少个数据 data size
  11.             &XXX_USART0.RBR_THR_DLL.RBR.Value,              //!< 源寄存器的地址 source address
  12.             &wTarget[0]                                     //!< 目标缓冲区的地址 destination address
  13.         ),
  14.     );

  15.     DMA0.Trigger(DMA_CHANNEL1_MASK);                        //!< set trigger
  16.     while (DMA0.GetChannelState(DMA_CHANNEL1, STATE_TIRG));
复制代码

范例五:单通道链表模式

  1. static volatile uint32_t wMemory0[] @0x20004200ul = {   //!< source of first
  2.         MREPEAT(TEST_COUNT, MEMORY0_DATA, 0)
  3.     };   
  4.     static volatile uint32_t wMemory1[] @0x20004300ul = {   //!< destination of first and source of second
  5.         MREPEAT(TEST_COUNT, MEMORY1_DATA, 0)
  6.     };     
  7.     static volatile uint32_t wMemory2[] @0x20004400ul = {   //!< destination of second
  8.         MREPEAT(TEST_COUNT, MEMORY2_DATA, 0)
  9.     };     
  10.             
  11.     DMA_CHN_CFG(
  12.         DMA_CHANNEL0,                                       //!< channel 0
  13.         
  14.         DMA_TSF_LIST(
  15.             TSF_ITEM (
  16.                 DMA_MODE_MEMORY_TO_MEMORY    |                  //!< memory to memory mode
  17.                 DMA_DATA_BITS_32,                               //!< data bits size

  18.                 TEST_COUNT,                                     //!< data size
  19.                 &wMemory0[0],                                   //!< source address
  20.                 &wMemory1[0]                                    //!< destination address
  21.             ),
  22.         
  23.             TSF_ITEM (
  24.                 DMA_MODE_MEMORY_TO_PERIPHRAL    |               //!< memory to peripheral mode
  25.                 DMA_DATA_BITS_32,                               //!< data bits size
  26.                 TEST_COUNT,                                     //!< data size
  27.                 &wMemory1[0],                                   //!< source address        
  28.                 &GSP_USART0.RBR_THR_DLL.THR.Value               //!< destination address
  29.             ),
  30.         
  31.             TSF_ITEM (
  32.                 DMA_MODE_PERIPHRAL_TO_PERIPHRAL    |            //!< peripheral to peripheral mode
  33.                 DMA_DATA_BITS_32,                               //!< data bits size
  34.                 TEST_COUNT,                                     //!< data size
  35.                 &GSP_USART1.RBR_THR_DLL.RBR.Value,              //!< source address        
  36.                 &GSP_USART1.RBR_THR_DLL.THR.Value               //!< destination address
  37.             ),        
  38.         
  39.             TSF_ITEM (
  40.                 DMA_MANUAL_TRIGGER_NEXT    |                    //!< Manual Trigger next block
  41.                 DMA_MODE_PERIPHRAL_TO_MEMORY    |               //!< peripheral to memory mode
  42.                 DMA_DATA_BITS_32,                               //!< data bits size
  43.                 TEST_COUNT,                                     //!< data size
  44.                 &GSP_USART0.RBR_THR_DLL.RBR.Value,              //!< source address        
  45.                 &wMemory2[0]                                    //!< destination address
  46.             )   
  47.         )
  48.       
  49.     );

  50.     DMA0.Trigger(DMA_CHANNEL0_MASK);                        //!< set trigger
  51.     delay(0x120);                                           //!< wait usart0 send complete
  52.     DMA0.Trigger(DMA_CHANNEL0_MASK);                        //!< set trigger
  53.     delay(0x120);                                           //!< wait usart1 send complete
  54.     DMA0.Trigger(DMA_CHANNEL0_MASK);                        //!< set trigger
复制代码

出0入296汤圆

 楼主| 发表于 2013-11-6 18:08:59 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2013-12-31 11:17 编辑


Sensor Hub 硬件触发的例子

应用场景描述
    我们来用DMA配合信号系统来构建一个芯片梦游的例子。是的,梦游,整个过程中,CPU都处于休眠状态。
应用是这个样子的:
    a. CPU完成最初DMA和信号网络的配置以后就进入休眠模式并不再唤醒。
    b. 假设外部有一个传感器,该传感器通过SPI从机模式与芯片通信,当传感器完成数据采样后,会拉高信号
        线EXT_REQ(熟悉手机内部应用的人都很清楚这种结构,一般也把这根信号叫做中断信号) 。
    c. 芯片在EXT_REQ的上升沿回复系统时钟,但并不唤醒内核,随后该信号触发DMA完成一次数据传送,
        用以开启SPI的时钟。
    d. 当SPI时钟开启后,由于发送缓冲中(TX_FIFO)预先填充了7个字节的数据,通信立即开始。
    e. 在SPI通信的过程中,由于接受缓冲不为空,RX_FIFO_DAVL(RX FIFO Data Available)信号为高,该
        信号持续触发DMA及时的将SPI接受缓冲中的数据搬运到指定的SRAM缓冲区内
    f. 当SPI通信结束后,帧结束信号FRM_EXCHANGE将触发 DMA将 SPI的时钟关闭,并在关闭时钟后,预先
       填充下一次通讯所需的7个字节的数据到SPI的发送缓冲中。由于SPI时钟已经关闭,FIFO仍然能操作,
       但是数据却要等到下一次时钟恢复时才能发送了。
    g. 当所有外设完成工作后,系统重新进入休眠模式。

    可以看到,整个过程中内核并未参与。如果不需要数据处理,芯片只是采集传感器信息,集中后,以固定
的频率(比如100Hz)发送给主控芯片,那么仍然不需要涉及到内核。如果需要简单的数据处理,那么内核
可以在必要的时候唤醒,快速完成功能后重新进入休眠。这种思想,就是我在另外一个帖子里面提到的脉冲
工作模式。





  1. void dma_cfg(void)
  2. {
  3.     static uint32_t wSrc0 @0x20008004 = 0;
  4.     static uint32_t wSrc1 @0x20008008 = 1;
  5.     static uint32_t wOutputBuffer[8]    @0x2000800C = {0xAC,0,1,2,3,4,5};
  6.     static uint32_t wInputBuffer[8]     @0x20008104 ;

  7.     //!< init dma
  8.     DMA_CHN_CFG(
  9.         DMA_CHANNEL0,                                           //!< channel0                       
  10.         DMA_CHN_TRIG_RISING_EDGE_SENSITIVE  ,

  11.         //!  Open SPI0 P_CLK
  12.         DMA_TSF_CFG(
  13.             DMA_TSF_MODE_MEMORY_TO_PERIPHRAL    |
  14.             DMA_TSF_MANUAL_TRIGGER_NEXT         |
  15.             DMA_TSF_DATA_BITS_32                ,
  16.             1                                   ,
  17.             &wSrc1                              ,
  18.             &GSP_CMC.PCLKDIV[PCLK_SPI0].Value
  19.         ),
  20.     );      

  21.    
  22.     DMA_CHN_CFG(
  23.         DMA_CHANNEL1,                                           //!< channel1           
  24.         DMA_CHN_TRIG_RISING_EDGE_SENSITIVE      |
  25.         DMA_CHN_BURST_TRANSFER                  |
  26.         DMA_CHN_BURST_SIZE_1                    ,

  27.         //! read spi data CMD(Ignored) + 6 Bytes
  28.         DMA_TSF_CFG(
  29.             DMA_TSF_MODE_PERIPHRAL_TO_MEMORY    |
  30.             DMA_TSF_MANUAL_TRIGGER_NEXT         |
  31.             DMA_TSF_DATA_BITS_32                ,
  32.             7                                   ,
  33.             &GSP_SPI0.DR.Value                  ,
  34.             wInputBuffer
  35.         ),
  36.     );


  37.     //!< init dma
  38.     DMA_CHN_CFG(
  39.         DMA_CHANNEL2,                                           //!< channel2                          
  40.         DMA_CHN_TRIG_RISING_EDGE_SENSITIVE      ,

  41.         //! disable SPI P_CLK
  42.         DMA_TSF_CFG(
  43.             DMA_TSF_MODE_MEMORY_TO_PERIPHRAL    |
  44.             DMA_TSF_AUTO_TRIGGER_NEXT           |
  45.             DMA_TSF_DATA_BITS_32                ,
  46.             1                                   ,
  47.             &wSrc0                              ,
  48.             &GSP_CMC.PCLKDIV[PCLK_SPI0].Value
  49.         ),  

  50.         //! fill spi fifo with CMD + 6 Bytes(Dummy write for spi read)
  51.         DMA_TSF_CFG(
  52.             DMA_TSF_MODE_MEMORY_TO_PERIPHRAL    |
  53.             DMA_TSF_MANUAL_TRIGGER_NEXT         |
  54.             DMA_TSF_DATA_BITS_32                ,
  55.             7                                   ,
  56.             wOutputBuffer                       ,
  57.             &GSP_SPI0.DR.Value
  58.         ),
  59.     );
  60. }

  61. void spi_dma_test_init(void)
  62. {
  63.     ...

  64.     // enable dma
  65.     PM_AHB_CLK_ENABLE(AHBCLK_DMA);

  66.     IO_CFG(
  67.         {PA7, IO_WORKS_AS_APIO0,        IO_PULL_UP},
  68.         {PA1, IO_WORKS_AS_SPI0_SCK,     IO_PULL_UP},
  69.         {PA2, IO_WORKS_AS_SPI0_MISO,    IO_PULL_UP},
  70.         {PA3, IO_WORKS_AS_SPI0_MOSI,    IO_PULL_UP},
  71.         {PA4, IO_WORKS_AS_SPI0_CS,      IO_PULL_UP},
  72.     );
  73.      
  74.     SPI_CFG(
  75.         SPI0,
  76.         SPI_MODE_MASTER             |
  77.         SPI_MODE_FORMAT_SPI         |
  78.         SPI_MODE_CLK_IDLE_LOW       |
  79.         SPI_MODE_SAMP_SECOND_EDGE,
  80.         SPI_MODE_DATASIZE_8,
  81.         SPI_PCLK_DIV_1
  82.     );
  83.     SPI0.Open();                        //!< enable spi0
  84.     PM_PCLK_SET(PCLK_SPI0,0);           //!< disable P_CLK for SPI manually
  85.    
  86.     //! fill spi fifo with CMD + 6 Bytes(Dummy write for spi read)
  87.     SPI0.Write(0xAC);
  88.     SPI0.Write(0x00);
  89.     SPI0.Write(0x01);
  90.     SPI0.Write(0x02);
  91.     SPI0.Write(0x03);
  92.     SPI0.Write(0x04);
  93.     SPI0.Write(0x05);
  94.    
  95.     //! signal connection
  96.     SIGNAL_CFG(
  97.     /*----------------------------------------------------------------------------------------------*
  98.      *    SIGNAL    Source Signal           Usage                   Digtal Filter                   *
  99.      *----------------------------------------------------------------------------------------------*/

  100.         /*! \note Use the raising edge of APIO0 to trigger DMA Channel0, the APIO0 is connected to
  101.          *        PA7 in IO_CFG(). It is the trigger signal called EXT_REQ in the wave form.  
  102.          */
  103.         { SIGNAL0,  USE_SIGNAL_APIO0,       TO_TRIGGER_DMA0_CHN0,   ON_RAISING_EDGE                 },

  104.         /*! \note When there are any data available in SPI0 RX FIFO (signal gose high), general pulse
  105.          *        to trigger DMA channel2 to fetch data from spi. Here EVERY_5_TIMES is the pulses
  106.          *        prescaler, which means the pulse frequency is the 1/5 of the system clock.
  107.          */
  108.         { SIGNAL1,  USE_SPI0_RX_FIFO_DAVL,  TO_TRIGGER_DMA0_CHN1,   ON_HIGH_LEVEL | EVERY_5_TIMES   },

  109.         /*! \note When SPI Frame complete, trigger the dma channel3 transfer
  110.          */
  111.         { SIGNAL2,  USE_SPI0_FRM_EXCHANGED, TO_TRIGGER_DMA0_CHN2,                                   },
  112.     );
  113.    
  114.     //! configure DMA
  115.     dma_cfg();

  116.     //! fall in sleep and NEVER wake up.
  117.     PM_SLEEP(DEEP_SLEEP);
  118. }

复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-11-6 18:10:30 | 显示全部楼层
先顶一下。。。。

出0入0汤圆

发表于 2013-11-7 13:51:53 | 显示全部楼层
DMA_CHN_CFG(
        ......
        DMA_TSF_CFG(
                ......
        ),
);

那个拖尾的逗号是必须的吗?
如果不是,我觉得应该去掉。
“如果在其他由逗号分隔的列表(如枚举声明、单行多变量声明等)中也允许使用,那还说得过去,可惜事实并非如此。”

出0入296汤圆

 楼主| 发表于 2013-11-7 16:38:03 | 显示全部楼层
catwill 发表于 2013-11-7 13:51
DMA_CHN_CFG(
        ......
        DMA_TSF_CFG(

这不是多余的……因为在链表模式下……允许有多个Transfer,也就是多个DMA_TSF_CFG,不过删除也可以的

出0入296汤圆

 楼主| 发表于 2013-11-7 17:11:40 | 显示全部楼层
更新了链式传输——使用单通道完成四次不同类型的传输,传输之间既有自动切换,也有手动触发切换
这里,需要手动触发的地方,可以是硬件触发,也可以是例子中的软件触发。

出0入0汤圆

发表于 2013-11-7 17:50:47 | 显示全部楼层
小白求指点:

1:看不懂下面的含义 Memory repeat 函数,后两个参数是神马意思?
   MREPEAT(TEST_COUNT, SOURCE_DATA, 0)
2:DMA_CHN_CFG 里面为什么包含DMA_TSF_CFG函数?分成两个不好?
3:UBOUND(chSource),是神马意思
4:DMA_IS_CHN_TSF_CPL名字有待考究 CPL complete
5:DMA_MANUAL_TRIGGER_NEXT, 建议去掉NEXT,多余
6:最后一个链表的例子有意思,想知道DMA_CHN_CFG的实现方式,可变宏?
7:CHANNEL_BLOCK0_ADDR, 啥意思?

出0入0汤圆

发表于 2013-11-7 18:14:59 | 显示全部楼层
版主你好 yg?

出0入4汤圆

发表于 2013-11-7 18:56:58 | 显示全部楼层
还是不习惯太多的大写  

出0入8汤圆

发表于 2013-11-7 20:42:50 来自手机 | 显示全部楼层
不明觉厉

出0入0汤圆

发表于 2013-11-7 21:27:50 | 显示全部楼层
顶个帖。

出0入0汤圆

发表于 2013-11-8 11:49:13 | 显示全部楼层
MREPEAT(TEST_COUNT, SOURCE_DATA, 0)是啥东东,函数么?怎么后面又没有分号呢?看着很蛋疼

出0入0汤圆

发表于 2013-11-8 12:04:16 | 显示全部楼层
说好的展开风格呢?

出0入0汤圆

发表于 2013-11-8 12:15:58 | 显示全部楼层
帮顶……

出0入296汤圆

 楼主| 发表于 2013-11-8 22:22:20 | 显示全部楼层
STM32_Study 发表于 2013-11-8 12:04
说好的展开风格呢?

DMA太复杂了,展开会死人的……真的……相信我……

出0入296汤圆

 楼主| 发表于 2013-11-8 22:22:59 | 显示全部楼层
sbk100 发表于 2013-11-8 11:49
MREPEAT(TEST_COUNT, SOURCE_DATA, 0)是啥东东,函数么?怎么后面又没有分号呢?看着很蛋疼 ...

这个其实无关紧要……只是用来做数据填充的,真不是这个例子的一部分……

出0入0汤圆

发表于 2013-11-8 23:33:32 | 显示全部楼层
内部的宏不知道什么意思。
依楼主上一个模版来看,上面的几个例子,应该是主程序把。
说实话我还是比较喜欢一条一条的配置外设,这样封装的太厉害,有点摸不着北。

出0入296汤圆

 楼主| 发表于 2013-11-9 09:37:47 | 显示全部楼层
meirenai 发表于 2013-11-8 23:33
内部的宏不知道什么意思。
依楼主上一个模版来看,上面的几个例子,应该是主程序把。
说实话我还是比较喜欢 ...

作为一种讨论,你是不是平时不太喜欢使用黑盒子呢?

出0入0汤圆

发表于 2013-11-9 14:54:05 | 显示全部楼层
学习一下

出0入0汤圆

发表于 2013-11-12 21:26:54 | 显示全部楼层
忍不住吐个槽

现在的经济环境真的已经差到这种程度了么?还是说现在的人心已经浮躁到没人愿意搞技术的程度了?

傻孩子才刚发出来的技术帖,竟然3天没有人回复、竟然6天里只有不到20个回复,不可思议。

出0入296汤圆

 楼主| 发表于 2013-11-13 09:54:54 | 显示全部楼层
eduhf_123 发表于 2013-11-12 21:26
忍不住吐个槽

现在的经济环境真的已经差到这种程度了么?还是说现在的人心已经浮躁到没人愿意搞技术的程度 ...

只能说用DMA的环境和场合不多,大家也就凑合着搬运版运数据而已。过几天我放出来中断系统的接口,
一定砖头多的能盖房子了。

出0入0汤圆

发表于 2013-11-13 11:20:25 | 显示全部楼层
这个结构体定义的有点太偏底层了,可能和DMA的设计是一一对应的(看到你的定义,我就想起了DMA的实现);
建议封装的靠上层一点(个人感觉,就是软件使用者不太需要了解太多的底层);

另外,增加异步回调机制是不是会好点;这样在发出DMA后,不需要那个WHILE了;

可以简化单次和链表,统一一种模式(越简单越好),功能都是可以实现的;

出0入296汤圆

 楼主| 发表于 2013-11-13 12:10:35 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2013-11-13 12:13 编辑
jm2011 发表于 2013-11-13 11:20
这个结构体定义的有点太偏底层了,可能和DMA的设计是一一对应的(看到你的定义,我就想起了DMA的实现);
建 ...


其实这个已经比较高层了,更底层的部分已经屏蔽了。回调机制其实是有的,是基于硬件中断的,
由于中断系统的架构还在改进,所以暂时只能使用查询来展示接口。

另外,你仔细看,单次和链表实际上是一样的啊,DMA_TSF_CFG() 块只有一个,就是单次的,
有多个就是链表。

关于你说的希望更高层一点,能否给出一点例子呢?

出0入0汤圆

发表于 2013-11-13 13:32:29 | 显示全部楼层
恩,个人考虑,可以给当前的通道单独提炼一个cfg的函数,来设置一些公共的属性;
像参数DMA_MANUAL_TRIGGER_NEXT, DMA_MODE_PERIPHRAL_TO_MEMORY等用户不用知道这些,这些在内部自己处理;
参数DMA_DATA_BITS_32也不用每次都设置,直接设置当前channel一次就可以;

另外就是关于LIST的最好再细化一下,可以细化为:Element 和 List结构;
如果是当前DMA就一次那么就只有一个Element,多个块就有多个Element;
至于上面的一些DMA的参数,放在另外的结构体里保存;

这样比较符合程序员的思维,一人之言,如有不周,敬请谅解:)

出0入296汤圆

 楼主| 发表于 2013-11-13 17:15:24 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2013-11-13 17:39 编辑
jm2011 发表于 2013-11-13 13:32
恩,个人考虑,可以给当前的通道单独提炼一个cfg的函数,来设置一些公共的属性;
像参数DMA_MANUAL_TRIGGER ...



恩,个人考虑,可以给当前的通道单独提炼一个cfg的函数,来设置一些公共的属性;

答:如果单独提炼一个CFG函数,会破坏一致性,而且实际上,对一个通道来说,其实没有公共属性。


像参数DMA_MANUAL_TRIGGER_NEXT, DMA_MODE_PERIPHRAL_TO_MEMORY等用户不用知道这些,这些在内部自己处理;

DMA_MANUAL_TRIGGER_NEXT, DMA_MODE_PERIPHRAL_TO_MEMORY 这些是用户必须指定的信息,对驱动来说,这些信息
是无法确定的,必须要用户指定,其实类似 DMA_MODE_PERIPHRAL_TO_MEMORY 这样的宏,已经是进行封装以后的结果了,
它规定了数据传输时候源地址和目标地址的指针处理方式(是否自动加,加多少之类的),对于这种已经可以确定的逻辑,我们
是可以封装成模板的(DMA_MODE_PERIPHRAL_TO_MEMORY就是模板),但是对于只有用户知道的信息,而驱动无法确定的
信息,我们是无法进行信息封装的。


参数DMA_DATA_BITS_32也不用每次都设置,直接设置当前channel一次就可以;

DMA_DATA_BITS_32 不是公共信息,因为每次传输的数据类型都不同,如果非要实现你说的这种功能,恐怕只有使用C++这种
天然支持类的语言,通过基类的方式来实现了。你说的很有道理,但目前用的是C语言,要实现这个功能,同事又不增加太多代码
的复杂度,难度有点大,不过既然需求提出来了,我会认真考虑实现方式的。


另外就是关于LIST的最好再细化一下,可以细化为:Element 和 List结构;
如果是当前DMA就一次那么就只有一个Element,多个块就有多个Element;
至于上面的一些DMA的参数,放在另外的结构体里保存;

这个是可以修改的,目前实际上DMA_TSF_CFG就是一个Element,但即便这么做了未必讨好,因为很多嵌入式开发人员并不熟悉
这种链表结构,对他们来说Transfer也许更直接一点,这一点我再仔细考虑下。


这样比较符合程序员的思维,一人之言,如有不周,敬请谅解:)

非常感谢你的反馈,我希望针对我的回复,我们能有更多的讨论。请看看新的Chain List风格如何?





我们现在尝试减少参数的数量,并把每一次传输触发下一次传输的方式的设定改为默认是自动的,可以通过特殊指定的方式将其
改为手动。过一会儿将更新新的接口。


出0入0汤圆

发表于 2013-11-13 17:29:00 | 显示全部楼层
我觉得一个东西最难的地方,就是用自己的表达方式来完全描述它,最起码,这点,我要向楼主学习,DMA既然高级,难学,但更应该去掌握,顶楼主!

出0入0汤圆

发表于 2013-11-15 14:55:01 | 显示全部楼层
Robin_King 发表于 2013-11-6 18:10
先顶一下。。。。

这位的头像要不要这么销魂啊

出0入0汤圆

发表于 2013-11-29 11:49:04 | 显示全部楼层
mark

出0入0汤圆

发表于 2013-12-18 10:23:34 | 显示全部楼层
正在mark中。。。。。

出0入0汤圆

发表于 2013-12-18 10:24:05 | 显示全部楼层
楼主能否给点完整的代码,我等入门的人可以先在系统上跑起来

出0入296汤圆

 楼主| 发表于 2013-12-18 10:32:19 | 显示全部楼层
wazhiyi 发表于 2013-12-18 10:24
楼主能否给点完整的代码,我等入门的人可以先在系统上跑起来


这目前只是风格调查,还没有办法针对其它家芯片做出驱动。以后我们的开源团队会尝试补对其他它家的芯片支持。
另外,对目前的DMA接口风格,有什么看法么?随便说说都没关系。

出0入0汤圆

发表于 2013-12-18 10:51:38 | 显示全部楼层
Gorgon_Meducer 发表于 2013-12-18 10:32
这目前只是风格调查,还没有办法针对其它家芯片做出驱动。以后我们的开源团队会尝试补对其他它家的芯片支 ...

我想现在我的STM32系统上跑起来在看看有没有不妥的地方,光看代码,好抽象,可能太菜了

出0入296汤圆

 楼主| 发表于 2013-12-18 12:15:25 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2013-12-18 16:44 编辑
wazhiyi 发表于 2013-12-18 10:51
我想现在我的STM32系统上跑起来在看看有没有不妥的地方,光看代码,好抽象,可能太菜了 ...


目前还不支持STM32,主要看DMA的特性,不一定能封装出相同的功能,可能更强,也可能更弱。这里只是从
接口的角度来征求风格以及使用便利性上的意见。

出0入296汤圆

 楼主| 发表于 2013-12-31 11:17:58 | 显示全部楼层
在二楼更新使用DMA配合信号网络系统通过梦游模式实现传感器数据读取的例子。

出0入0汤圆

发表于 2014-7-21 22:23:59 | 显示全部楼层
个人喜欢把左括号另起一行,呵呵,各人风格不一样的啦

出0入0汤圆

发表于 2015-5-5 22:37:37 | 显示全部楼层
自己太菜了,有点看不懂啊!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 00:32

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表