qq_到底为了什么
qq_到底为了什么
这家伙很懒,什么也没写!

注册于 9年前

回答
15
文章
0
关注者
0

发布于8年前

no zuo no die, why you try?

你的QQ名称就很好的诠释了这一切!


…..一次偶然机会,本来是在中断外延时的,但因为程序处理的问题改了一下代码,然后发现这个问题,就一直想不懂,所以想看看到底怎么回事。

发布于8年前

这几天一直纠结,再把自己理解加一下,不知正确与否?

1、正常情况下,即在线程中调用rt_thread_delay,会把当前PC if (thread->error == -RT_ETIMEOUT)等其他寄存器压到应用层的栈(这里针对comtex-M系列)

  1. rt_err_t rt_thread_sleep(rt_tick_t tick)
  2. {
  3. register rt_base_t temp;
  4. struct rt_thread *thread;
  5. /* disable interrupt */
  6. temp = rt_hw_interrupt_disable();
  7. /* set to current thread */
  8. thread = rt_current_thread;
  9. RT_ASSERT(thread != RT_NULL);
  10. /* suspend thread */
  11. rt_thread_suspend(thread);
  12. /* reset the timeout of thread timer and start it */
  13. rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick);
  14. rt_timer_start(&(thread->thread_timer));
  15. /* enable interrupt */
  16. rt_hw_interrupt_enable(temp);
  17. rt_schedule();
  18. /* clear error number of this thread to RT_EOK */
  19. if (thread->error == -RT_ETIMEOUT)
  20. thread->error = RT_EOK;
  21. return RT_EOK;
  22. }

2、如果在中断里面调用rt_thread_delay,系统会直接在MSP(主栈)里面,同时中断退出时,相当恢复到进中断之前的PC(因为systick的中断优先级最低,一定要等所有中断ISR全部执行完,再执行pendsv中断),这样造成的结果就是当thread->thread_timer超时,本来是希望恢复到 if (thread->error == -RT_ETIMEOUT),结果恢复到进中断前的PC,这与设计应该不符。
3、根据上面理解,然后有人会提出来为什么在中断可以调用信号量发送等呢?
我的理解,应该是一样的,因为发送信号量函数后面没有需要调度回来再继续执行。
4、查了网上资料,大部分是关于linux,给出的解释大概是说进行内核态后,无法获取current_thread信息,这个应该设计上的的原因,但cortex-M系列没有存在这样的情况,因为current_thread作为全局变量是可以获取的,所以给出上面我的理解,不知正确与否?

发布于8年前

老大,稍加解释一下。呵呵!

发布于9年前

啥问题?请指教,哈!

发布于9年前

需求:ADC 采样频率 1S/12800个,即78us采样一次,并且要求4个通道采到,CPU频率需要工作在4MHZ或者8MHZ,以便保证功耗,采用rtthread 系统,CPU采用cortex-M0+,freescale KL series,此芯片有个限制:4个ADC通道不能同时采样。

一、 需要解决的问题:
1、 ADC轮流采样。
2、 78us采样一次。
3、 低功耗问题。
4、 在cpu工作在4MHZ或者8MHZ情况下,rtthread系统在78us能及时的响应。
二:对策及思考:
1、 根据一、条件4,采用中断方式基本行不通,大概评估了一下在4MHZ情况,rtthread系统响应时间大约要150us.
2、 采用DMA方式来采样ADC的值。
3、 采用DMA方式来改变ADC的采样通道从而触发ADC采样,DMA的触发源为:周期性硬件定时器 78us触发一次。
二、 方案:

  1. 1

三、 实现:

  1. 2
  2. 3

五、上述方案及实现存在的问题:
1、如上图2: 当4个通道值传送完成以后,DMA0的BCR如何及时进行填充?因为TPM的触发频率78us/次,如果DMA0传送结束以后没有及时填充BCR,会导致DMA0出错。
2、同样上图3:DMA1的BCR如何及时填充?虽然它的触发间隔是78us+DMA0传送时间+ADC采样完成时间。 试了一下这个是可以用DMA中断来进行BCR填充,但它仍然有一定的风险,导致DMA1出错。
六、接下去的方案及实现:
就是解决 五 中的2个问题,由于芯片有一个link功能:当一个DMA结束以后可以启动另一个DMA,即采用另一个DMA(设DMA2)中对DMA0的BCR进行赋值。
这里DMA2需要传送清除DMA0完成标志+DMA0的BCR等2个数据到DMA0的寄存器来实现,而DMA2本身的BCR可以采用DMA2中断来实现,因为DMA2中断只要在有大约64478us时间里面完成对BCR的填充就OK。
同时道理可以在DMA1 link 到DMA3,让DMA3来完成DMA1的BCR和清除标志的工作。当DMA3中断来时发信号量到任务,然后进行数据copy,为了防止采样BUF溢出,采用循环2倍BUF,同时在DMA3中断到来时,cpu根据标志读取相应的BUF段。
如下图:

注:相当于采用4个DMA来规避。
注: 不知道怎么上传图片。。。。

发布于9年前

问题二:是对临界区的保护,无法开启中断。

发布于9年前

补充:rtthread下采样AD,是采用DMA方式,当DMA数据传送结束以后,需要及时在DMA的中断服务程序中重新写入DMA搬运的长度,DMA的中断服务程序大概是80微秒中断一次。

发布于9年前

能不能把VBUS机制也讲讲,只是一个建议,如果跟整个思路不合,就当没提,呵呵

发布于9年前

2天看完,看得还算过隐啊,什么时候出版,先预定一本哈。

发布于9年前

哦,有点忘记了,就是第一条是获取向量表地址__vector_table,第二条是获取 CSTACK

  1. __vector_table
  2. DCD sfe(CSTACK)
  3. DCD Reset_Handler ; Reset Handler
  4. DCD NMI_Handler ; NMI Handler
  5. DCD HardFault_Handler ; Hard Fault Handler
  6. DCD MemManage_Handler ; MPU Fault Handler
  7. DCD BusFault_Handler ; Bus Fault Handler
  8. DCD UsageFault_Handler ; Usage Fault Handler
  9. DCD 0 ; Reserved
  10. DCD 0 ; Reserved
  11. DCD 0 ; Reserved
  12. DCD 0 ; Reserved
  13. DCD SVC_Handler ; SVCall Handler
  14. DCD DebugMon_Handler ; Debug Monitor Handler
  15. DCD 0 ; Reserved
  16. DCD PendSV_Handler ; PendSV Handler
  17. DCD SysTick_Handler ; SysTick Handler

多谢哈!

发布于9年前

恩,谢了,懂了

发布于9年前

把 “那会不会导致无法实现中断嵌套和中断优先级的区分”
改成“ 那会不会导致无法实现中断嵌套和中断优先级”

发布于9年前

恩,放在线程里初始化,是不会出现混乱。谢了。

发布于9年前

恩,OK,谢谢!

发布于9年前

谢谢,aozima,后来单步调试了一下,发现在rt_compenet_init()调用各种init函数时,调用自己应用程序中rt_pin_mode();时候,出现了上述错误,先去掉自己的应用程序,系统可以运行,看来这个rt_pin_mode()还不是很理解。

回到
顶部

发布
问题

投诉
建议