10/27/2006

Come Again, What's the Cost and Overhead?

I've been implementing object-based stuff in C for embedded firmware with passing an index parameter to an array of structs, like I tried to explain here. Yesterday I remembered an article about pointer-less C in Embedded System Design and thought I will give it a couple minutes more. The article gives some ideas how to make pointers safer to use and talks about the cost and benefit of using pointers. I'm not saying anything about the value of article itself, but I got curious. I took our simple switch debounce filter routine which is used a lot, and which is typically the only one that actually implements multiple objects at run time. It uses the me index as parameter for two functions. I quickly modified the code so that both functions take in a pointer to a struct instead of simple unsigned char. I compiled both versions for Microchip 16F876A (8-bit uC) and got surprised. The pointer version used over 30% less code memory than the index version, reducing the ROM image from above 300 words to below 200 words. I then compiled the source files to give me the assy listing, and below are the results that I found for a simple function that just sets some members of a struct. Because of werd mechanism of indirect addressing in PIC micros, the pointer is actually passed just as a 8-bit register. Word of caution; we have experienced problems when passing pointers and enabling optimization with Hi-Tech compilar for PIC micros, that is another reason why we have avoided this.

The lesson; while I do believe in intuition for great solutions, it is worth to challenge your beliefs every once in a while.

Pointer version:


30 0764 _Cbutton_construct
31 ;button_ptr.c: 27: me->debounceCounter = 0;
32
33 0764 0084 movwf fsr
34
35 0765 1383 bcf 3,7
36 0766 0180 clrf 0
37 ;button_ptr.c: 28: me->level = !1;
38
39 ; _me assigned to ?a_Cbutton_construct+0
40 0000 _Cbutton_construct$me set
?a_Cbutton_construct+0
41 ;_me stored from w
42 0767 1283 bcf status,5
43 0768 1303 bcf status,6 ;carry unused
44 0769 00A8 movwf (((?a_Cbutton_construct+0)))
45 076A 0A28 incf (((?a_Cbutton_construct+0))),w
46 076B 0084 movwf fsr
47
48 076C 1383 bcf 3,7
49 076D 0180 clrf 0



Index version:


30 06F6 _Cbutton_construct
31 ;button.C: 27: theButton[meIndex].
debounceCounter = 0;
32
33 global _theButton
34 ; _meIndex assigned to ?a_Cbutton_construct+0
35 0000 _Cbutton_construct$meIndex set ?a_
Cbutton_construct+0
36 ;_meIndex stored from w
37 06F6 1283 bcf status,5
38 06F7 1303 bcf status,6 ;carry unused
39 06F8 00A8 movwf (((?a_Cbutton_construct+0)))
40 06F9 0828 movf (((?a_Cbutton_construct+0))),w
41 06FA 00F0 movwf btemp
42 06FB 1003 bcf status,0
43 06FC 0DF0 rlf btemp
44 06FD 1003 bcf status,0
45 06FE 0D70 rlf btemp,w
46 06FF 3E20 addlw ((_theButton))
47 0700 0084 movwf fsr
48
49 0701 1383 bcf 3,7
50 0702 0180 clrf 0
51 ;button.C: 28: theButton[meIndex].level = !1;
52
53 0703 0828 movf (((?a_Cbutton_construct+0))),w
54 0704 00F0 movwf btemp
55 0705 1003 bcf status,0
56 0706 0DF0 rlf btemp
57 0707 1003 bcf status,0
58 0708 0D70 rlf btemp,w
59 0709 00F0 movwf btemp
60 070A 0A70 incf btemp,w
61 070B 3E20 addlw ((_theButton))
62 070C 0084 movwf fsr
63
64 070D 1383 bcf 3,7
65 070E 0180 clrf 0

No comments: