Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread一般讨论
不知道这个问题能不能加个检测手段来规避?
发布于 2016-05-11 11:04:15 浏览:2021
订阅该版
问题:有个周期性的软件定时器(称作test_timer,时间为30ms)调用下面函数xfer( if (-RT_ETIMEOUT == rt_event_recv(&dma_tx_event, (1<<1),RT_EVENT_FLAG_AND|RT_EVENT_FLAG_CLEAR, RT_TICK_PER_SECOND * 300, &e)):当发送长数据时会拉起)发送SPI的数据,另个周期性的软件定时器(称作checktimer,时间比较长)当没有收到GPRS数据包进行重连,另个线程进行数据包解析TCP_SISR_Filter,当test_time定时器因为发送长数据包,导致此线程挂起,此时GPRS收到数据包,切到TCP_SISR_Filter进行解析,在这函数里面进行了checktimer关,再开操作((rt_timer_stop(dev->checktimer);rt_timer_start(dev->checktimer):进行checktimer开关操作)),因为软件定时器rt_timer_start ```(#ifdef RT_USING_TIMER_SOFT if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) { /* check whether timer thread is ready */ if (timer_thread.stat != RT_THREAD_READY) { /* resume timer thread to check soft timer */ rt_thread_resume(&timer_thread); rt_schedule(); } } #endif ),``` 会导致test_timer这个定时器被重新唤醒,从而导致函数xfer不等待DMA的中断信号,直接执行 rt_pin_write(spi_ssn,1)拉高SSN,导致SPI逻辑出错。 这种用法: 1、在软件定时器执行了挂起动作,我看了void rt_soft_timer_check(void),是允许的; 2、对软件定时器的开关操作也是被允许的。 当然上述用法是有点不太合理,就是在定时器服务程序执行东西偏多,但既然系统是允许,我想能不能加个检测?或者说直接系统不允许。 ```static rt_uint32_t xfer(struct rt_spi_device *device, struct rt_spi_message *message) { struct mkl17_spi_bus * spi_bus = (struct mkl17_spi_bus *)device->bus; SPI_Type *base = spi_bus->SPI; uint8_t * ptmp ; rt_uint32_t e; #ifdef SPI_USE_DMA uint8_t tx_channel = spi_bus->DMA_Channel_TX; uint8_t rx_channel = spi_bus->DMA_Channel_RX; #endif struct mkl17_spi_cs *mkl17_spi_cs = device->parent.user_data; uint16_t spi_ssn = mkl17_spi_cs->GPIO_Pin; rt_uint32_t size = message->length; /* take CS */ if(message->cs_take) { rt_pin_write(spi_ssn,0); } // Disable module to clear the shift register SPI_HAL_Disable(base); SPI_HAL_Enable(base); if (RT_NULL != message->send_buf) { ptmp = (uint8_t *)message->send_buf; #ifdef SPI_USE_DMA /* Read the SPI Status register */ SPI_HAL_IsTxBuffEmptyPending(base); SPI_HAL_SetRxDmaCmd(base, false); /* Enable the SPI TX DMA Request */ SPI_HAL_SetTxDmaCmd(base, true); dma_send_config(tx_channel,(uint32_t)ptmp,size); if (-RT_ETIMEOUT == rt_event_recv(&dma_tx_event, (1<<1), RT_EVENT_FLAG_AND|RT_EVENT_FLAG_CLEAR, RT_TICK_PER_SECOND * 300, &e)) { rt_kprintf("send: event timeout "); message->length = 0; goto release; } #else for(uint32_t i = 0; i< size; i++) { SPI_HAL_WriteDataBlocking(base, kSpi8BitMode, 0, *ptmp++); } #endif } if (RT_NULL != message->recv_buf) { #ifdef SPI_USE_DMA ptmp = rt_malloc(size); if (RT_NULL == ptmp ) { rt_kprintf("xfer rt_malloc error "); message->length = 0; goto release; } rt_memset(ptmp,0xff,size); /* Read the SPI Status register */ SPI_HAL_IsTxBuffEmptyPending(base); SPI_HAL_IsReadBuffFullPending(base); SPI_HAL_SetRxDmaCmd(base, true); SPI_HAL_SetTxDmaCmd(base, true); spi_dma_recv_config(tx_channel,rx_channel,(uint32_t)ptmp,(uint32_t)message->recv_buf,size); if (-RT_ETIMEOUT == rt_event_recv(&dma_tx_event, (1<<0)|(1<<1), RT_EVENT_FLAG_AND |RT_EVENT_FLAG_CLEAR, 50, &e)) { rt_kprintf("recv: event timeout "); rt_free(ptmp); message->length = 0; goto release; } rt_free(ptmp); #else ptmp = (uint8_t *)message->recv_buf; for(uint32_t i = 0; i< size; i++) { // Send dummy byte to receive data from slave SPI_HAL_WriteDataBlocking(base, kSpi8BitMode, 0, 0xff); // Wait for slave send data back while(SPI_HAL_IsReadBuffFullPending(base)==0){} // Read data register *ptmp++ = SPI_HAL_ReadDataLow(base); } #endif } delay_ms(8); release: SPI_HAL_SetRxDmaCmd(base, false); SPI_HAL_SetTxDmaCmd(base, false); /* release CS */ if(message->cs_release) { rt_pin_write(spi_ssn,1); } return message->length; } void DMA0_IRQHandler(void) { DMA_DRV_IRQhandler(SPI0_DMA_TX_CH0); rt_event_send(&dma_tx_event,1<<1); } void DMA1_IRQHandler(void) { DMA_DRV_IRQhandler(SPI0_DMA_RX_CH1); rt_event_send(&dma_tx_event,1<<0); } signed int TCP_SISR_Filter(modem_t *dev, char *pp_scr)//at^siso=1 { //^SISR: 0,6,680401008A16 u8 *recv_hex; char *p,*ptmp; u16 len; msg_head_t msgHead; rt_err_t err; //rx_data_num++; rt_timer_stop(dev->checktimer); rt_timer_start(dev->checktimer); // rt_kprintf("sisr=%s ",p); if (p = parseData(pp_scr,Modem_TCP_SISRAck,Modem_ACK_Enter)) { ptmp = rt_strstr(p,","); if (RT_NULL == ptmp) { rt_kprintf("%s find , failed ",__FUNCTION__); return FAIL; } len = simple_strtoul(p,NULL,10); ptmp = ptmp+rt_strlen(","); debug_printf("%s ", ptmp); //打印数据 if (strlen(ptmp) != len * 2) { rt_kprintf("strlen(ptmp)=%d,len=%d ",strlen(ptmp),len); return FAIL; } recv_hex = rt_malloc(len); if (NULL == recv_hex) { rt_kprintf("%s rt_malloc error ",__FUNCTION__); return FAIL; } if (FAIL == AsciiToHex(ptmp,len,recv_hex)) { rt_kprintf("%s AsciiToHex error ",__FUNCTION__); rt_free(recv_hex); return FAIL; } vBuildMsgHead((&msgHead),EMANG_MODULE,EAT_MODULE,ENET_DATA,len,recv_hex); err = rt_mq_send(MANGE_mq,&msgHead,sizeof(msg_head_t)); if (RT_EOK != err) { rt_kprintf("rt_mq_send error %s, %d ", __FUNCTION__, __LINE__); rt_free(recv_hex); return FAIL; } // led_mutex_set_state(Eled_remote_rx_red_flashing,TRUE); return SUCC; } else { rt_kprintf("parseData error %s, %d ", __FUNCTION__, __LINE__); return FAIL; } } rt_err_t rt_timer_start(rt_timer_t timer) { unsigned int row_lvl; rt_list_t *timer_list; register rt_base_t level; rt_list_t *row_head[RT_TIMER_SKIP_LIST_LEVEL]; unsigned int tst_nr; static unsigned int random_nr; /* timer check */ RT_ASSERT(timer != RT_NULL); /* stop timer firstly */ level = rt_hw_interrupt_disable(); /* remove timer from list */ _rt_timer_remove(timer); /* change status of timer */ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; rt_hw_interrupt_enable(level); RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(timer->parent))); /* * get timeout tick, * the max timeout tick shall not great than RT_TICK_MAX/2 */ RT_ASSERT(timer->init_tick < RT_TICK_MAX / 2); timer->timeout_tick = rt_tick_get() + timer->init_tick; /* disable interrupt */ level = rt_hw_interrupt_disable(); #ifdef RT_USING_TIMER_SOFT if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) { /* insert timer to soft timer list */ timer_list = rt_soft_timer_list; } else #endif { /* insert timer to system timer list */ timer_list = rt_timer_list; } row_head[0] = &timer_list[0]; for (row_lvl = 0; row_lvl < RT_TIMER_SKIP_LIST_LEVEL; row_lvl++) { for (;row_head[row_lvl] != timer_list[row_lvl].prev; row_head[row_lvl] = row_head[row_lvl]->next) { struct rt_timer *t; rt_list_t *p = row_head[row_lvl]->next; /* fix up the entry pointer */ t = rt_list_entry(p, struct rt_timer, row[row_lvl]); /* If we have two timers that timeout at the same time, it's * preferred that the timer inserted early get called early. * So insert the new timer to the end the the some-timeout timer * list. */ if ((t->timeout_tick - timer->timeout_tick) == 0) { continue; } else if ((t->timeout_tick - timer->timeout_tick) < RT_TICK_MAX / 2) { break; } } if (row_lvl != RT_TIMER_SKIP_LIST_LEVEL - 1) row_head[row_lvl+1] = row_head[row_lvl]+1; } /* Interestingly, this super simple timer insert counter works very very * well on distributing the list height uniformly. By means of "very very * well", I mean it beats the randomness of timer->timeout_tick very easily * (actually, the timeout_tick is not random and easy to be attacked). */ random_nr++; tst_nr = random_nr; rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL-1], &(timer->row[RT_TIMER_SKIP_LIST_LEVEL-1])); for (row_lvl = 2; row_lvl <= RT_TIMER_SKIP_LIST_LEVEL; row_lvl++) { if (!(tst_nr & RT_TIMER_SKIP_LIST_MASK)) rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL - row_lvl], &(timer->row[RT_TIMER_SKIP_LIST_LEVEL - row_lvl])); else break; /* Shift over the bits we have tested. Works well with 1 bit and 2 * bits. */ tst_nr >>= (RT_TIMER_SKIP_LIST_MASK+1)>>1; } timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED; /* enable interrupt */ rt_hw_interrupt_enable(level); #ifdef RT_USING_TIMER_SOFT if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) { /* check whether timer thread is ready */ if (timer_thread.stat != RT_THREAD_READY) { /* resume timer thread to check soft timer */ rt_thread_resume(&timer_thread); rt_schedule(); } } #endif return -RT_EOK; } ```
查看更多
1
个回答
默认排序
按发布时间排序
撰写答案
登录
注册新账号
关注者
0
被浏览
2k
关于作者
qq_到底为了什么
这家伙很懒,什么也没写!
提问
8
回答
15
被采纳
0
关注TA
发私信
相关问题
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
【NXP-MCXA153】 定时器驱动移植
2
GD32F450 看门狗驱动适配
3
【NXP-MCXA153】看门狗驱动移植
4
RT-Thread Studio V2.2.9 Release Note
5
CherryUSB的bootuf2配置
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
freemodbus
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
踩姑娘的小蘑菇
7
个答案
2
次被采纳
a1012112796
15
个答案
1
次被采纳
Ryan_CW
5
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
本月文章贡献
YZRD
3
篇文章
6
次点赞
catcatbing
3
篇文章
6
次点赞
lizimu
2
篇文章
8
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部