This is a snippet from a general-purpose library function that is (effectively) non-application specific and, by design, can make no assumptions about the context of the calling process. Hint: The assumption the code makes has to do with interrupts. Do you see a problem?
_GenericFunctionA: MOV A, R7 RL A ADD A, #array_base MOV R0, A CLR EA MOV A, @R0 JNB ACC.BIT_X, ?C0026 JNB ACC.BIT_Y, ?C0026 SETB ACC.BIT_Z ?C0026: SETB ACC.BIT_N XCH A, @R0 SETB EA JB ACC.BIT_N, ?C0027 MOV R7, #0 RET ?C0027: MOV R7, #1 RET
The assumption is that interrupts are enabled. This may not be the case. The following is the Keil C51 function prefix to save and disable EA state:
;On function entry, this code saves ;the state of EA and clears EA. 0000 D3 SETB C 0001 10AF01 JBC EA,?C0004 0004 C3 CLR C 0005 ?C0004: 0005 C0D0 PUSH PSW
;On function exit, this code restores ;the state of EA. 0020 D0D0 POP PSW 0022 92AF MOV EA,C
Jon, You are correct sir. Would you care to guess where I got the snippet?
Well, if it's from our library then we should fix this problem. Where did it come from? And, do you have a snippit of code I can compile to reproduce it? Jon
Its from RTX Tiny (oops). I changed the names in the example, but if search through the code you'll find several cases where global interrupts are disabled (via clr EA) and then reenabled (via setb EA) with no regards to the context of the calling process. Granted, when this happens within scope of the RTX interrupt itself, its no problem as this bit must have been set for the interrupt to happen in the first place. Other functions, however, such as _os_create_task, the wait functions, and pretty much every support function makes this mistake. Granted, most people will have interrupts enabled when things are up and running and these functions are being used, but IMO its a wrong for RTX to assume this. Perhaps the best example of when the forground process would require interrupts to remain disabled is during startup...but _os_create_task takes the liberty of SETB EA.
Robert, A URTOS such as Rtx will, in may cases, "know" what the interrupt status is and thus not have to worry about what you show. ANYONE that insist on using a URTOS that allow app control of interrupts will have to spend a lot of time on sorting out interrupt conflicts between the app and the URTOS. Thus, in my opinion, if an OS allow ANY interrupt handling by the app (i.e. does not control ALL I/O via device drivers), that URTOS should be trashed since sorting out using it takes more time than is saved by using it. Erik
Eric, I couldn't agree more. If it were my choice, I wouldn't be using an RTOS on in '51 in the first place. Kinda like dropping a 440 Hemi into a Geo Metor. Problem is, its not my decision. RTX for a '51 is never going to provide as complete an abstraction layer as, say, NT or similar. Its a microcontroller and applications are going to have to cooperate with the interrupt structure. All that aside; for the functions I mentioned, particularly os_create_task, to assume interrupts were enable coming into the function is not what I'd call the best programming technique. That's all.
All that aside; for the functions I mentioned, particularly os_create_task, to assume interrupts were enable coming into the function is not what I'd call the best programming technique. Why? Most of the embedded programs I've created used interrupts. I enable global intsrrupts (EA=1) and assume that they stay enabled all the time (except when there is some kind of critical section). For instance, when I call printf I still want my serial receive interrupt to work. If I disabled interrupts that would not happen. RTX51 Tiny is a Tiny RTOS. Like most RTOS, a timer tick interrupt service routine is used to manage tasks, events, and blocking. If you disable interrupts, RTX51 Tiny will fail to update this information and will stop switching tasks. For that reason, interrupts must be enabled at most all times. I have tried to clarify this in the documentation at http://www.keil.com/support/man/docs/tr51/tr51_interrupts.htm. Here's something to consider. If you need to disable interrupts for extended periods of time that extend beyond one task (the only real reason to call an RTX51 Tiny Library Routine is to switch tasks) then is your program REALLY real-time? And, is a real-time OS necessary? Jon
In nearly ALL program startup cases, I don't want interrupts enabled until everything is set up and ready to run. This includes module initialization as well as task instantiation. The last thing you do is hit the "let-er-rip" which basically does the final EA. Its a way to ensure that all cooperative operations wait until everything's ready to go. That the os_create_task forces interrupts to be set basically states that I can't write a driver that completely encapsulates all related hardware initialization...namely particular interrupts associated with that hardware. Instead, I have to put a note somewhere that says, "Oh, BTW, you have to add a separate line to actually enable this driver's interrupt AFTER any calls to os_create_task"...and hope the user reads it. None of this would be a problem if the the RTX code used the method your first reply illustrated.
In the RTX51 Tiny applications I've written, I do all of the hardware initialization in task 0 (which is called first). I disable interrupts while I do this. Then, I re-enable interrupts and call the os_create_task to create all of my remaining tasks. Jon
Yes, I can see where it can be a matter of technique. I've never used RTX before my current stint and I guess I'm just not that accustomed to giving up control of EA :o)
I'm just not that accustomed to giving up control of EA The moment you decide to use a URTOS, you give up that control. You can't have it both ways. Erik
The moment you decide to use a URTOS, you give up that control. You can't have it both ways. Yep. That's pretty much the way it is with all RTOS. Jon
The moment you decide to use a URTOS, you give up that control. Correction: The moment someone else decided to us a URTOS, they took that control away from me. >:(
The moment you decide to use a URTOS, you give up that control. Correction: The moment someone else decided to us a URTOS, they took that control away from me. If you were told to us a URTOS, then yoiur "correction" is correct. If your statement tries to blame the maker of the URTOS then blatantly incorrect. There is no way anyone can make something that uses interrupts and truly state "you can do with interrupts whatevere you want, it does not affect me". "truly" in bold, because I have seen that lie. Erik