Every RTOS for a PIC which does not have a software-addressable stack generally requires that all but one of the tasks must have its work divided into uninterruptable pieces which begin and end at the top stack level; the "task-yield" operation does not use a function call, but rather a sequence like
// This code is part of task C (assume for this example, there are tasks
// called A, B, C
movlw JumpC4 & 255
goto TASK_SWITCH_FROM_C
TargetC4:
Elsewhere in the code would be some code like:
TASK_SWITCH_FROM_A:
movwf nextJumpA // Save state of task C
// Now dispatch next instruction for task A
movlw TaskB_Table >> 8
movwf PCLATH
movf nextJumpB,w
movwf PCL
TASK_SWITCH_FROM_B:
movwf nextJumpB // Save state of task C
// Now dispatch next instruction for task A
movlw TaskC_Table >> 8
movwf PCLATH
movf nextJumpC,w
movwf PCL
TASK_SWITCH_FROM_C:
movwf nextJumpC // Save state of task C
// Now dispatch next instruction for task A
movlw TaskA_Table >> 8
movwf PCLATH
movf nextJumpA,w
movwf PCL
At the end of the code, for each task, there would be a jump table; each table would have to fit within a 256-word page (and could thus have a maximum of 256 jumps)
TaskC_Table:
JumpC0 : goto TargetC0
JumpC1 : goto TargetC1
JumpC2 : goto TargetC2
JumpC3 : goto TargetC3
JumpC4 : goto TargetC4
...etc.
Effectively, the movlw
at the start of the task-switch sequence loads the W register with the LSB of the address of the instruction at JumpC4
. The code at TASK_SWITCH_FROM_C
would stash that value someplace, and then dispatch the code for task A. Later, after TASK_SWITCH_FROM_B
is executed, the stored JumpC4
address would be reloaded into W and the system would jump to the instruction pointed to thereby. That instruction would be a goto TargetC4
, which would in turn resume execution at the instruction following the task-switch sequence. Note that task switching doesn't use the stack at all.
If one wanted to do a task switch within a called function, it might be possible to do so if that function's call and return were handled in a manner similar to the above (one would probably have to wrap the function call in a special macro to force the proper code to be generated). Note that the compiler itself wouldn't be capable of generating code like the above. Instead, macros in the source code would generate directives in the assembly-language file. A program supplied by the RTOS vendor would read the assembly-language file, look for those directives, and generate the appropriate vectoring code.
It's not the width of number it can store, it's the width it can work with in a single operation. Customarily (but not necessarily) this also has a degree of correlation to the width of native memory addressing, and thus the amount of storage which can be easily mapped without ugly workarounds such as segmentation or bank switching.
Today's 32-bit cores are superior to 8-designs in most respects (flexibility, flat memory model, and of course performance), with the major exceptions being legacy systems, applications with extreme volume and price pressure (otherwise pricing tends to correlate better with on chip memory size than with core width), and side effects of process/density. The later can provide things like 5v operation, or possibly in some cases greater radiation hardness or a simplicity advantage if trying to prove the CPU design itself to be free of logic errors. One final process/age side effect of value to many hobbyists is that 8-bit cores in DIP packages are common, while 32-bit devices in such packages are rarer (though they do exist).
Best Answer
When the PIC18 series are referred to as 8-bit microcontrollers, its the size of the data words which these micros use which is being specified.
Their registers and RAM are 8-bit wide, and computations and operations are typically done on 8-bits at a time.
However, since the PICs use a Harvard architecture, their data and program memories are kept completely separate.
This means that there is no link between the size of the data words and the size of the program code words.
When looking at the different sub-groups in the 8-bit PIC family, you can see that there are different groups with different code word sizes. The PIC18's have 16-bit code words, while the PIC12's have 12-bit code words.
Once upon a time there was also a PIC14 with a 14-bit code word.
You may have noticed that PIC12=12-bit, PIC14=14-bit, but PIC18 doesn't correspond with an 18-bit code word.
This is because the PIC18's were developed as an upgrade to the PIC16 series and PIC16=16-bit.