c_tips_and_tricks_for_pic_programming
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
c_tips_and_tricks_for_pic_programming [2006/11/13 19:59] – added comment on bit copy operations ilmenator | c_tips_and_tricks_for_pic_programming [2011/09/15 07:14] (current) – ichaljhe | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== C Variables ====== | ||
- | |||
- | * Declaring a [[http:// | ||
- | |||
- | * Adding the keyword ' | ||
- | |||
- | |||
- | \\ | ||
- | |||
====== Arithmetic Calculations ====== | ====== Arithmetic Calculations ====== | ||
* Avoid using **multiplications** and **divisions** whenever possible. These complex mathmatic calculations need a lot processing power and (what' | * Avoid using **multiplications** and **divisions** whenever possible. These complex mathmatic calculations need a lot processing power and (what' | ||
* If you need to multiply with and divide through even numbers like 2, 4, 8, 16, 32 ... you can make use of the bitshifting operators ">>" | * If you need to multiply with and divide through even numbers like 2, 4, 8, 16, 32 ... you can make use of the bitshifting operators ">>" | ||
- | char c; | + | unsigned |
c = 12 >> 1; // c is 6 (division through 2) | c = 12 >> 1; // c is 6 (division through 2) | ||
c = 12 >> 2; // c is 3 (division through 4) | c = 12 >> 2; // c is 3 (division through 4) | ||
Line 20: | Line 11: | ||
</ | </ | ||
* There' | * There' | ||
+ | * The [[http:// | ||
* If this is not enough, you could search for ASM optimized custom functions. You'll find some in code examples of TK, the [[ACSensorizer]] and a lot of PIC-Specialized Webpages – or of course the forum. | * If this is not enough, you could search for ASM optimized custom functions. You'll find some in code examples of TK, the [[ACSensorizer]] and a lot of PIC-Specialized Webpages – or of course the forum. | ||
- | * If that still is not enough or you have no time and a lot of processing power / space available on your PIC, you can include the **libsdcc library**: | + | \\ |
+ | \\ | ||
+ | |||
+ | ==== MIOS LIBSDCC Library ==== | ||
+ | |||
+ | If that still is not enough or you have no time and a lot of processing power / space available on your PIC, you can include the **libsdcc library**. Using the new MIOS GPUtils structure, this will be included automatically as required. | ||
+ | |||
+ | When using the library, sometimes the compiler will optimise multiplications to bitshifts (as demonstrated above) automatically. You can check the output files to see if this has occurred, but it is recommended to code the bitshifts manually, to be sure. | ||
- | >> //if multiplications, | ||
\\ | \\ | ||
+ | |||
+ | ==== Bitfields, Unions & Structs ==== | ||
+ | |||
+ | * Avoid using huge int- or char-arrays when you just need to store some ON/OFF values. Use a bitfield instead | ||
+ | <code c> | ||
+ | // define the bitfield | ||
+ | typedef union { | ||
+ | struct { | ||
+ | unsigned ALL: | ||
+ | }; | ||
+ | struct { | ||
+ | unsigned led1: | ||
+ | unsigned led2:1; | ||
+ | unsigned led3:1; | ||
+ | unsigned led4:1; | ||
+ | unsigned free:4; | ||
+ | }; | ||
+ | } something_t; | ||
+ | |||
+ | // declare var | ||
+ | something_t something; | ||
+ | |||
+ | // set bits | ||
+ | something.led1 = 1; | ||
+ | something.led3 = 0; | ||
+ | |||
+ | // get number | ||
+ | mynum = something.ALL; | ||
+ | |||
+ | </ | ||
+ | |||
+ | >> It has been confirmed with recent versions of SDCC, that bitfields are not limited to 8bits as was previously expected. | ||
+ | |||
====== C Functions ====== | ====== C Functions ====== | ||
Line 38: | Line 69: | ||
* [[How to mix C and ASM]] | * [[How to mix C and ASM]] | ||
+ | * [[Compiled C Code Size]] | ||
\\ | \\ | ||
+ | ====== C Variables ====== | ||
+ | |||
+ | * Declaring a [[http:// | ||
+ | |||
+ | * Adding the keyword ' | ||
+ | |||
+ | * Always use ' | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | \\ | ||
====== SDCC Bugs/ | ====== SDCC Bugs/ | ||
Some of these bugs have first been described in a [[http:// | Some of these bugs have first been described in a [[http:// | ||
Line 47: | Line 90: | ||
\\ | \\ | ||
- | ===== Array Access | + | |
- | Sometimes the transfer of an array between modules does not work properly, e.g. file 1: <code c> | + | ==== Array Access ==== |
+ | Sometimes the transfer of an array between modules does not work properly, e.g. file 1: | ||
+ | <code c> | ||
unsigned char MIDIValues[8]; | unsigned char MIDIValues[8]; | ||
- | </ | + | </ |
+ | file 2: | ||
+ | <code c> | ||
MIOS_MIDI_TxBufferPut(MIDIValues[1]); | MIOS_MIDI_TxBufferPut(MIDIValues[1]); | ||
- | </ | + | </ |
- | unsigend | + | Instead, you need to do something like |
- | MIOS_MIDI_TxBufferPut(value);</ | + | <code c> |
+ | unsigned | ||
+ | MIOS_MIDI_TxBufferPut(value); | ||
+ | </ | ||
+ | In most cases, adding parenthesis around your index variable has the same effect (see tip further down) | ||
+ | <code c> | ||
+ | MIOS_MIDI_TxBufferPut((MIDIValues[1])); | ||
+ | </ | ||
\\ | \\ | ||
- | ===== Large Arrays | + | ==== Large Arrays ==== |
- | Arrays with more than 256 elements will produce compile (in fact linker) errors: | + | Arrays with more than 256 bytes of elements will produce compile (in fact linker) errors: |
<code c> | <code c> | ||
unsigned char myArray[256]; | unsigned char myArray[256]; | ||
Line 66: | Line 120: | ||
unsigned char myArray[64][4]; | unsigned char myArray[64][4]; | ||
unsigned char myArray[64][5]; | unsigned char myArray[64][5]; | ||
+ | |||
+ | unsigned int myArray[128]; | ||
+ | unsigned int myArray[129]; | ||
</ | </ | ||
- | Thanks to Thomas for [[http:// | + | |
+ | This is due to the fact that the PIC's RAM has been segmented into 256-byte banks in the linker script, and an array' | ||
+ | |||
+ | The linker script can be modified to work around the 256-byte limitation by creating larger banks, as per the [[using_pic18f4620# | ||
+ | |||
+ | Thanks to Thomas for [[http:// | ||
\\ | \\ | ||
+ | ==== Bit Copy Operations ==== | ||
+ | There is potential trouble with bit copy operations (See [[http:// | ||
+ | <code c> | ||
+ | app_flags.SRAM_CARD_STATUS = PORTEbits.RE2; | ||
+ | </ | ||
+ | you should use | ||
+ | <code c> | ||
+ | if( PORTEbits.RE2 ){ | ||
+ | app_flags.SRAM_CARD_STATUS = 1; | ||
+ | }else{ | ||
+ | app_flags.SRAM_CARD_STATUS = 0; | ||
+ | } | ||
+ | </ | ||
+ | It is less elegant, but it works safely. | ||
- | ===== Parenthesis | + | |
+ | \\ | ||
+ | ==== Parenthesis ==== | ||
Always use parenthesis around expressions like <code c> | Always use parenthesis around expressions like <code c> | ||
\\ | \\ | ||
- | ===== Preprocessor #ifs ===== | + | ==== Preprocessor #ifs ==== |
Avoid #ifdef and #if preprocessor-statements wrapped around declarations and function prototypes. Even if the preprocessor' | Avoid #ifdef and #if preprocessor-statements wrapped around declarations and function prototypes. Even if the preprocessor' | ||
#define TEST 1 | #define TEST 1 | ||
Line 88: | Line 167: | ||
</ | </ | ||
- | \\ | ||
- | ===== Zero Compare | + | \\ |
- | Avoid comparisons of '' | + | ==== Zero Compare ==== |
+ | Avoid comparisons of '' | ||
+ | <code c> | ||
unsigned char i; | unsigned char i; | ||
for (i = 0; i < 0; i+ü) { | for (i = 0; i < 0; i+ü) { | ||
- | //body | + | // body |
- | | + | } |
+ | </ | ||
+ | '' | ||
+ | |||
+ | \\ | ||
+ | ==== Stack Size ==== | ||
+ | |||
+ | [[http:// | ||
+ | The stack boundaries are defined in the file header of mios_wrapper/ | ||
- | ===== Bit Copy Operations ===== | ||
- | There is potential trouble with bit copy operations. Instead of | ||
<code c> | <code c> | ||
- | app_flags.SRAM_CARD_STATUS = PORTEbits.RE2; | + | ; the upper boundary of the stacks are defined here |
+ | ; customize the values for your needs | ||
+ | #ifndef STACK_HEAD | ||
+ | #define STACK_HEAD 0x37f | ||
+ | #endif | ||
+ | |||
+ | #ifndef STACK_IRQ_HEAD | ||
+ | #define STACK_IRQ_HEAD 0x33f | ||
+ | #endif | ||
</ | </ | ||
- | you should | + | |
- | < | + | The default setup is 64 bytes for main tasks, 64 bytes for interrupt tasks. (stack pointer is counted down, there is no collision control to save runtime) |
- | if( PORTEbits.RE2 ){ | + | |
- | app_flags.SRAM_CARD_STATUS = 1; | + | Since a PIC18F4620 has enough memory, |
- | }else{ | + | < |
- | app_flags.SRAM_CARD_STATUS = 0; | + | #define STACK_HEAD 0xeff |
- | } | + | #define STACK_IRQ_HEAD 0xdff |
</ | </ | ||
- | It is less elegant, but it works safely. | + | this should relax the situation. |
+ | |||
+ | Note that the appr. memory area (0xd00-0xeff) should be reserved in the projekt.lkr file | ||
+ | // | ||
+ | // | ||
+ | Note that stacks greater than 256 bytes will not work with SDCC at present. [[http:// |
c_tips_and_tricks_for_pic_programming.txt · Last modified: 2011/09/15 07:14 by ichaljhe