Multithreading using C on PIC18
Asked Answered
H

13

10

How does one create threads that run in parallel while programming PIC18, since there is no OS?

Histopathology answered 26/10, 2009 at 11:14 Comment(4)
What compiler are you using? Some have features for this purpose.Bankbook
Separate execution context is possible without OS, using tricks like Timer interrupts or other event based interrupts but Threads: not possible without OS.Legatee
You use a low footprint RTOS.Danieldaniela
This question is really open-ended.Bush
T
11

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. 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.

Thetes answered 26/10, 2009 at 11:31 Comment(12)
Agreed. If it meets your needs, keep it simple.Stob
Note that this assumes asynchronous I/O. It doesn't help if your main program is blocked on some I/O. With threads, and simple time based round robin taskswitching you uncouple various tasks, guaranteeing them a small, but constant amount of time.Enlargement
This is a PIC18 chip, and threads need to be implemented somewhere and their state needs to be stored. Pretty much all of the I/O you can do can be done asynchronously in some way; if you start doing synchronous I/O, you have to disable interrupts for reliability and then you're not going to be preempted anyway. You can implement a threading library and scheduler on top of the async features of the chip, but why bother? You probably have less than 4kB of RAM and the time-critical operations are likely to be I/O driven. Just consider PIC18 as a h/w implemented, very simple OS.Thetes
I understand why people say that this is not something you would do, but RTOS greatly increases the quality of programing by using an RTOS to isolate threads. In complex safety critical code an RTOS can save many months of time for a team of engineers, this can exceed 6 figures in savings to use an RTOS that is safety critical certified.Danieldaniela
@Danieldaniela Sure, in complex and safety critical code there are factors beyond "how do I do threads?" A team of engineers working on a safety critical project tend not to ask "how do I do threads", but ask, as you did on the electronics SO, "can you tell me about your RTOS experiences on these dimensions?" Having said that, I have implemented safety critical code on a certified device using a event loop structure and was happy with the outcome. However, that decision depends on many factors not just "x good, y bad".Thetes
@janm, I gave a simple example, please forgive me for undervaluing your experience. The primary reason I want an RTOS is due to decoupling. As I decouple sub-processes the net amount of work the project needs will go down significantly.Danieldaniela
@Danieldaniela No problem, I know that wasn't your intention. I agree that decoupling is good, but you can decouple your decoupling requirement from an RTOS! Whether you choose an RTOS depends on many factors, including the experience of the developers, the problem to be solved, time, money, etc. Separation of concerns is something good developers consider, and do throughout their own code, not just across a boundary to third party code.Thetes
@janm, Most people I have seen do this on their own end up implementing the basics of an RTOS and having to debug the code they write, why not pay for it.Danieldaniela
@janm, I am not saying you are wrong though, There is not a clear rule on what to do!Danieldaniela
@janm, on that note, I do think that the user has chosen that they want to do threads, I think an answer helping them get to threading is of value. Now I have met many that really think threading is going to be something like calling fork() on a pic18Danieldaniela
@Danieldaniela We agree that the answer varies by situation. When we look at the situation in the question, a software developer coming to a PIC18 from a general purpose platform and asking about "threads" should be introduced to the concept of an event loop and dealing with asynchronous events. The chip supports that programming model much better than a threading model, and it is a worthwhile model in and of itself, frequently preferable even when general-purpose threads are available. A separate answer covered the "use an RTOS to get threads" case! :-)Thetes
@janm, Now if the asker would accept an answer you could know what they want. Thank you for the discussion, I quite enjoyed it.Danieldaniela
B
9

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.

Blowing answered 26/10, 2009 at 11:21 Comment(1)
FYI, I just posted some code to illustrate how simple cooperative multitasking can be. I've not done it on the PIC18, but I've done it on the 8051 and on a TI DSP platform.National
L
7

You can put an RTOS on there (there's an unofficial ucOS port, or you could check out FreeRTOS's PIC18 port).

Otherwise, you could try implementing coroutines in C by using setjmp and longjmp.

Laroche answered 26/10, 2009 at 11:21 Comment(0)
F
5

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). 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.

Here is an example of "protothreads" for the PIC18, looks like a reasonable amount of code. 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). You will need control over the registers the program counter, and those are not C concepts.

Falconry answered 26/10, 2009 at 11:24 Comment(0)
S
3

You might want to read this article from embedded system programming: Build a Super Simple Tasker

Syllabism answered 26/10, 2009 at 13:49 Comment(0)
C
2

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.

E.g. 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. 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.

Chris answered 26/10, 2009 at 11:45 Comment(0)
B
1

The CCS compiler includes an 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. This is accomplished by a function (RTOS_RUN()) that acts as a dispatcher. 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. That's one reason I'm still using the older version (v3.249).

Bankbook answered 26/10, 2009 at 18:31 Comment(0)
N
1

On the 8051, I've done dual-tasking by using a simple stack switcher. I would expect the same could be done on the PIC, provided each task only used 16 levels of stack. The code would be something like this (assumes _altSP is in the common bank)

_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. The second task will run until it calls _TaskSwitch, whereupon the main task will resume execution following the instruction that called _InitTask2. From thence forth, every time a task calls _TaskSwitch, the other task will resume execution from the last place it called _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. It will also have to be told that _Task2Start and functions it calls must be allocated separate variable space from the main task.

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.

National answered 19/8, 2010 at 17:41 Comment(2)
This application note tells that it is not possible to access stack pointer if the core is not PIC18. I do not know assembly and trying to learn about simple (s)tack switchers. Does this mean that my hopes on creating a simple task switcher with PIC12 and PIC16 are nonsense?Nerland
@abdullahkahraman: The only way to multitask code on the PIC12 or PIC16 is to require that only one of the tasks can perform a task switch within a nested subroutine. Incidentally, I did a nice task-switched application once on a PIC165x-based chip where both tasks were nearly identical except for I/O assignments. Each task used one set of banked registers. Worked out really slick.National
H
1

I would like to share my tiny kernel in C programming language to manage tasks on a microcontroller. 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. You have to create just one interrupt function and replace the function Timer() to get your tiny-kernel for your own application. 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

I hope to help people to manage tasks on microcontroller.

Happen answered 8/5, 2012 at 18:2 Comment(0)
H
1

Protothreads library is simple way for multi-tasking, cross-platform: http://dunkels.com/adam/pt/

Example of minimal scheduler for PT with task synchronization,timers,and user data: https://github.com/edartuz/c-ptx

Hanser answered 25/5, 2014 at 9:54 Comment(0)
M
0

I agree with ndim -- you can think of each interrupt handler as something like a "thread". 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. There are quite a few PIC-specific multithreading libraries and "multitasking operating system kernels" for the PIC18, many of them free and open source. See PICList: "PIC Microcontroller specific Multitasking Methods".

Meredith answered 26/10, 2009 at 11:14 Comment(0)
S
0

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

Siffre answered 9/12, 2009 at 9:26 Comment(0)
C
0

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. Basically threads corrupt each other. If I figure out a way around this, I'll update this answer with sample code.

Controversy answered 22/12, 2012 at 16:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.