User Tools

Site Tools


c_tips_and_tricks_for_pic_programming

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
c_tips_and_tricks_for_pic_programming [2006/10/27 11:22]
audiocommander hooray! I remembered what has been lost on friday the 13th!!! C-Arithmetics :)
c_tips_and_tricks_for_pic_programming [2011/09/15 07:14] (current)
ichaljhe
Line 1: Line 1:
-====== C Variables ====== 
- 
-  * Declaring a [[http://​en.wikipedia.org/​wiki/​Variable|variable]] as type '​const'​ will cause the [[http://​en.wikipedia.org/​wiki/​Compiler|compiler]] to store the variable in the PIC's program [[http://​en.wikipedia.org/​wiki/​Flash_memory|flash memory]], not the [[http://​en.wikipedia.org/​wiki/​Static_random_access_memory|SRAM]]. 
- 
-  * Adding the keyword '​[[http://​en.wikipedia.org/​wiki/​Volatile_variable|volatile]]'​ to a [[http://​en.wikipedia.org/​wiki/​Variable|variable]] is a good idea when this variable can be changed or altered outside the sourcefile that declared this variable. 
- 
- 
-\\ 
 ====== Arithmetic Calculations ====== ====== Arithmetic Calculations ======
  
   * Avoid using **multiplications** and **divisions** whenever possible. These complex mathmatic calculations need a lot processing power and (what'​s even worser) a huge library to be compiled at all.   * Avoid using **multiplications** and **divisions** whenever possible. These complex mathmatic calculations need a lot processing power and (what'​s even worser) a huge library to be compiled at all.
   * 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 ">>"​ and "<<"​ <code c>   * 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 ">>"​ and "<<"​ <code c>
-char c;+unsigned ​char c;
 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 18: Line 10:
 c = 1023 >> 3; //  c is 127 (10bit to 7bit ;) c = 1023 >> 3; //  c is 127 (10bit to 7bit ;)
 </​code>​ </​code>​
 +  * There'​s an excellent thread in the forum that discusses bitoperations:​ http://​www.midibox.org/​forum/​index.php?​topic=6981.0
 +  * The [[http://​www.midibox.org/​forum/​index.php/​topic,​9666.msg73781.html#​msg73781|Re:​ Scan Matrix extended : VOIRINOV]] thread has an explanation of what the declaration of the bitfield is all about.
   * 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,​ divisions, pointer operations, etc. are used in the .c code, the linker may fail due to missing functions, which are part of the libsdcc.lib library. The common library for pic16 derivatives is not compatible to MIOS, therefore I've created a special one which can be downloaded from [[http://​www.ucapps.de/​mios/​mios_libsdcc_v2_5_0.zip|here]]. Read the README.txt file for further details. [[http://​www.ucapps.de/​mios_c.html|TK on the C-Page]] // 
  
 \\ \\
 +
 +==== 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:​8; ​   // by calling something.ALL,​ you get the whole bitfield as 8-bit number
 + };
 + struct {
 + unsigned led1:​1; ​  // by calling something.led1 you get one bit-state (1 or 0)
 + 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;​
 +
 +</​code>​
 +
 +>> 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 35: Line 69:
  
   * [[How to mix C and ASM]]   * [[How to mix C and ASM]]
 +  * [[Compiled C Code Size]]
  
 \\ \\
  
 +====== C Variables ======
 +
 +  * Declaring a [[http://​en.wikipedia.org/​wiki/​Variable|variable]] as type '​const'​ will cause the [[http://​en.wikipedia.org/​wiki/​Compiler|compiler]] to store the variable in the PIC's program [[http://​en.wikipedia.org/​wiki/​Flash_memory|flash memory]], not the [[http://​en.wikipedia.org/​wiki/​Static_random_access_memory|SRAM]].
 +
 +  * Adding the keyword '​[[http://​en.wikipedia.org/​wiki/​Volatile_variable|volatile]]'​ to a [[http://​en.wikipedia.org/​wiki/​Variable|variable]] is a good idea when this variable can be changed or altered outside the sourcefile that declared this variable.
 +
 +  * Always use '​unsigned'​ if you are sure you don't need negative values. Although the default is an unsigned char, it's not always clear how C treats a '​char'​ (signed: -128 to 127; unsigned: 0 to 255), so it's better to be clear here. 
 +
 +
 +
 +
 +\\
 ====== SDCC Bugs/​Workarounds ====== ====== SDCC Bugs/​Workarounds ======
 Some of these bugs have first been described in a [[http://​www.midibox.org/​forum/​index.php?​topic=7463.msg50464#​msg50464|german thread in the forum]]. Some of these bugs have first been described in a [[http://​www.midibox.org/​forum/​index.php?​topic=7463.msg50464#​msg50464|german thread in the forum]].
Line 44: 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];​
-</​code>​ file 2: <code c>+</​code> ​ 
 +file 2:  
 +<code c>
 MIOS_MIDI_TxBufferPut(MIDIValues[1]);​ MIOS_MIDI_TxBufferPut(MIDIValues[1]);​
-</​code> ​ Instead, you need to do something like <code c> +</​code>  ​ 
-unsigend ​char value = MIDIValues[1];​ //explicite ​temp variable +Instead, you need to do something like  
-MIOS_MIDI_TxBufferPut(value);</​code>​+<code c> 
 +unsigned ​char value = MIDIValues[1];​ //explicit ​temp variable 
 +MIOS_MIDI_TxBufferPut(value);​ 
 +</​code>​ 
 +In most cases, adding parenthesis around your index variable has the same effect (see tip further down) 
 +<code c> 
 +MIOS_MIDI_TxBufferPut((MIDIValues[1]));​ 
 +</​code>​
  
 \\ \\
  
-===== 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];​ // will work unsigned char myArray[256];​ // will work
Line 63: Line 120:
 unsigned char myArray[64][4];​ // will work unsigned char myArray[64][4];​ // will work
 unsigned char myArray[64][5];​ // will not be linked! unsigned char myArray[64][5];​ // will not be linked!
 +
 +unsigned int myArray[128];​ // will work
 +unsigned int myArray[129];​ // will not be linked!
 </​code>​ </​code>​
-Thanks to Thomas for [[http://​www.midibox.org/​forum/​index.php?​topic=6814.msg43501#​msg43501|testing some workarounds with multiple single-dimensional arrays]].+ 
 +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'​s contents may not span across more than one bank. 
 + 
 +The linker script can be modified to work around the 256-byte limitation by creating larger banks, as per the [[using_pic18f4620#​linker_script|Linker Script]] and [[using_pic18f4620#​application_code|Application Code]] tips on the 4620 page. 
 + 
 +Thanks to Thomas for [[http://​www.midibox.org/​forum/​index.php?​topic=6814.msg43501#​msg43501|testing some workarounds with multiple single-dimensional arrays]]. ​These methods would be recommended if possible. 
  
 \\ \\
 +==== Bit Copy Operations ====
 +There is potential trouble with bit copy operations (See [[http://​www.midibox.org/​forum/​index.php?​topic=7925.msg54675#​msg54675|this posting]]). Instead of 
 +<code c>
 +  app_flags.SRAM_CARD_STATUS = PORTEbits.RE2;​
 +</​code>​
 +you should use
 +<code c>
 +  if( PORTEbits.RE2 ){
 +    app_flags.SRAM_CARD_STATUS = 1;
 +  }else{
 +    app_flags.SRAM_CARD_STATUS = 0;
 +  }
 +</​code>​
 +It is less elegant, but it works safely.
  
-===== Parenthesis ​=====+ 
 +\\ 
 +==== Parenthesis ====
 Always use parenthesis around expressions like <code c>​myarray[a+b];</​code>​ instead use <code c>​myarray[(a+b)];</​code>​ Always use parenthesis around expressions like <code c>​myarray[a+b];</​code>​ instead use <code c>​myarray[(a+b)];</​code>​
  
 \\ \\
-===== Preprocessor #ifs =====+==== Preprocessor #ifs ====
 Avoid #ifdef and #if preprocessor-statements wrapped around declarations and function prototypes. Even if the preprocessor'​s #if statement is true (eg defined as '​1'​),​ any access to it's vars and functions from outside these wrapped statements produce a compile-warning:​ <code c> Avoid #ifdef and #if preprocessor-statements wrapped around declarations and function prototypes. Even if the preprocessor'​s #if statement is true (eg defined as '​1'​),​ any access to it's vars and functions from outside these wrapped statements produce a compile-warning:​ <code c>
 #define TEST 1 #define TEST 1
Line 84: Line 166:
 } }
 </​code>​ </​code>​
 +
  
 \\ \\
-===== Zero Compare ​===== +==== Zero Compare ==== 
-Avoid comparisons of ''​unsigned char''​ with ''​0'',​ e.g. <code c>+Avoid comparisons of ''​unsigned char''​ with ''​0'',​ e.g.  
 +<code c>
 unsigned char i; unsigned char i;
    for (i = 0; i < 0; i+ü) {    for (i = 0; i < 0; i+ü) {
-      //body +      // body 
-   ​} ​ </​code>​ ''​0''​ could be a constant that was defined using ''#​define'',​ e.g. the number of motorized faders. But you have no motorized faders... The main problem consists in the fact that your code depends on what else is done around the comparison or in the body. This provokes completely erratic behaviour.+   } 
 +</​code>​ 
 +''​0''​ could be a constant that was defined using ''#​define'',​ e.g. the number of motorized faders. But you have no motorized faders... The main problem consists in the fact that your code depends on what else is done around the comparison or in the body. This provokes completely erratic behaviour. 
 + 
 +\\ 
 +==== Stack Size ==== 
 + 
 +[[http://​www.midibox.org/​forum/​index.php?​topic=7687.msg52402#​msg52402|TK says:]]\\ 
 +The stack boundaries are defined in the file header of mios_wrapper/​mios_wrapper.asm:​ 
 + 
 +<code c> 
 +; 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 
 +</​code>​ 
 + 
 +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) 
 + 
 +Since a PIC18F4620 has enough memory, you could use two 256 bytes stacks located at the upper RAM pages: 
 +<​code>​ 
 +#define STACK_HEAD 0xeff 
 +#define STACK_IRQ_HEAD 0xdff 
 +</​code>​ 
 +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://​wemelt.com/​ipaymu-com-pembayaran-online-indonesia/​|iPaymu.com Pembayaran Online Indonesia]]
c_tips_and_tricks_for_pic_programming.1161948153.txt.gz · Last modified: 2006/10/30 20:28 (external edit)