The 18F family with the extended instruction set seems to have almost everything necessary to write a true multitasking, real time, pre-emptive event scheduler. The one thing that seems to be missing (and I'm new so it may be me that's missing the instruction and not the other way around) is an uninterruptible test and set instruction for scheduling and handling resources. I haven't been able to find an instruction that would serve this purpose, but I may be missing something. I know that on the MC6809 micro you had to use and arithmetic right shift through the carry on the appropriately set up memory location to get the function, but it worked just fine when you did it right. Am I missing something? Is there a way to get this function in the 18F instruction set? Inquiring minds want to know. Those of us who need to write such a scheduler also want to know. Thanks.
Yes, you can just disable the interrupts, and that is what I missed. The micros I'm used to using all have at least 1 interrupt that can't be disabled. It's usually called the NMI, or non-maskable interrupt. Given this, you have to have a non-interruptable test-and-set operation in order to successfully handle the allocation of resources. But since the 18F lets you disable ALL the interrupts, this is not a problem. Still, suppose you had an application that was extremely time sensative so that you didn't want to ever disable at least one of the interrupts. It would be nice the have the instruction so that you could still write the software that way if you wanted to.
Posts: 2924
Joined: May 25, 2005
From: PA, now MN via NJ,AZ,OR,CA
Status: offline
You probably already know this, but just to emphasize, the watchdog is not disabled with the other interrupts. There is no way to disable the watchdog once the system is running.
In an 18F you have high and low priority interrupts. You can disable all low priority interrupts or all interrupts. Depending on your timing requirements, you can configure your system with different priorities and have your scheduler disable only the low (or both high and low).
< Message edited by jspaarg -- Aug. 31, 2005 1:02:47 PM >
_____________________________
PM personal questions and observations only. Keep technical questions to the forums where everyone can benefit. When it comes to binary, there are 10 kinds of people: those who understand, and those who don't.
RE: Is the 18F family missing an instruction? - Aug. 31, 2005 1:33:50 PM
Guest
mickelsen, there is no atomic test/set instruction on the PIC16 or PIC18 (at least I couldnt find one). For the dsPIC there's the BTSTS (Bit Test then Set), that is able to test and secure a semaphore in one atomic operation, thus can be used to implement a MUTEX even with interrupts ON.
On the PIC16/18 there is no such atomic op, so you have to disable interrupts to secure a MUTEX.
WARNING: On PIC16 there is an obscure fact, not discussed often (I never saw it discussed in the forum, but I can have missed it), regarding disabling interrupts: - When you disable interrupts by clearing bit GIE, and an interrupt happens at cycle Q1 of that instruction (BCF INTCON,GIE), the bit gets cleared, and the interrupt is serviced! Then at the end of the interrupt service routine, the RETFIE instruction enables the GIE bit again. The critical section code thinks that interrupts are disabled and they are enabled. To overcome this, you have to implement a 'shadow interrupt enable' and the ISR return code check on the shadow bit and return with RETURN or RETFIE.
Does anyone know if the PIC18 has the same issue? My analysis of the datasheets leads me to conclude that PIC18s also suffer from this syndrome. I'm about to port my RTOS to PIC18, but preliminary analysis shows I'll have to continue to use the shadow GIE approach.
The above discussion may appear off-topic, but it's central to the design of an RTOS scheduler.
< Message edited by j_doin -- Aug. 31, 2005 5:36:54 PM >
Posts: 5416
Joined: Nov. 7, 2003
From: Morgan Hill, CA
Status: offline
I don't know how many of the 16-series chips have that problem; I'm sure that not all of them do.
Microchip published a workaround for the problem for those chips that do have it. IIRC, the code is:
int_dis:
bcf INTCON, GIE ; turn interrupts off
btfsc INTCON, GIE ; are they really off?
goto int_dis ; no, try turning them off agian
;
; here with interrupts guaranteed off
;
AFAIK, none of the 18-series chips have this problem.
_____________________________
While it's always good to learn from one's mistakes, it's much easier to learn from the mistakes of others. Please don't PM me with technical questions. I'll be quite happy to help (if I can) on the forums.
Posts: 1301
Joined: Nov. 7, 2003
From: Sweden
Status: offline
Hi
quote:
I don't know how many of the 16-series chips have that problem; I'm sure that not all of them do.
I remember this being discussed a while back. I did a quick search and found this. I don't know if this is the thread that I remember. Might be others too.
Posts: 2924
Joined: May 25, 2005
From: PA, now MN via NJ,AZ,OR,CA
Status: offline
I believe that I saw mention of this same problem in some posting within the last few weeks. I thought it was related to an 18F, but I'm not sure; so don't hold me to this comment.
I will check and see if I can find it.
_____________________________
PM personal questions and observations only. Keep technical questions to the forums where everyone can benefit. When it comes to binary, there are 10 kinds of people: those who understand, and those who don't.
RE: Is the 18F family missing an instruction? - Aug. 31, 2005 2:36:04 PM
Guest
BTW, that loop around GIE is irksome.
All PIC16 that I tested exhibit this behavior (87X, 87XA, 6XX). I believe it's not a glitch, in the PIC16 it is a side effect. I use a bit flag in global shared RAM and the ISR return is like this:
btfsc S_GIE ; S_GIE is 'SYSFLAGS,7'
retfie
return
Then at foreground threads the INTDIS macro does:
bcf S_GIE ; S_GIE is 'SYSFLAGS,7'
bcf INTCON, GIE
>>> EDITED: Changed STATUS, GIE to INTCON, GIE. Many thanks to jspaarg to point out the mistake ;-)
Posts: 2924
Joined: May 25, 2005
From: PA, now MN via NJ,AZ,OR,CA
Status: offline
quote:
bcf STATUS, GIE
Don't you mean
bcf INTCON,GIE ?
_____________________________
PM personal questions and observations only. Keep technical questions to the forums where everyone can benefit. When it comes to binary, there are 10 kinds of people: those who understand, and those who don't.
RE: Is the 18F family missing an instruction? - Sep. 10, 2005 8:40:33 AM
Guest
Disabling interrupts for atomic ops seems problematical though. Since there's no atomic test&set, how can you determine if interrupts were on before you do your atomic op?
Tha atomic op can't blindly enable interrupts, because they might have been off to begin with. And there's no way to atomically test the interrupt enable bit.
If you look at the write eeprom examples in the 18f1220 data sheet, they suffer from the same problem. They blindly disable, then re-enable interrupts. But what if interrupts were off before?
If there was a software interrupt, it would help. You would have to force a high priority interrupt of some kind, and it would acquire the mutex and save the previous interrupt state. For this to work thogh, it would need to be the only high priority interrupt.
RE: Is the 18F family missing an instruction? - Sep. 10, 2005 10:12:57 AM
Guest
quote:
ORIGINAL: pixpop
Disabling interrupts for atomic ops seems problematical though. Since there's no atomic test&set, how can you determine if interrupts were on before you do your atomic op? [...]It's actually a tricky problem.
It shure is. Mutexes are really needed for multitasking environments. But actually the lack of atomic test-branch-set operations is only critical in preemptive multitasking systems. The stack-limited 14bit cores (PIC16) are hardly a platform for preemptive multitasking, and Mutexes can be implemented in collaborative multitasking by limiting the shared resources to foreground threads only. The running tasks access the shared resources using state-machine driven algorithms, and interrupts are used for low-level system resources.
For preemptive systems, it's much more difficult. PIC18 and dsPIC have the stack and basic structure needed to implement fast preemptive multitask systems. The dsPIC instruction set have an atomic test-and-set instruction, BTSTS.
For PIC18, depending on system architecture, you can implement a central registrar for all mutexes, and make the mutex acquisition a operating system function. The system can have a FIFO queue of mutex requests, and manage the resource granting mechanism. The kernel thread can be the only thread running in high-priority.
But this rule out simpler implementations of mutexes. An atomic instruction would be much simpler.
RE: Is the 18F family missing an instruction? - Sep. 10, 2005 10:17:58 AM
Guest
quote:
ORIGINAL: pixpop
Tha atomic op can't blindly enable interrupts, because they might have been off to begin with. And there's no way to atomically test the interrupt enable bit.
This is another critical problem. The easiest rule is: never allow a thread to return to the kernel with interrupts disabled. If you have a critical section, disable ints, do the job, and enable ints, all without giving a change of another thread getting control.
WARNING: On PIC16 there is an obscure fact, not discussed often (I never saw it discussed in the forum, but I can have missed it), regarding disabling interrupts: - When you disable interrupts by clearing bit GIE, and an interrupt happens at cycle Q1 of that instruction (BCF INTCON,GIE), the bit gets cleared, and the interrupt is serviced! Then at the end of the interrupt service routine, the RETFIE instruction enables the GIE bit again. The critical section code thinks that interrupts are disabled and they are enabled.
This is explicitly documented in the datasheets of affected parts. E.g., from the 16C6X datasheet:
quote:
Note: For the PIC16C61/62/64/65, if an interrupt occurs while the Global Interrupt Enable bit, GIE is being cleared, bit GIE may unintentionally be re-enabled by the user’s Interrupt Service Routine (the RETFIE instruction). The events that would cause this to occur are:
1. An instruction clears the GIE bit while an interrupt is acknowledged 2. The program branches to the Interrupt vector and executes the Interrupt Service Routine. 3. The Interrupt Service Routine completes with the execution of the RETFIE instruction. This causes the GIE bit to be set (enables interrupts), and the program returns to the instruction after the one which was meant to disable interrupts. 4. Perform the following to ensure that interrupts are globally disabled.
LOOP BCF INTCON,GIE ;Disable Global ;Interrupt bit BTFSC INTCON,GIE ;Global Interrupt Disabled? GOTO LOOP ;NO, try again : ;Yes, continue with program flow
I haven't seen this mentioned in anything but older 16C parts; you say you are seeing it in newer 16F parts?
Posts: 2924
Joined: May 25, 2005
From: PA, now MN via NJ,AZ,OR,CA
Status: offline
quote:
disable ints, do the job, and enable ints
This can be a bad practice. Interrupts might not have been enabled at the start of the process. You need to copy the state of the interrupts prior to disabling them and then restore them
e.g.
movlw 0x80 ; position of GIE flag
andwf INTCON, w
movwf tempvar ; save just the GIE flag
... code here
movf tempvar, w
iorwf INTCON, f
_____________________________
PM personal questions and observations only. Keep technical questions to the forums where everyone can benefit. When it comes to binary, there are 10 kinds of people: those who understand, and those who don't.
RE: Is the 18F family missing an instruction? - Sep. 10, 2005 5:51:26 PM
Guest
Good point. Actually I use to do this, I should have been more comprehensive above. I have two sets of macros, one to unconditionally disable/enable ints, and the other to perform a critical section. The critical section does a push_intdis, pop_inten pseudo-operation, much similar to your approach, but using a single bit in the kernel system flags.
RE: Is the 18F family missing an instruction? - Sep. 10, 2005 6:50:21 PM
Guest
quote:
This can be a bad practice. Interrupts might not have been enabled at the start of the process. You need to copy the state of the interrupts prior to disabling them and then restore them
...
movlw 0x80 ; position of GIE flag andwf INTCON, w movwf tempvar ; save just the GIE flag
...
But that doesn't necessarily fix the problem. You could take a context switch sometime after your "andwf INTCON,w" instruction, but before you disable the interrupts, and that switch could leave interrupts off. Since you saved the state when they were on, your restore would turn them on when they were supposed to be off.
Presumably, it would be necessary to simply prohibit such behavior, as was previously suggested. A context switch must never change the state of GIE.
Perhaps that's not too much of a limitation. It's just something you have to remember. But if you forget, you'll open yourself up to a class of bugs that's very difficult to resolve.
RE: Is the 18F family missing an instruction? - Sep. 10, 2005 7:04:04 PM
Guest
To avoid this (interrupt enables messing), I impose the following coding rule: Every thread (object) runs in an interrupts ENABLED environment always. When a critical section inside an object needs processing, that object disables interrupts, performs the critical section, and re-enables interrupts. Since I (presently) never do preemptive context switching, I never had any interrupt problems. All my code make heavy use of interrupts and this "object model" has served well to large projects.
Now I'm porting my microkernel to the PIC18 architecture and started to face these problems (mutexes, preemptive scheduling and interrupts).