EmbeddedRelated.com
Forums

PUSHF equivalent for HCS08 uc ??

Started by Ether Jones December 15, 2006
Does anyone know how to "push flags" on the HCS08 series
microcontrollers?

I have a section of code that I need to make non-interruptable.  But I
can't simply do this:

DisableInterrupts
<non-interruptable code here>
EnableInterrupts

... because I don't know whether or not interrupts were disabled in the
first place, and if they were disabled, I don't want to enable them.  I
want to leave things the way I found them.

In the Intel world, I'd just do this:

PUSHF  (push flags)
DisableInterrupts
<non-interruptable code here>
POPF  (pop flags, restoring whatever state existed before I disabled
interrupts)

I read all the docs I could find, but never saw this issue addressed.
It says that the "CCR" register contains the global interrupt flag, but
there's no assembly instruction to read it or push it unto the stack.

Does anyone have a solution for this?


On Dec 15, 5:28 pm, "Ether Jones" <EtherJo...@yahoo.com> wrote:
> Does anyone know how to "push flags" on the HCS08 series > microcontrollers?
...
> I read all the docs I could find, but never saw this issue addressed. > It says that the "CCR" register contains the global interrupt flag, but > there's no assembly instruction to read it or push it unto the stack. > > Does anyone have a solution for this?
Ether, Use the sequence: TPA (transfer the CCR to the ACC) PSHA (put on the stack) SEI ... PULA TAP (Transfer ACC to CCR) ... kevin
kevinjwhite@comcast.net wrote:

> Ether, > > Use the sequence: > > TPA (transfer the CCR to the ACC) > PSHA (put on the stack) > SEI > ... > PULA > TAP (Transfer ACC to CCR) > ...
Thanks. If I am putting this into a macro to be used in C code, I assume I have to save and restore the A register (see modified code below)? Or, do most C compilers nowadays examine in-line asm code and automatically do the extra PSH and PUL? PSHA (save A contents) TPA (transfer the CCR to the ACC) PSHA (put on the stack) SEI ... PULA (retrieve copy of A containing CCR) TAP (Transfer ACC to CCR) PULA (restore original A contents)
Ether Jones wrote:
> kevinjwhite@comcast.net wrote: > >> Use the sequence: >> >> TPA (transfer the CCR to the ACC) >> PSHA (put on the stack) >> SEI >> ... >> PULA >> TAP (Transfer ACC to CCR) >> ... > > If I am putting this into a macro to be used in C code, I assume I > have to save and restore the A register (see modified code below)? > Or, do most C compilers nowadays examine in-line asm code and > automatically do the extra PSH and PUL?
That would be wrong. The system can be interrupted anywhere, so you need a safe sequence. I suggest (using the same opcodes): PSHA ; save A TPA ; condition codes to A SEI ; disable interrupts PSHA ; save old interrupt status ... PULA ; get old interrupt status TAP ; to condition codes PULA ; restore A If all interrupts use the same sequence, then another interrupt will not lose information. The PSHA ... PULA sequence now cannot be interrupted. -- Chuck F (cbfalconer at maineline dot net) Available for consulting/temporary embedded and systems. <http://cbfalconer.home.att.net>

On Dec 16, 10:10 am, CBFalconer <cbfalco...@yahoo.com> wrote:
> Ether Jones wrote:
...
> > If I am putting this into a macro to be used in C code, I assume I > > have to save and restore the A register (see modified code below)? > > Or, do most C compilers nowadays examine in-line asm code and > > automatically do the extra PSH and PUL?That would be wrong. The system can be interrupted anywhere, so > you need a safe sequence. I suggest (using the same opcodes): > > PSHA ; save A > TPA ; condition codes to A > SEI ; disable interrupts > PSHA ; save old interrupt status > ... > PULA ; get old interrupt status > TAP ; to condition codes > PULA ; restore A > > If all interrupts use the same sequence, then another interrupt > will not lose information. The PSHA ... PULA sequence now cannot > be interrupted. >
... That will work but is not necessary - It is safe as originally written - if the procesor gets interrupted after the TPA but before the PSHA then it is the ISR's responsibility to restore the ACC to the state before the interrupt. This is not an additional requirement on the ISR, ISRs always have to put things back how they found them. The critical section between the SEI and the TAP is still protected. kevin
kevinjwhite@comcast.net wrote:
> On Dec 16, 10:10 am, CBFalconer <cbfalco...@yahoo.com> wrote: > > Ether Jones wrote: > ... > > > If I am putting this into a macro to be used in C code, I assume I > > > have to save and restore the A register (see modified code below)? > > > Or, do most C compilers nowadays examine in-line asm code and > > > automatically do the extra PSH and PUL?That would be wrong. The system can be interrupted anywhere, so > > you need a safe sequence. I suggest (using the same opcodes): > > > > PSHA ; save A > > TPA ; condition codes to A > > SEI ; disable interrupts > > PSHA ; save old interrupt status > > ... > > PULA ; get old interrupt status > > TAP ; to condition codes > > PULA ; restore A > > > > If all interrupts use the same sequence, then another interrupt > > will not lose information. The PSHA ... PULA sequence now cannot > > be interrupted. > > > ... > > That will work but is not necessary - It is safe as originally written > - if the procesor gets interrupted after the TPA but before the PSHA > then it is the ISR's responsibility to restore the ACC to the state > before the interrupt. This is not an additional requirement on the > ISR, ISRs always have to put things back how they found them.
Yes. And if such were not the case, Chuck's code wouldn't be safe either. If an interrupt occurred between his TPA and SEI, and the ISR did not preserve register A, then his PSHA would push the wrong contents onto the stack. As it turns out though, with the compiler I am using, I discovered after a bit of experimenting and examining disassembly files that the following shorter sequence is safe: TPA ; condition codes to A PSHA ; save old interrupt status SEI ; disable interrupts ... PULA ; get old interrupt status TAP ; to condition codes ... because the compiler actually examines the assembly code, and if A is changed in any way, the compiler inserts code to as necessary to maintain integrity. For example, if I have the code byte1 = 1; byte2 = 2; Then the compiler generates LDA #1 STA byte1 STA byte2 And if I have the following code: byte1 = 1; __asm PSHH; PULH; byte2 = 1; The compiler generates LDA #1 STA byte1 PSHH PULH STA byte2 But if I have the following code: byte1 = 1; __asm PSHA; PULA; byte2 = 1; The compiler generates LDA #1 STA byte1 PSHA PULA LDA #1 STA byte2 (The compiler isn't smart enough to figure out that PSHA/PULA didn't change Register A, so it errs on the safe side and re-loads A). In other words, the compiler doesn't assume that Register A is preserved in the assembly code, if A is accessed.
Ether Jones wrote:

> Does anyone know how to "push flags" on the HCS08 series > microcontrollers? > > I have a section of code that I need to make non-interruptable. But I > can't simply do this: > > DisableInterrupts > <non-interruptable code here> > EnableInterrupts > > ... because I don't know whether or not interrupts were disabled in the > first place, and if they were disabled, I don't want to enable them. I > want to leave things the way I found them. > > In the Intel world, I'd just do this: > > PUSHF (push flags) > DisableInterrupts > <non-interruptable code here> > POPF (pop flags, restoring whatever state existed before I disabled > interrupts) > > I read all the docs I could find, but never saw this issue addressed. > It says that the "CCR" register contains the global interrupt flag, but > there's no assembly instruction to read it or push it unto the stack. > > Does anyone have a solution for this?
Do the interrupt sources not have their own enable flag? If they do, like all the other micros in my experience, then your original idea will work fine. Thats what a global interrupt enable flag is for.