首页 > 代码库 > ecos stm32 步步深入8 - 手工打造串口usart2驱动实验ecos中断

ecos stm32 步步深入8 - 手工打造串口usart2驱动实验ecos中断

最近忙别的事情,很长时间没碰ecos了,这两天有点空,抽空写个串口驱动玩玩,也验证一下ecos的中断调用。LZ花了两天时间写好这个驱动,中间遇到了几个比较恶心的问题,后来发现是前面的基础没打好,所幸都解决了。


尽管ECOS已经写好了串口的驱动程序,只需要在配置工具中使能即可。不过别人写的毕竟不是自己的,还是自己写的用的方便,这次试验的主要目的是为了调试ecos的中断服务,让串口中断能收发数据。


首先遇到的最大的问题,事实上跟什么串口都没关系,就是debug时一执行task delay,调试程序就收到停止命令,所有寄存器都不能正确读出。反复花了很长时间去定位原因,开始我怀疑是thread没正确设置,用gdb各种配置thread,时好时坏,看来不是问题的根本。后来我又怀疑是JLINK仿真器有问题,实验了不同的版本,最后还是升级到正版的最新的程序。在网上搜索相关的错误,没什么有价值的内容。这里严重鄙视我天朝的网络,google他妈的都用不了,搜英文得用bing了。后来无意中在打开gdb server时候看到可以选择芯片类型,默认的是cortexm3,就选择了stm32f103ze,没想到问题就这么解决了。我在gdb server的脚本中已经指定了芯片信号命令,看来没有起作用,一定要在开始的时候就选好目标芯片型号。至此,调试时程序不会无缘无故的退出了。


这里说两句题外话,LZ以前看代码用source insight,写代码用slickedit,不过现在公司没买source insight的license,就没法使用了。slickedit是10年前版本的license,应该没有什么限制,仍然用原来公司的license。结果是最近搞ecos要大量读操作系统源码,没有好的工具真是急死人啊。后来发现其实slickedit也是超级好用的查看代码工具,只不过定位不像source insight那么方便,但其实习惯了也非常好用。现在也习惯用slickedit编辑浏览代码,非常方便,不愧是最贵的编辑工具。


上面gdb调试基础打好之后,又有了之前gpio驱动的经验,写串口驱动就非常容易了。代码基本上都是原来写过的,复制黏贴就行,把st的库文件usart加上。在配置串口时添加上中断响应函数

static Cyg_ErrNo usart_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void* buf, cyg_uint32 *len)
{    
    NVIC_InitTypeDef NVIC_InitStructure;
    USART_InitTypeDef u_info;
    Usart_Info_t *info = (Usart_Info_t *)buf;

    USART_DeInit( USART2);
    ConvertSerial2UartInfo(info->b, info->p, info->d, info->s , &u_info);
    USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
    USART_Cmd(USART2, DISABLE);
    USART_Init(USART2, (USART_InitTypeDef *)&u_info);

    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    // create ISR & DSR
<span style="color:#FF6666;">    cyg_interrupt_create(CYGNUM_HAL_INTERRUPT_UART2, 0x80, 0, &usart2_ISP, &usart2_DSR, &int_usart_handle, &int_usart);
    cyg_interrupt_attach(int_usart_handle);
    cyg_interrupt_unmask(CYGNUM_HAL_INTERRUPT_UART2);</span>

    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
    USART_Cmd(USART2, ENABLE);
    return ENOERR;
}

static cyg_uint32 usart2_ISP(cyg_uint32 vector, CYG_ADDRWORD data)
{
	//cyg_interrupt_mask(vector);
	cyg_interrupt_acknowledge( vector );

	if ( USART_GetITStatus(USART2, USART_IT_RXNE) == SET )
    {
        USART_ClearITPendingBit(USART2, USART_IT_RXNE);
        UART2RxISR();
    }
    if ( USART_GetITStatus(USART2, USART_IT_TXE) == SET )
    {
        USART_ClearITPendingBit(USART2, USART_IT_TC);
        UART2TxISR();
    }
    //cyg_interrupt_unmask(vector);
	return (CYG_ISR_HANDLED);
}

其他过程跟GPIO差不多,LZ遇到了有中断响应但无数据发出的问题,后来发现是初始化时候可复用的引脚配置不对造成的,仔细检查配置即可。

开始过程总是比较痛苦的,会遇到这样或那样的问题,有些时候的确不知道该如何解决,但随着一个一个问题的解决,你就会获得大量的实践经验,这就是为什么不同的人工作效率不同的原因。高手为什么是一般工程师工作效率的5-10倍,除了天赋之外,更重要的是建立在大量编程实践的基础之上,那些只看书不操作的人基本上只会是纸上谈兵,这也是我面试软件工程师一定要出一道上机题目的原因。最近看了一些案例,发点感慨,空谈误国,空谈误国。