最近忙别的事情,很长时间没碰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倍,除了天赋之外,更重要的是建立在大量编程实践的基础之上,那些只看书不操作的人基本上只会是纸上谈兵,这也是我面试软件工程师一定要出一道上机题目的原因。最近看了一些案例,发点感慨,空谈误国,空谈误国。
ecos stm32 步步深入8 - 手工打造串口usart2驱动实验ecos中断