The first thing to do is to code and test the task. Here is an example of a task which is so brief that it can be done without using a timer. It requires only twelve (12) BYTEs of FLASH memory and ten (10) clock cycles, plus the system calling overhead. It simply toggles Discrete Output #2:
After assembling it to address 0x0FF0, for example, the resulting code can be inserted into the running device. First verify that there are no other routines already at that location or in the vicinity:ToggleDIO2: IN R25, PORTC ; Read and freeze the present DIO #2 value SBRC R25, PORTC2 ; If DIO #2 was OFF, skip turning it OFF again CBI PORTC, PORTC2 ; Clear the bit directly to turn DIO #2 OFF SBRS R25, PORTC2 ; If it was ON, skip the next instruction SBI PORTC, PORTC2 ; Set the bit directly to turn DIO#2 ON RET
There are two steps to cause it to be called each main() cycle. The first is to initialize EEfptrEachMain to point to that address. The second is to enable that system feature by turning BIT_SM_EACHMAIN in EEbSystemMode ON. The example below also shows what impact it has on the device's processing:> D+P 0xFE0 32 FLASH (program memory) contents: 0FE0: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0FF0: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 1000: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ >; Login with '$' as the first character on this line and send the block m>:100FF00098B192FD429892FF429A08950000000035 m>:00000001FF m>:00000001FF m>D+P 0xFE0 48 FLASH (program memory) contents: 0FE0: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0FF0: 98 B1 92 FD 42 98 92 FF-42 9A 08 95 00 00 00 00 ....B...B....... 1000: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ m>@ 0xFF0 ; Test - call the subroutine to turn LED #2 ON m>@ 0xFF0 ; Test - call the subroutine to turn LED #2 OFF m>
The difference seems to be about 1,200 cycles through the main() loop each second, or about 5% of the processing time. With the little subroutine still being called each loop through main, what happens when the FLASH memory which contains that subroutine is reset? The "X 0xFF0" command below will only work in one of the privileged modes.> DES EEPROM contents: 0000: 10 21 00 9F 01 00 84 FF-04 00 FF FF 28 3C 50 FF .!..........(<.. 0010: C0 00 3F FF 40 08 03 67-FF 25 74 FF FF FF FF FF ..?.@..g.%t..... 0020: 24 28 05 00 FF FF 2A FF-FF 14 30 20 00 30 FF FF $(....*...0 .0.. 0030: 80 16 FF FF FF FF FF FF-60 00 B0 00 80 01 FF FF ........`....... 0040: FF FF FF FF FF FF 00 2F-FF FF FF FF FF FF FF FF ......./........ >DES >EW 0x42 = 0xFF0 ; Set its address in EEfptrEachMain EEPROM contents: 0000: 10 21 00 9F 01 00 84 FF-04 00 FF FF 28 3C 50 FF .!..........(<.. 0010: C0 00 3F FF 40 08 03 67-FF 25 74 FF FF FF FF FF ..?.@..g.%t..... 0020: 24 28 05 00 FF FF 2A FF-FF 14 30 20 00 30 FF FF $(....*...0 .0.. 0030: 80 16 FF FF FF FF FF FF-60 00 B0 00 80 01 FF FF ........`....... 0040: FF FF F0 0F FF FF 00 2F-FF FF FF FF FF FF FF FF ......./........ >E 4 ^= 16 ; Toggle BIT_RTC_SEC_PRG_HZ in EEbFlags_RTC >Main program Hz: 2,372 Main program Hz: 2,388 Main program Hz: 2,383 Main program Hz: 2,384 Main program Hz: 2,383 Main program Hz: 2,389E 1 ^= 4 ; Toggle BIT_SM_EACHMAIN in EEbSystemMode >Main program Hz: 2,374 Main program Hz: 2,261 Main program Hz: 2,266 Main program Hz: 2,261 Main program Hz: 2,261 Main program Hz: 2,265 Main program Hz: 2,261E 1 ^= 4 >Main program Hz: 2,248 Main program Hz: 2,384 Main program Hz: 2,388 Main program Hz: 2,384 >
What happened was that the EachMain() system routine stopped calling the subroutine at 0x0FF0. It uses the ICALL_IfValid_EEPROM System Function and will not call a subroutine when the WORD at its target address is 0xFFFF. That feature is to help prevent system crashes.> ; Log back in m>DF+ 0xFE0 48 FLASH (program memory) contents: 0FE0: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0FF0: 98 B1 92 FD 42 98 92 FF-42 9A 08 95 00 00 00 00 ....B...B....... 1000: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ m>E 4 ^= 16 m>Main program Hz: 2,255 Main program Hz: 2,261 Main program Hz: 2,261 Main program Hz: 2,261 Main program Hz: 2,266X 0xFF0 ; Reset the block from 0x0F80 through 0x0FFF to all 0xFFs m>Main program Hz: 2,252 Main program Hz: 2,270 Main program Hz: 2,274 Main program Hz: 2,269 Main program Hz: 2,272 Main program Hz: 2,270DF+ 0xFE0 48 FLASH (program memory) contents: 0FE0: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0FF0: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 1000: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ m>Main program Hz: 2,201 Main program Hz: 2,270 Main program Hz: 2,272 m>
A good thing to remember to do at this stage is to both reset the EEfptrEachMain subroutine pointer (to 0xFFFF) and clear BIT_RTC_SEC_PRG_HZ in EEbFlags_RTC. If they remain in their present state and the a different routine is loaded using that location, EachMain() may jump into the middle of that routine. That will create a bug that is very difficult to find or one that requires using the lockout recovery procedure to reset the EEbFlags_RTC variable using jumpers. Those commands are:
> DES EEPROM contents: 0000: 10 25 00 9F 01 00 84 FF-04 00 FF FF 28 3C 50 FF .%..........(.P. 0010: C0 00 3F FF 40 08 03 67-FF 25 74 FF FF FF FF FF ..?.@..g.%t..... 0020: 24 28 05 00 FF FF 2A FF-FF 14 30 20 00 30 FF FF $(....*...0 .0.. 0030: 80 16 FF FF FF FF FF FF-60 00 B0 00 80 01 FF FF ........`....... 0040: FF FF F0 0F FF FF 00 2F-FF FF FF FF FF FF FF FF ......./........ >EW 0x42 = -1 ; Reset EEfptrEachMain >E 1 != 4 ; Clear BIT_RTC_SEC_PRG_HZ >DES EEPROM contents: 0000: 10 21 00 9F 01 00 84 FF-04 00 FF FF 28 3C 50 FF .!..........(.P. 0010: C0 00 3F FF 40 08 03 67-FF 25 74 FF FF FF FF FF ..?.@..g.%t..... 0020: 24 28 05 00 FF FF 2A FF-FF 14 30 20 00 30 FF FF $(....*...0 .0.. 0030: 80 16 FF FF FF FF FF FF-60 00 B0 00 80 01 FF FF ........`....... 0040: FF FF FF FF FF FF 00 2F-FF FF FF FF FF FF FF FF ......./........ >
See also: | |
The iHex and erase FLASH block System Commands as well as the longer embedded timers example. |