Gorgon_Meducer 发表于 2013-11-16 10:52:26

[交流][拍砖]新版驱动接口风格调查(三):信号系统

本帖最后由 Gorgon_Meducer 于 2014-5-20 16:16 编辑

说在前面的话
这次是关于中断系统的接口……默默等待房产……

解释下:现在的格式是这样的,
SIGNAL_CFG(
    SINGLE(<中断向量:SIGNAL0..SIGNAL31>, <信号源:手动信号 / 外设信号>, <信号用途:触发中断 / 触发外设功能>,
   <信号源的检测方式:上升沿,下降沿,双边沿,高电平,低电平,每xx次才触发一次>|<是否产生中断,其它属性>),
    ...
)
我关心的是对用户来说,这种方式是否灵活,易用。
比如,你可以吐槽我的例子比较渣,但是你立即就知道,并且有自己的欲望去实现一个自己的例子,关键就是你立即就知道如何自己去做



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

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

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


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



范例一:USART数据接收完成中断

    SIGNAL_CFG(
      //! 一旦USART0的接收缓冲区中有数据(Data Available),就产生中断,并复位TIMER0
      SINGLE( SIGNAL0, USE_SIGNAL_USART0_RX_FIFO_DAVL, TO_TRIGGER(INTERRUPT_REQUEST , TIMER0_RESET), EVERY_TIME ),

      //! 如果很久没有发生USART0的接收事件,导致TIMER0溢出了,就认为发生了接收超时,触发中断处理程序
      SINGLE( SIGNAL1, USE_SIGNAL_TIMER0_OVF, TO_TRIGGER(INTERRUPT_REQUEST), EVERY_TIME),
    );

    ISR(SIGNAL0_vect)
    {
      //! Signal0 的中断处理程序,当USART的接收缓冲区中存在数据时,该中断被触发
    }

    ISR(SIGNAL1_vect)
    {
      //! Signal1 的中断处理程序, 定时器0的溢出事件触发,表示USART通信超时,用TIMER0的TOP值设置超时范围
    }

范例二:用DMA从USART接收数据
这是直接用DMA的例子,当USART0的缓冲区中有数据可用的时候,自动触发DMA进行搬运

#define USART0_RX_BUFFER_SIZE         256

static uint8_t s_chUSARTBuffer;

static void start_usart_dma_transfer(void)
{
    DMA_CHN_CFG(
      DMA_CHANNEL0,                           //!< 使用DMA的通道0
      DMA_CHN_BURST_TRANSFER |                //!< 分多次完成数据传输
      DMA_CHN_BURST_SIZE_1,                   //!< 每次传输一个数据(数据类型由DMA_TSF_CFG指定)
      
      //! 配置一次传输
      DMA_TSF_CFG (
            DMA_TSF_MODE_PERIPHRAL_TO_MEMORY,   //!< 从外设到内存的搬运方式
            DMA_TSF_DATA_BITS_BYTE,             //!< 每次搬运的数据类型是字节         
            &GSP_USART0.RBR_THR_DLL.RBR.Value,//!< 源地址
            s_chUSARTBuffer                     //!< 目标地址
      )
    );
}

void app_init(void)
{
    ...
    SIGNAL_CFG(
      //! 一旦USART0的接收缓冲区中有数据(Data Available),就触发DMA通道0从USART版运数据
      SINGLE( SIGNAL0, USE_SIGNAL_USART0_RX_FIFO_DAVL, TO_TRIGGER(DMA0_CHN0_TSF), EVERY_TIME ),

      //! 当DMA完成指定数量数据的搬运后,触发中断,由中断来配置下一次的DMA
      SINGLE( SIGNAL1, USE_DMA_CHN0_FINAL_TSF, TO_TRIGGER(INTERRUPT_REQUEST), EVERY_TIME),
    );

    //! 配置USART0
    USART_CFG(
      USART0,
      USART_8_BIT_LENGTH|       //!< 8数据位
      USART_1_STOPBIT   |       //!< 1停止位
      USART_NO_PARITY,            //!< 无校验
      9600                        //!< 9600波特率
    );

    //! 配置DMA进行USART的数据传输
    start_usart_dma_transfer();
    ...
}

ISR(SIGNAL1_vect)
{
    //! 配置下一次DMA传输
    start_usart_dma_transfer();
}

范例三:外中断

    SELECT_PIN_SIGNAL_SOURCE(PIN_CHN0, PA6);
    SELECT_PIN_SIGNAL_SOURCE(PIN_CHN1, PA7);
    SELECT_PORT_GROUP_SIGNAL_SOURCE(PORT_GROUP_CHN0, PB0_MSK | PB1_MSK | PB2_MSK | PB3_MSK)

    SIGNAL_CFG(
      //! 在PA6的第61个上升沿产生一个中断
      SINGLE(SIGNAL0, USE_SIGNAL_PIN_CHN0, TO_TRIGGER(INTERRUPT_REQUEST), ON_RAISING_EDGE | EVERY_61_TIME),

      //! 在PA7每保持低电平32个系统周期,产生一个中断
      SINGLE(SIGNAL1, USE_SIGNAL_PIN_CHN1, TO_TRIGGER(INTERRUPT_REQUEST), ON_LOW_LEVEL | EVERY_32_TIME),

      //! PB0, PB1, PB2, PB3 任何一个引脚的双边沿产生一个中断
      SINGLE(SIGNAL2, USE_SIGNAL_PORT_GROUP_CHN0, TO_TRIGGER(INTERRUPT_REQUEST), ON_BOTH_EDGE},
    )

    ISR(SIGNAL0_vect)
    {
      //! Signal0 的中断处理程序,
    }

    ISR(SIGNAL1_vect)
    {
      //! Signal1 的中断处理程序,
    }

    ISR(SIGNAL2_vect)
    {
      //! Signal2 的中断处理程序,
    }

Gorgon_Meducer 发表于 2013-11-16 10:58:49

占位……

whatcanitbe 发表于 2013-11-16 12:40:55

最近也想做个类似的系统,正好看看中断怎么封装

dxf5200 发表于 2013-11-16 13:00:26

学习一下      

zhexuejia 发表于 2013-11-16 13:47:57

为什么手机神马代码也看不到

y574924080 发表于 2013-11-16 18:11:20

zhexuejia 发表于 2013-11-16 13:47 static/image/common/back.gif
为什么手机神马代码也看不到

切换到电脑版就可以看到了

hqgboy 发表于 2013-11-16 18:30:56

这样写,能看懂。
只要所有库的书写和变量命名保持一致就可以。

sbk100 发表于 2013-11-16 22:41:17

SIGNAL_CFG(
      //! 使用USART0接收完成事件产生中断,因为USART有16字节的FIFO,所以我们配置该事件每8次才触发一次中断
      { SIGNAL0, USE_USART0_RX_CPL, TO_GENERATE_INTERRUPT, EVERY_8_TIMES, ENABLE_INTERRUPT },

      //! 用USART0接收完成事件来复位定时器到0
      { SIGNAL1, USE_USART0_RX_CPL, TO_TRIGGER_TIMER0_RESET},

      //! 用定时器0的溢出事件来产生中断,这个中断实际上表示很久没有发生通信了,是一个通信超时中断
      { SIGNAL2, USE_TIMER0_OVF, TO_GENERATE_INTERRUPT, EVERY_TIME, ENABLE_INTERRUPT},
    )
----------------------------------------------------------------------------------------------------------------------------------------------------
这一段看不懂;
不知道信号和中断有啥关系,中断不是硬件本身的属性吗?中断向量在单片机的地址也都是固定的吧?信号是楼主自定义的数据结构吧?这两个有必然的联系吗?

    ISR(SIGNAL0)
    {
      //! Signal0 的中断处理程序,每8个USART0接收完成事件触发一次
    }
----------------------------------------------------------------------------------------------------------------------------------------------------
这个如果是中断处理程序我觉得并不够明确,如果不看前面一段,只看通过括号里的SIGNAL0并不能知道是啥中断,还要考函数里的注释才能知道,还不如用一个有意义的函数名表示来的清晰,我是菜鸟,理解的比较浅,吐槽完毕。另外第21行是不是应该改成Signal2?

Gorgon_Meducer 发表于 2013-11-16 23:00:25

sbk100 发表于 2013-11-16 22:41 static/image/common/back.gif
SIGNAL_CFG(
      //! 使用USART0接收完成事件产生中断,因为USART有16字节的FIFO,所以我们配置该事件 ...

SIGNAL不是一个数据结构,是一个硬件概念,SIGNAL可以用来产生中断,也可以用来直接触发
外设的动作而不经过内核的干预。我的这个系统中,中断向量表是用户自己定义的,可以选择任
何自己感兴趣的信号来产生中断,所以中断处理程序是以Signal为单位的。

yiming988 发表于 2013-11-17 15:04:40

Gorgon_Meducer 发表于 2013-11-16 23:00 static/image/common/back.gif
SIGNAL不是一个数据结构,是一个硬件概念,SIGNAL可以用来产生中断,也可以用来直接触发
外设的动作而不 ...

上面仁兄抓了个虫子:范例一第21行,注释Signal1应该改成Signal2.

catwill 发表于 2013-11-17 16:40:46

什么是“默默等待房产”?

Gorgon_Meducer 发表于 2013-11-17 23:25:20

catwill 发表于 2013-11-17 16:40 static/image/common/back.gif
什么是“默默等待房产”?

砖头数量多到可以盖房子啊

Gorgon_Meducer 发表于 2013-11-17 23:28:23

yiming988 发表于 2013-11-17 15:04 static/image/common/back.gif
上面仁兄抓了个虫子:范例一第21行,注释Signal1应该改成Signal2.

谢谢提醒,已经更正

eduhf_123 发表于 2013-11-18 13:00:38

无槽可吐肿么办?

zhexuejia 发表于 2013-11-18 15:15:24

竟然看懂了 。。。。{:victory:}

Gorgon_Meducer 发表于 2013-11-18 15:18:26

zhexuejia 发表于 2013-11-18 15:15 static/image/common/back.gif
竟然看懂了 。。。。

要的就是这个效果哈

didadida 发表于 2014-5-18 20:51:15

老帖了,表示也看懂了,感觉封装以后,考虑东西就清晰了,因为很多底层不需要关心。可能我的比喻不恰当,就好像Arduino把底层封装好,只有一个setup和一个loop似的。{:smile:}

qingaixww 发表于 2014-5-18 22:17:50

我也看懂了,很开心,可以不用关心很多底层的配置,造福于民啊!

Gorgon_Meducer 发表于 2014-5-18 22:52:49

didadida 发表于 2014-5-18 20:51
老帖了,表示也看懂了,感觉封装以后,考虑东西就清晰了,因为很多底层不需要关心。可能我的比喻不恰当,就 ...

这个接口又更新了,更简单,更强大。明天(周一)我来更新这个帖子。

Gorgon_Meducer 发表于 2014-5-19 14:15:21

更新了SIGNAL系统的范例。

y574924080 发表于 2014-5-19 14:22:02

MARK......................

dongfo 发表于 2014-5-19 14:56:38

居然看懂了!
这么写的好处就是可以十分简洁明了地配置中断,同时也使得逻辑十分直接。用户只需要要知道自己想干什么,不需要知道具体实现的细节。配置过程直接描述了行为。


dongfo 发表于 2014-5-19 15:04:18

本帖最后由 dongfo 于 2014-5-19 15:21 编辑

但是,往往这样写了,也就意味着用户需要知道配置函数里面那些参数的意义,和使用范围。
看懂了容易,用起来的时候需要熟知命名规则。
正确的配置方法看起来会很和谐,如果用户想要自己配置的时候,可能会出现一些参数之间的组合,没有示例,也不知道具体的寄存器配置动作,就不知道这样是否可行。
还有就是,这样直接由用户指定中断向量的方式确很方便。但是好像没有提及中断优先级。

Gorgon_Meducer 发表于 2014-5-19 15:59:41

dongfo 发表于 2014-5-19 15:04
但是,往往这样写了,也就意味着用户需要知道配置函数里面那些参数的意义,和使用范围。
看懂了容易,用起 ...

我的理解是:这类代码都必须是代码生成器提供的,我应该有责任提供一套好用的图形化代码配置工具。
这类代码的生成应该是代码生成器来产生,产生的代码应该做到容易读懂。

同时,必要的说明文档来给用户提供培训也是必须的。你觉得呢?

中断优先级的问题其实是ARM的NVIC统一配置的,不过你提醒的对,我应该提供一个统一的配置接口。

minier 发表于 2014-5-19 20:03:10

向楼主致敬

dongfo 发表于 2014-5-19 22:54:21

Gorgon_Meducer 发表于 2014-5-19 15:59
我的理解是:这类代码都必须是代码生成器提供的,我应该有责任提供一套好用的图形化代码配置工具。
这类 ...

哈哈,最低的门槛,给“最懒”的用户。让一个只有十分有限知识基础的用户用上复杂的处理器。让世界更美很重要,让世界变简单也很重要----懒人自白。
是的图形界面,培训文档很重要。
这种写法比STM32的固件库人性化,STM32库函数很多,相互之间关联不是那么明显。
初学者往往会觉得使用库函数太复杂,和直接用寄存器相比没有太大的优势。如果没有示例,往往用户还是会直接去看手册,根据手册自己配置。

Gorgon_Meducer 发表于 2014-5-19 23:20:51

dongfo 发表于 2014-5-19 22:54
哈哈,最低的门槛,给“最懒”的用户。让一个只有十分有限知识基础的用户用上复杂的处理器。让世界更美很 ...

我会努力的

didadida 发表于 2014-5-20 13:28:57

               
mark up

openm4 发表于 2014-12-1 19:22:30

默默等待房产 崩盘??

四川李工 发表于 2014-12-1 19:33:13

表示看不懂 太高升了!!!!!!!!!
页: [1]
查看完整版本: [交流][拍砖]新版驱动接口风格调查(三):信号系统