简体   繁体   English

在PIC18上使用C进行多线程

[英]Multithreading using C on PIC18

由于没有OS,如何在编程PIC18时创建并行运行的线程?

Don't use threads, use an event loop. 不使用线程,使用事件循环。

The PIC18 is a small processor and an event loop based style means you don't have to keep many deep stacks hanging around. PIC18是一款小型处理器,基于事件循环的样式意味着您不必保留许多深层堆栈。 You need to write your code in terms of the event loop, but that is probably reasonable. 您需要根据事件循环编写代码,但这可能是合理的。

If you do have some long running tasks, use timers are different interrupt priority levels to allow higher priority event loops to preempt lower priority event loops, and put appropriate types of work into the appropriate event queue. 如果确实有一些长时间运行的任务,则使用定时器的中断优先级不同,以允许较高优先级的事件循环抢占较低优先级的事件循环,并将适当的工作类型放入适当的事件队列中。

You could try Cooperative multitasking . 您可以尝试协作式多任务处理

For types of problems that PICs solve, you'd probably be better of if you try a different design that uses interrupts or polling instead of multiple threads. 对于PIC解决的问题类型,如果尝试使用中断或轮询而不是多个线程的其他设计,则可能会更好。

You can put an RTOS on there (there's an unofficial ucOS port , or you could check out FreeRTOS's PIC18 port ). 您可以在其中放置一个RTOS(有一个非官方的ucOS端口 ,也可以检出FreeRTOS的PIC18端口 )。

Otherwise, you could try implementing coroutines in C by using setjmp and longjmp . 否则,您可以尝试使用setjmplongjmp 在C中实现协程

If there is no OS at all, you'll (obviously) have to re-create the necessary functionality yourself. 如果根本没有操作系统,则(显然)您必须自己重新创建必要的功能。

The easiest way to follow would probably be to install a timer interrupt running at some suitable frequency (probably depends on your actual clock speed, but perhaps in the range 100-1000 Hz). 最简单的方法可能是安装一个以适当频率运行的定时器中断(可能取决于您的实际时钟速度,但可能在100-1000 Hz的范围内)。 In the interrupt handler, you need to inspect the state of the current thread, and decide if a switch should occur. 在中断处理程序中,您需要检查当前线程的状态,并确定是否应该进行切换。

The trick is then to make the switch if necessary, and return from the interrupt handler into a different thread . 然后,诀窍是在必要时进行切换,然后从中断处理程序返回另一个线程

Of course, getting this to work when the threads themselves might use interrupts, will not necessarily be easy. 当然,当线程本身可能使用中断时使此功能正常工作并不一定很容易。

You could also look into installing some kernel, perhaps Contiki . 您也可以考虑安装一些内核,也许是Contiki

Here is an example of "protothreads" for the PIC18, looks like a reasonable amount of code. 是PIC18的“ protothreads”示例,看起来像是相当数量的代码。 Not sure about the semantics, though. 但是,不确定语义。

Update : This will probably require you do some of the lowest-level code in assembler (I'm not sure, haven't worked in C on the PIC so I don't know exactly how much control you get). 更新 :这可能需要您在汇编器中执行一些最低级别的代码(我不确定,因为尚未在PIC上的C语言中工作,所以我不知道您将获得多少控制权)。 You will need control over the registers the program counter, and those are not C concepts. 您将需要控制程序计数器的寄存器,而这些不是C概念。

Be aware that on microcontrollers, some "threads" can also be handled by just some specific interrupt handler, and thus run in "parallel" to your main event loop anyway. 请注意,在微控制器上,某些“线程”也可以仅由某些特定的中断处理程序处理,因此无论如何都与主事件循环“并行”运行。

Eg if you have an external event trigger an ADC conversion, your ADC-conversion-done handler can take that value, do a few calculations and then set some output bits to adapt the control output according to the ADC value. 例如,如果您有外部事件触发ADC转换,则ADC转换完成处理程序可以获取该值,进行一些计算,然后设置一些输出位以根据ADC值调整控制输出。 All that can happen in the interrupt handler, and thus parallel to everything else. 所有可能发生在中断处理程序中的事件,因此与其他所有事件并行发生。

Depending on the things you need to do in parallel, you can choose a combination of multiple techniques to make stuff work in parallel as intended. 根据您需要并行执行的操作,可以选择多种技术的组合来使内容按预期并行工作。

您可能需要阅读嵌入式系统编程中的本文: 构建超级简单Tasker

I would like to share my tiny kernel in C programming language to manage tasks on a microcontroller. 我想用C编程语言共享我的小内核,以管理微控制器上的任务。 You can create a task with a period, suspend, resume and change a period of task at any time. 您可以随时创建任务,并暂停,恢复和更改任务期限。 This kernel can delete all task to create another sequencer as you want. 该内核可以删除所有任务,以根据需要创建另一个音序器。 A TickGet function is supply by the kernel to manage all timers as you want. 内核提供了一个TickGet函数,可以根据需要管理所有计时器。 You have to create just one interrupt function and replace the function Timer() to get your tiny-kernel for your own application. 您只需创建一个中断函数并替换函数Timer()即可为您自己的应用程序获取小型内核。 To resume this kernel is based on a circular linked list, to switch task on task. 恢复该内核是基于循环链表,以便在任务之间切换任务。 It is willingly written in a general way to help people to customise for theirs owns applications. 它愿意以一种通用的方式来编写,以帮助人们针对自己的应用程序进行自定义。 There is no priority between task like a round-robin task scheduling. 任务之间没有优先权,例如循环任务调度。 And I wrote this source code in respect of the MISRA guidelines (automotive norm) You can download it here 我是根据MISRA准则(汽车规范)编写此源代码的,您可以在此处下载

I hope to help people to manage tasks on microcontroller. 我希望能帮助人们在微控制器上管理任务。

The CCS compiler includes an RTOS. CCS编译器包含一个RTOS。 I haven't used it, but from the compiler manual : 我没有用过,但是从编译器手册中可以找到

The CCS Real Time Operating System (RTOS) allows a PIC micro controller to run regularly scheduled tasks without the need for interrupts. CCS实时操作系统(RTOS)允许PIC微控制器运行定期计划的任务,而无需中断。 This is accomplished by a function (RTOS_RUN()) that acts as a dispatcher. 这是通过充当调度程序的函数(RTOS_RUN())完成的。 When a task is scheduled to run, the dispatch function gives control of the processor to that task. 当任务计划运行时,调度功能将处理器的控制权交给该任务。 When the task is done executing or does not need the processor anymore, control of the processor is returned to the dispatch function which then will give control of the processor to the next task that is scheduled to execute at the appropriate time. 当任务完成执行或不再需要处理器时,将处理器的控制权返回到分派功能,该功能将把处理器的控制权交给计划在适当时间执行的下一个任务。 This process is called cooperative multi-tasking. 此过程称为协作多任务。

Just a word of warning - check their forums for info about the specific features you're looking for. 只需警告一下-在其论坛上查看有关您正在寻找的特定功能的信息。 Apparently CCS has a habit of releasing new features before they're fully tested. 显然,CCS习惯于在新功能经过全面测试之前发布它们。 That's one reason I'm still using the older version (v3.249). 这就是我仍在使用旧版本(v3.249)的原因之一。

On the 8051, I've done dual-tasking by using a simple stack switcher. 在8051上,我已经使用一个简单的堆栈切换器完成了双重任务。 I would expect the same could be done on the PIC, provided each task only used 16 levels of stack. 如果每个任务仅使用16个级别的堆栈,我希望可以在PIC上执行相同的操作。 The code would be something like this (assumes _altSP is in the common bank) 该代码将是这样的(假设_altSP在公共库中)

_InitTask2:
    movff _STKPTR,_altSP
    movlw 16
    movwf _STKPTR,c
    goto _Task2Start

_TaskSwitch:
    movf  _altSP,w,c
    movff _STKPTR,_altSP
    movwf _STKPTR,c
    return

The main task should call _InitTask2 to start the second task. 主要任务应调用_InitTask2以启动第二个任务。 The second task will run until it calls _TaskSwitch, whereupon the main task will resume execution following the instruction that called _InitTask2. 第二个任务将一直运行,直到调用_TaskSwitch,然后主任务将按照称为_InitTask2的指令恢复执行。 From thence forth, every time a task calls _TaskSwitch, the other task will resume execution from the last place it called _TaskSwitch. 从此以后,每次一个任务调用_TaskSwitch时,另一个任务将从其最后一个位置_TaskSwitch恢复执行。

If you use this approach, your compiler will have to be informed that all registers may be trashed by calls to _InitTask2 or _TaskSwitch. 如果使用这种方法,则必须通过调用_InitTask2或_TaskSwitch通知编译器所有寄存器都被废弃。 It will also have to be told that _Task2Start and functions it calls must be allocated separate variable space from the main task. 还必须告知_Task2Start及其调用的函数必须与主任务分开分配独立的变量空间。

I'm not sure what you need to tell the compiler to make it happy, but I will say that cooperative dual-tasking can make some things work really nicely. 我不确定您需要告诉编译器使其满意的是什么,但是我会说协同双任务可以使某些事情真的很好地工作。

I'm doing it (strictly speaking cooperative multitasking at fixed call stack depth). 我正在做(严格来说是在固定调用堆栈深度进行协作式多任务处理)。

It works, but Hitec-c compiler works against me -- it reuses memory locations for temporary variables from functions that it thinks never run at the same time. 它可以工作,但是Hitec-c编译器对我不利-它从它认为永远不会同时运行的函数中为临时变量重用内存位置。 Basically threads corrupt each other. 基本上,线程会互相破坏。 If I figure out a way around this, I'll update this answer with sample code. 如果我想办法解决这个问题,我将用示例代码更新此答案。

This does that very thing, a task loop, as well as provisions priorities of tasks, and what I like simple coding of breaking up long running functions into slices. 这样就完成了一个任务循环,并提供了任务的优先级,我喜欢将长时间运行的函数分解为多个片段的简单编码。

http://www.mculabs.com/drivers/qtask.html http://www.mculabs.com/drivers/qtask.html

Protothreads library is simple way for multi-tasking, cross-platform: http://dunkels.com/adam/pt/ Protothreads库是用于多任务,跨平台的简单方法: http ://dunkels.com/adam/pt/

Example of minimal scheduler for PT with task synchronization,timers,and user data: https://github.com/edartuz/c-ptx 具有任务同步,计时器和用户数据的PT最小调度程序的示例: https : //github.com/edartuz/c-ptx

I agree with ndim -- you can think of each interrupt handler as something like a "thread". 我同意ndim的看法-您可以将每个中断处理程序视为“线程”之类的东西。 Sometimes all the tasks you need to do can be handled by interrupt handlers triggered by external and internal events -- the "main loop" is an idle loop that does nothing. 有时,您需要完成的所有任务都可以由外部和内部事件触发的中断处理程序处理-“主循环”是一个不执行任何操作的空闲循环。

I don't know where some commenters get the idea that there is "no OS" for the PIC18. 我不知道有些评论者会认为PIC18没有“ OS”。 There are quite a few PIC-specific multithreading libraries and "multitasking operating system kernels" for the PIC18, many of them free and open source. PIC18有很多专用于PIC的多线程库和“多任务操作系统内核”,其中许多都是免费和开源的。 See PICList: "PIC Microcontroller specific Multitasking Methods" . 请参见PICList:“ PIC单片机特定的多任务处理方法”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM