Microcontroller Cycle
With each cycle of the microcontroller an instruction is executed. But before that happens, several other things have to be done. First, the Power-Down (PD) and Sleep (SLP) bits of the Power Control Register (PCON) are checked. If either of them are set, it means the microcontroller is either in Sleep or in Power-Down mode, and the whole cycle is skipped. Timers are not incremented, interrupts are not polled and no instruction is executed.
If the microcontroller is not in Sleep or Power-Down modes, timers are incremented and interrupts are polled. After that, the Idle Mode bit (IDL) of the Power Control Register (PCON) is checked. If it is set that means the microcontroller is in Idle Mode, and the rest of the cycle is skipped. Otherwise the sequence continues, and the current instruction pointed to by the Program Counter Register (PC) is loaded and executed.
Microcontroller Cycles are sometimes called C-Cycles, which stands for Computational Cycles.
A brief recap of the Microcontroller Cycle sequence:
- If bits
PDorSLPare set, the whole cycle is skipped. - Timers are incremented
- Interrupts are polled
- If bit
IDLis set, instruction execution is skipped. - The current instruction is executed
Each of the steps of the sequence will now be explained in detail.
Timer increment
Timer clocks are incremented every microcontroller cycle according to the settings on the Timer Control Register (TCON). The microcontroller cycles through each of the four timers, checking wether or not they should be incremented and, if they should, increments the value of the corresponding Timer Special Function Register (TIM0 through TIM3).
For each of the timers, first of all the corresponding Timer Enabled bit (TRn) of the Timer Control Register (TCON) is checked. If the TRn bit is not set, the rest of this timer's sequence is skipped. Then the corresponding Timer Gate bit (GATEn) of the Timer Control Register (TCON) is checked and, if it is set and the corresponding Gate Active bit (XGn) of the External Port Control Register (XCON) is not set, the rest of this timer's sequence is skipped. Finally, the corresponding Counter/Timer Select bit (CTn) of the Timer Control Register (TCON) is checked and, if it is set and the corresponding Port Received bit (XIn) of the External Port Control Register (XCON) is not set, the rest of this timer's sequence is skipped.
If none of the above applied and the Timer is not skipped, the corresponding Timer Register (TIMn) for this Timer is incremented by one. If this makes the Timer overflow, that is its value before being increased was 0xFFFF, the Timer is reset to the value stored at the corresponding Timer Reload Register (TREn) and the corresponding Timer Overflow bit (TFn) of the Timer Control Register (TCON) is set.
A brief recap of the timer increase sequence as applied to each of the four timers:
- If bit
TRnis not set skip this Timer. - If bit
GATEnis set and bitXGnis not set skip this Timer. - If bit
CTnis set and bitXInis not set skip this Timer. - Register
TIMnis increased by one. - If the timer overflows
0xFFFF:- Register
TIMnis reset to the value of registerTREn. - Bit
TFnis set.
- Register
Interrupt polling
Interrupts are polled every microcontroller cycle according to the settings on the Interrupt Enable Register (IE). The order by which interrupts are polled depends on the priorities assigned to them on the Interrupt Priority Register (IP). If there is an interrupt currently being serviced, as denoted by the Interrupt Status Word Register (ISW), only interrupts with a higher priority will be polled. All other interrupts will be ignored. Finally, if an interrupt is triggered, the current Program Counter (PC) is pushed to the stack and then reset with the address of the corresponding interrupt service routine, as dictated by the corresponding Interrupt Service Routine Register (ISRP0 through ISRP7 and ISRT0 through ISRT3). Several bits are written to the Interrupt Status Word Register (ISW) to let the system know an interrupt is in progress and what its priority is.
When considering interrupt priorities, the following rules apply:
- Nothing can interrupt a high-priority interrupt — not even another high-priority interrupt.
- A high-priority interrupt may interrupt a low-priority interrupt.
- A low-priority interrupt may only occur if no other interrupt is already executing.
- If two interrupts occur at the same time, the interrupt with higher priority will execute first. If both interrupts are of the same priority the interrupt which is serviced first by polling sequence will be executed first.
When interrupt polling takes place, the Enable All Interrupts bit (EA) of the Interrupt Enable Register (IE) is first checked. If it is not set, interrupt polling is skipped. Otherwise, the Interrupt Status Flag (IFS) and the Interrupt Priority Flag (IFP) bits of the Interrupt Status Word Register (ISW) are checked. If both of them are set, this means there is currently a high-priority interrupt in progress. Since this kind of interrupt can not be interrupted because there can be no other interrupt with a higher priority, interrupt polling is skipped.
If none of the above applies, this means an interrupt could potentially be triggered, and thus interrupt polling must occur. High-priority interrupts are then checked since, even if an interrupt is currently in progress, it can not be a high-priority one. High-priority interrupts are those with the corresponding Interrupt Priority bit (PPn or PTn) of the Interrupt Priority Register (IP) set. Only enabled interrupts are checked, that is, those with the corresponding Interrupt Enable bit (EPn or ETn) of the Interrupt Enable Register (IE) set. A high-priority interrupt is then triggered if the corresponding bit for that kind of interrupt is set. The bit checked depends on the kind of interrupt being polled. For Timer Interrupts this bit is the corresponding Timer Overflow bit (TFn) of the Timer Control Register (TCON). For External Port Interrupts this bit is the corresponding Port Received bit (XIn) of the External Port Control Register (XCON).
If no high-priority interrupt has been triggered so far, and another interrupt is not currently in progress, low-priority interrupts are then polled. The Interrupt Status Flag (IFS) of the Interrupt Status Word Register (ISW) is checked to see if an interrupt is currently in progress. If this bit is set, low-priority interrupts are not polled. Otherwise low-priority interrupts are polled in the same way as high-priority interrupts, the only difference being that, if the corresponding bit is set, a low-priority interrupt will be triggered instead of a high-priority one.
The polling order of interrupts of the same priority is the following:
- Port 0 Interrupt.
- Timer 0 Interrupt.
- Port 1 Interrupt.
- Timer 1 Interrupt.
- Port 2 Interrupt.
- Timer 2 Interrupt.
- Port 3 Interrupt.
- Timer 3 Interrupt.
- Port 4 Interrupt.
- Port 5 Interrupt.
- Port 6 Interrupt.
- Port 7 Interrupt.
Whenever an interrupt is triggered, whether it be a high-priority or a low-priority one, interrupt polling will stop so that no further interrupts can be triggered during the current microcontroller cycle. The bit that triggered the interrupt is first cleared. This bit will be the Port Received bit (XIn) of the External Port Control Register (XCON) for External Port interrupts, or the Timer Overflow bit (TFn) of the Timer Control Register (TCON) for Timer Interrupts. The Interrupt Status Flag (IFS) of the Interrupt Status Word Register (ISW) is checked to see if another interrupt was already in progress. If that was the case, the Interrupt On Hold Flag (IFH) of the Interrupt Status Word Register (ISW) will be set. If no interrupt was in progress the Interrupt Status Flag (IFS) will be set and the Interrupt On Hold Flag (IFH) will be cleared, both located in the Interrupt Status Word Register (ISW). In both cases, the Idle Mode Flag (IDL) of the Power Control Register (PCON) will be cleared to ensure that, if the system was in Idle Mode, the interrupt makes it exit that mode.
If the triggering interrupt was a high-priority one, the Interrupt Priority Flag (IFP) of the Interrupt Status Word Register (ISW) will be set. If it was a low-priority one, it will be cleared. Then the current Program Counter Register (PC) will be pushed into the stack, incrementing the Stack Pointer Register (SP) accordingly. Finally, the Program Counter Register (PC) will be overwritten with the value of the Interrupt Service Routine Register corresponding the type of interrupt triggered. This will be the corresponding External Port Interrupt Service Routine Register (ISRPn) for External Port Interrupts, and the corresponding Timer Interrupt Service Routine Register (ISRTn) for Timer Interrupts. This will make the microcontroller launch the appropriate Interrupt Service Routine, which will be executed until a RETI instruction is executed, retrieving the previous Program Counter Register (PC) value from the stack and updating the Interrupt Status Word Register (ISW) as needed.
A brief recap of the interrupt polling sequence:
- If bit
EAis not set skip interrupt polling. - If both bits
IFSandIFPare set skip interrupt polling. - Poll high-priority interrupts:
- If bits
EP0,PP0andXI0are set, trigger a high-priority interrupt forXI0serviced byISRP0. - If bits
ET0,PT0andTF0are set, trigger a high-priority interrupt forTF0serviced byISRT0. - If bits
EP1,PP1andXI1are set, trigger a high-priority interrupt forXI1serviced byISRP1. - If bits
ET1,PT1andTF1are set, trigger a high-priority interrupt forTF1serviced byISRT1. - If bits
EP2,PP2andXI2are set, trigger a high-priority interrupt forXI2serviced byISRP2. - If bits
ET2,PT2andTF2are set, trigger a high-priority interrupt forTF2serviced byISRT2. - If bits
EP3,PP3andXI3are set, trigger a high-priority interrupt forXI3serviced byISRP3. - If bits
ET3,PT3andTF3are set, trigger a high-priority interrupt forTF3serviced byISRT3. - If bits
EP4,PP4andXI4are set, trigger a high-priority interrupt forXI4serviced byISRP4. - If bits
EP5,PP5andXI5are set, trigger a high-priority interrupt forXI5serviced byISRP5. - If bits
EP6,PP6andXI6are set, trigger a high-priority interrupt forXI6serviced byISRP6. - If bits
EP7,PP7andXI7are set, trigger a high-priority interrupt forXI7serviced byISRP7.
- If bits
- If bit
IFSis not set, poll low-priority interrupts:- If bits
EP0andXI0are set, trigger a low-priority interrupt forXI0serviced byISRP0. - If bits
ET0andTF0are set, trigger a low-priority interrupt forTF0serviced byISRT0. - If bits
EP1andXI1are set, trigger a low-priority interrupt forXI1serviced byISRP1. - If bits
ET1andTF1are set, trigger a low-priority interrupt forTF1serviced byISRT1. - If bits
EP2andXI2are set, trigger a low-priority interrupt forXI2serviced byISRP2. - If bits
ET2andTF2are set, trigger a low-priority interrupt forTF2serviced byISRT2. - If bits
EP3andXI3are set, trigger a low-priority interrupt forXI3serviced byISRP3. - If bits
ET3andTF3are set, trigger a low-priority interrupt forTF3serviced byISRT3. - If bits
EP4andXI4are set, trigger a low-priority interrupt forXI4serviced byISRP4. - If bits
EP5andXI5are set, trigger a low-priority interrupt forXI5serviced byISRP5. - If bits
EP6andXI6are set, trigger a low-priority interrupt forXI6serviced byISRP6. - If bits
EP7andXI7are set, trigger a low-priority interrupt forXI7serviced byISRP7.
- If bits
When an interrupt is triggered, this sequence occurs:
- Clear the triggering bit (
XInorTFn). - If bit
IFSis set, set bitIFH; otherwise clear it. - Unconditionally set bit
IFS. - Unconditionally clear bit
IDL. - If it is a high-priority interrupt, set bit
IFP; otherwise clear it. - Increment
SPby one and then writePCto the internal memory address pointed to bySP. - Overwrite
PCwith the value of the appropriate Interrupt Service Routine Register (ISRPnorISRTn). - The interrupt polling sequence is finished and no further interrupt polling takes place this microcontroller cycle.
Instruction execution
The microcontroller will load the instruction located in the memory address pointed to by the Program Counter Register (PC), execute it and then update the Program Counter Register (PC). The actual instruction's opcode is loaded into the Instruction Register (IR). The value of the first operand is loaded into the Operand 1 Register (O1R) and the value of the second operand into the Operand 2 Register (O2R). The memory addresses pointed by each operand are loaded into the Effective Address 1 Register (EA1R) and the Effective Address 2 Register (EA2R).
During execution of the instruction, several things can happen depending on the instruction being executed, including updating several registers, memory locations, sending data to external ports and much more. Detailed information on what each instruction does can be found in the Instruction Set section of the documentation.
The instruction being executed determines the new value that the Program Counter Register (PC) will have after executing it. For normal instructions, the Program Counter Register (PC) will be increased by one, two or three, depending on the number of operands of the instruction. If the instruction has no operands, the Program Counter Register (PC) will be increased by one, thus pointing at the next instruction. If it has one or two operands, it will be increased by two or three respectively, to prevent it from pointing at the instruction's operands instead of pointing at the next instruction.
For program-flow instructions (including program-flow bit instructions), the new value of the Program Counter Register (PC) will depend on the result of the instruction. If the instruction was an unconditional jump (for example JMP) or a conditional jump whose condition for branching is met (for example JZ when the value of its first operand is 0x0000), the Program Counter Register (PC) will be updated with the value of the relevant operand. If the instruction was a conditional jump whose condition for branching was not met (for example JZ when the value of the first operand is not 0x0000), the Program Counter Register (PC) will be incremented just like it would be for a normal instruction (that is, it will be incremented by one plus the number of operands).
Some special instruction, namely RET and RETI will update the Program Counter Register (PC) with a value popped from the stack. Please refer to the definition of those instructions in the Instruction Set section of the documentation.
A brief recap of the instruction execution sequence:
- Instruction is loaded from memory address
PCinto registersIR,O1R,O2R,EA1RandEA2R. - Instruction is executed.
PCis updated depending on the instruction being executed:- If a jump takes place, the
PCis updated with the relevant operand's value. - Otherwise, the
PCis increased by one plus the number of operands.
- If a jump takes place, the