Difference between revisions of "Programming Tips"
Jump to navigation
Jump to search
(→Auto baud rate detection: Is this more specific page a better link?) |
(driver development for dspic33) |
||
Line 1: | Line 1: | ||
+ | This wiki describes an example coding of the freertos_posix driver for the [[DsPIC30F 5011 Development Board | dsPic33 development board]]. Please refer to the actual coding used from [http://chungyan5.no-ip.org/vc/?root=freertos_posix here]. | ||
+ | ==Memory== | ||
− | + | ===Memory Map for dsPIC33FJ256GP506=== | |
− | |||
− | ==Memory Map for | ||
{| border="1" cellspacing="0" cellpadding="5" | {| border="1" cellspacing="0" cellpadding="5" | ||
− | |+ Table | + | |+ Table 11.1 Memory Location |
! Type !! Start Address !! End Address !! Size | ! Type !! Start Address !! End Address !! Size | ||
|-valign="top" | |-valign="top" | ||
− | | Flash || 0x000000 || | + | | Flash || 0x000000 ||0x0157FF || 86K<sup>[1]</sup> |
|-valign="top" | |-valign="top" | ||
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4 | | +--Flash: Reset Vector || 0x000000 ||0x000003 || 4 | ||
|-valign="top" | |-valign="top" | ||
− | | +--Flash: Interrupt Vector Table || 0x000004 | + | | +--Flash: Interrupt Vector Table || 0x000004 ||0x0000FF || 252 |
− | |||
− | |||
− | |||
− | |||
|-valign="top" | |-valign="top" | ||
− | | | + | | +--Flash: Alternate Vector Table || 0x000104 ||0x0001FF || 252 |
|-valign="top" | |-valign="top" | ||
− | | | + | | +--Flash: User Program || 0x000200 ||0x0157FF || 85.5K |
|-valign="top" | |-valign="top" | ||
− | | | + | | Programming Executive || 0x800000 || 0x800FFF || 4K<sup>[1]</sup> |
|-valign="top" | |-valign="top" | ||
− | | Config Registers || 0xF80000 || | + | | Config Registers || 0xF80000 || 0xF80017 || 24 |
|-valign="top" | |-valign="top" | ||
− | | Device ID || 0xFF0000 || 0xFF0003 || 4 | + | | Device ID (0xE5) || 0xFF0000 || 0xFF0003 || 4 |
|- | |- | ||
|} | |} | ||
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br> | [1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br> | ||
− | |||
− | ==Data Location== | + | ===Data Location=== |
{| border="1" cellspacing="0" cellpadding="5" | {| border="1" cellspacing="0" cellpadding="5" | ||
− | |+ | + | |+ |
! Type !! Description !! Example | ! Type !! Description !! Example | ||
|-valign="top" | |-valign="top" | ||
Line 82: | Line 77: | ||
| int _NEAR var1, var2; | | int _NEAR var1, var2; | ||
|-valign="top" | |-valign="top" | ||
− | | | + | | __attribute__((__interrupt__)) |
| Interrupt service rountine | | Interrupt service rountine | ||
− | | void | + | | void __attribute__((__interrupt__)) _INT0Interrupt(void); |
|-valign="top" | |-valign="top" | ||
| _ISRFAST | | _ISRFAST | ||
Line 94: | Line 89: | ||
− | == | + | ===<asm/types.h>=== |
+ | *The following maps the basic data types: | ||
+ | typedef unsigned char __u8; | ||
+ | typedef char __s8; | ||
+ | typedef unsigned int __u16; | ||
+ | typedef int __s16; | ||
+ | typedef unsigned long __u32; | ||
+ | typedef long __s32; | ||
+ | typedef unsigned long long __u64; | ||
+ | typedef long long __s64; | ||
+ | |||
+ | //to be used in <time.h> | ||
+ | typedef unsigned long time_t; | ||
+ | *The following macros are the platform-dependent | ||
+ | /** Interrupt Request */ | ||
+ | #define _IRQ __attribute__((__interrupt__)) | ||
+ | /** TRAP IRQ for saving program counter: declare __u16 StkAddrLo, StkAddrHi in trap.c (order matters) */ | ||
+ | #define _TRAP_IRQ __attribute__((__interrupt__(__preprologue__( \ | ||
+ | "mov #_StkAddrHi,w1\n\tpop [w1--]\n\tpop [w1++]\n\tpush [w1--]\n\tpush [w1++]")))) | ||
+ | /** IO Stub Functions are placed in .libc section so that the standard libraries can access these functions using short jumps. */ | ||
+ | #define _LIBC __attribute__((section(".libc"))) | ||
+ | /** FAST RAM */ | ||
+ | #define _DMA __attribute__((space(dma),aligned(256))) | ||
+ | |||
+ | |||
+ | ===Custom Linker Script to Maximize Space for Constant Data=== | ||
+ | *Constant data declared using keyword '''const''' will be stored in the .const section in the flash memory. | ||
+ | *Normally, during compilation, the linker will assign these data after the program code (.text section). | ||
+ | *Since .const is accessed by auto-psv function, to maximize the space for constant data (32kb), the .const section needs to be aligned at 0x80000 boundary. | ||
+ | *This requires the following change in linker script: | ||
+ | |||
+ | __CONST_BASE = 0x8000; | ||
+ | |||
+ | .text __CODE_BASE : | ||
+ | { | ||
+ | *(.reset); | ||
+ | *(.handle); | ||
+ | *(.libc) *(.libm) *(.libdsp); /* keep together in this order */ | ||
+ | *(.lib*); | ||
+ | /* *(.text); deleted to maximize space for const data */ | ||
+ | } >program | ||
+ | |||
+ | .const __CONST_BASE : | ||
+ | { | ||
+ | *(.const); | ||
+ | } >program | ||
+ | |||
+ | *If your program is large, after this change in linker script, function calls may involve large jump in the memory map (>32kB). As a result, you may need to enable the large code and large memory model during compilation. In such case, use the following options in your build path: | ||
+ | -mlarge-code -mlarge-data | ||
+ | *Meanwhile, functions that are defined in the standard C libraries, but are replaced with your own implementations (e.g. I/O stubs: open(), read(), write(), lseek(), ioctl() etc.) may have the following linker error: | ||
+ | /usr/pic30-elf/lib//libc-elf.a(fflush.eo)(.libc+0x3c): In function '.LM11': | ||
+ | : Link Error: relocation truncated to fit: PC RELATIVE BRANCH _write | ||
+ | /usr/pic30-elf/lib//libc-elf.a(fclose.eo)(.libc+0x42): In function '.LM18': | ||
+ | : Link Error: relocation truncated to fit: PC RELATIVE BRANCH _close | ||
+ | *To resolve the problem, you need to place the functions in the .libc section rather than in the .text section, like this: | ||
+ | int _LIBC open(const char *pathname, int flags){ ... } | ||
+ | int _LIBC close(int fd){ ... } | ||
+ | int _LIBC write(int fd, void* buf, int count) { ... } | ||
+ | int _LIBC read(int fd, void* buf, int count) { ... } | ||
+ | int _LIBC ioctl(int fd, int request, void* argp) { ... } | ||
+ | int _LIBC lseek(int fd, int offset, int whence) { ... } | ||
+ | |||
+ | |||
+ | ==System Setup== | ||
+ | |||
+ | ===Clock Speed=== | ||
*System clock source can be provided by: | *System clock source can be provided by: | ||
#Primary oscillator (OSC1, OSC2) | #Primary oscillator (OSC1, OSC2) | ||
Line 102: | Line 162: | ||
*These clock sources can be incorporated with interal Phase-locked-loop (PLL) x4, x8 or x16 to yield the osciallator frequrence F<sub>OSC</sub> | *These clock sources can be incorporated with interal Phase-locked-loop (PLL) x4, x8 or x16 to yield the osciallator frequrence F<sub>OSC</sub> | ||
*The system clock is divided by 4 to yield the internal instruction cycle clock, F<sub>CY</sub>=F<sub>OSC</sub>/4 | *The system clock is divided by 4 to yield the internal instruction cycle clock, F<sub>CY</sub>=F<sub>OSC</sub>/4 | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | ===System Clock=== | |
− | == | ||
*Each timer is 16-bit (i.e. counting from 0 to 65535). | *Each timer is 16-bit (i.e. counting from 0 to 65535). | ||
− | |||
*Prescale is the ratio between timer counts and system clock counts. Prescales of 1:1, 1:8, 1:64 and 1:256 are available. | *Prescale is the ratio between timer counts and system clock counts. Prescales of 1:1, 1:8, 1:64 and 1:256 are available. | ||
− | |||
− | |||
− | |||
*Let required time for ticking be PERIOD. | *Let required time for ticking be PERIOD. | ||
*Number of instruction cycles during PERIOD = PERIOD*F<sub>CY</sub> cycles | *Number of instruction cycles during PERIOD = PERIOD*F<sub>CY</sub> cycles | ||
*Using a prescale of 1:x, the timer period count register = # of cycles/x | *Using a prescale of 1:x, the timer period count register = # of cycles/x | ||
− | *e.g. PERIOD = 10ms; # of cycles = 10ms* | + | *e.g. PERIOD = 10ms; # of cycles = 10ms*40MHz = 400000 cycles; Using 1:8 Prescale, register setting = 400000/8 = 50000 |
− | void | + | void |
− | + | prvSetupTimerInterrupt (void) | |
− | + | { | |
− | + | T1CON = 0; | |
− | + | TMR1 = 0; | |
− | + | PR1 = 50000; | |
− | + | //============================================================ | |
− | + | IPC0bits.T1IP = configKERNEL_INTERRUPT_PRIORITY; | |
− | + | IFS0bits.T1IF = 0; | |
− | + | IEC0bits.T1IE = 1; | |
+ | //============================================================ | ||
+ | T1CONbits.TCKPS0 = 1; | ||
+ | T1CONbits.TCKPS1 = 0; | ||
+ | T1CONbits.TON = 1; | ||
} | } | ||
//******************************************************************** | //******************************************************************** | ||
− | void | + | void _IRQ |
− | + | _T1Interrupt (void) | |
− | + | { | |
− | + | IFS0bits.T1IF = 0; | |
− | + | vTaskIncrementTick(); | |
− | + | portYIELD(); | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | == | + | ===<asm/system.h>=== |
*Registers are involved in Interrupts includes: | *Registers are involved in Interrupts includes: | ||
#Interrupt Flag Status (IFS0-IFS2) registers | #Interrupt Flag Status (IFS0-IFS2) registers | ||
Line 171: | Line 210: | ||
#define cli() SR |= IPL //Set IPL to 7 | #define cli() SR |= IPL //Set IPL to 7 | ||
#define sti() SR &= ~IPL //Set IPL to 0 | #define sti() SR &= ~IPL //Set IPL to 0 | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | ==POSIX System Call and Drivers== | |
− | + | *POSIX System calls (open(), close(), read(), write(), lseek()) are used to access hardware devices related to data stream. | |
− | + | *The file descriptor return by open() for these devices are statically assigned at compile time. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | === | + | ===UART=== |
− | * | + | *Serves as the default communication channel for STDIN, STDOUT and STDERR. |
− | + | *Implementation of this driver allows transparent operation of printf() in standard C library. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | * | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | ===I<sup>2</sup>C=== | |
− | ==I<sup>2</sup>C== | + | *A number of I2C devices can be added using this driver (e.g. I2C DAC, I2C EEPROM, etc) |
*Two lines are devoted for the serial communication. SCL for clock, SDA for data. | *Two lines are devoted for the serial communication. SCL for clock, SDA for data. | ||
*Standard communication speed includes | *Standard communication speed includes | ||
Line 406: | Line 229: | ||
#Fast speed mode: 400kHz | #Fast speed mode: 400kHz | ||
#High speed mode: 3.4MHz | #High speed mode: 3.4MHz | ||
− | |||
*Pull-up resistors are required for both SCL and SDA. Minimum pull-up resistance is given by: | *Pull-up resistors are required for both SCL and SDA. Minimum pull-up resistance is given by: | ||
Pull-up resistor (min) = (V<sub>dd</sub>-0.4)/0.003 ...... [See section 21.8 in Family reference manual] | Pull-up resistor (min) = (V<sub>dd</sub>-0.4)/0.003 ...... [See section 21.8 in Family reference manual] | ||
*2.2Kohm is typical for standard speed mode. | *2.2Kohm is typical for standard speed mode. | ||
*After initiating a start/stop/restart bit, add a small delay (e.g. no operation) before polling the corresponding control bit (hardware controlled). | *After initiating a start/stop/restart bit, add a small delay (e.g. no operation) before polling the corresponding control bit (hardware controlled). | ||
− | *After sending a byte and receiving an | + | *After sending a byte and receiving an acknowledgment from the slave device, ensure to change to idle state. |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | ===ADC=== | |
− | + | *12-bit ADC: (Max 18 Channels) | |
− | + | *ADC uses DMA to buffer the adc data. | |
− | + | *A maximum of 500kps of sampling rate when using auto sampling mode. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | === | ||
− | * | ||
− | |||
− | |||
− | |||
− | |||
− | * | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | = | + | ===Simple PWM (Output Compare Module)=== |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | ==Simple PWM (Output Compare Module)== | ||
*The PWM module consists of 8 channels using the output compare module of dsPic. | *The PWM module consists of 8 channels using the output compare module of dsPic. | ||
*These channels are locate at pin 46 (OC1), 49 (OC2), 50 (OC3), 51 (OC4), 52 (OC5), 53 (OC6), 54 (OC7), 55 (OC8). These pins are shared with port D. | *These channels are locate at pin 46 (OC1), 49 (OC2), 50 (OC3), 51 (OC4), 52 (OC5), 53 (OC6), 54 (OC7), 55 (OC8). These pins are shared with port D. | ||
Line 874: | Line 249: | ||
{| border="1" cellspacing="0" cellpadding="5" | {| border="1" cellspacing="0" cellpadding="5" | ||
− | |+ | + | |+ Relationship of Resolution and PWM Frequency |
! Resolution (bit) !! Prescale=1 !! Prescale=8 !! Prescale=64 !! Prescale=256 | ! Resolution (bit) !! Prescale=1 !! Prescale=8 !! Prescale=64 !! Prescale=256 | ||
|- | |- | ||
Line 911: | Line 286: | ||
|} | |} | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | === | + | ===Flash-emulated EEPROM=== |
− | * | + | *Using built-in functions __builtin_tblpage(), __builtin_tbloffset() to set special-purpose registers to access flash memory |
− | + | *Using assembly code to read and write flash memory. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | * | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
==DSP Library== | ==DSP Library== | ||
+ | *Not POSIX compliant | ||
*Library functions in <dsp.h> include the following categories: | *Library functions in <dsp.h> include the following categories: | ||
#Vector | #Vector | ||
Line 1,054: | Line 317: | ||
**Floating point values can be converted to Fractional values using: '''fr = Float2Fract(fo);''' or '''fr = Q15(fo);''' for fo = [-1, 1-2<sup>-15</sup>] | **Floating point values can be converted to Fractional values using: '''fr = Float2Fract(fo);''' or '''fr = Q15(fo);''' for fo = [-1, 1-2<sup>-15</sup>] | ||
**Float2Fract() is same as Q15(), except having saturation control. When +ve >= 1, answer = 2<sup>15</sup>-1 = 32767 (0x7FFF). When -ve < -1, answer = -2<sup>15</sup> = -32767 (0x8000) | **Float2Fract() is same as Q15(), except having saturation control. When +ve >= 1, answer = 2<sup>15</sup>-1 = 32767 (0x7FFF). When -ve < -1, answer = -2<sup>15</sup> = -32767 (0x8000) | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− |
Revision as of 00:43, 31 August 2009
This wiki describes an example coding of the freertos_posix driver for the dsPic33 development board. Please refer to the actual coding used from here.
Memory
Memory Map for dsPIC33FJ256GP506
Type | Start Address | End Address | Size |
---|---|---|---|
Flash | 0x000000 | 0x0157FF | 86K[1] |
+--Flash: Reset Vector | 0x000000 | 0x000003 | 4 |
+--Flash: Interrupt Vector Table | 0x000004 | 0x0000FF | 252 |
+--Flash: Alternate Vector Table | 0x000104 | 0x0001FF | 252 |
+--Flash: User Program | 0x000200 | 0x0157FF | 85.5K |
Programming Executive | 0x800000 | 0x800FFF | 4K[1] |
Config Registers | 0xF80000 | 0xF80017 | 24 |
Device ID (0xE5) | 0xFF0000 | 0xFF0003 | 4 |
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.
Data Location
Type | Description | Example |
---|---|---|
_XBSS(N) [1] | RAM Data in X-memory, aligned at N, no initilization | int _XBSS(32) xbuf[16]; |
_XDATA(N) [1] | RAM Data in X-memory, aligned at N, with initilization | int _XDATA(32) xbuf[] = {1, 2, 3, 4, 5}; |
_YBSS(N) [1] | RAM Data in Y-memory, aligned at N, no initilization | int _YBSS(32) ybuf[16]; |
_YDATA(N) [1] | RAM Data in Y-memory, aligned at N, with initilization | int _YDATA(32) ybuf[16] = {1, 2, 3, 4, 5}; |
__attribute__((space(const))) | Flash ROM data, constant, accessed by normal C statements, but 32K max. |
int i __attribute__((space(const))) = 10; |
__attribute__((space(prog))) | Flash ROM data, read/write by program space visibility window (psv) |
int i __attribute__((space(prog))); |
__attribute__((space(auto_psv))) | Flash ROM data, read by normal C statements, write by accessing psv |
int i __attribute__((space(auto_psv))); |
__attribute__((space(psv))) | Flash ROM data, read/write by (psv) | int i __attribute__((space(psv))); |
_EEDATA(N) [1] | ROM Data in EEPROM, aligned at N, read/write with psv | int _EEDATA(2) table[]={0, 1, 2, 3, 5, 8}; |
_PERSISTENT | RAM Data, data remain after reset | int _PERSISTENT var1, var2; |
_NEAR | RAM Data at near section | int _NEAR var1, var2; |
__attribute__((__interrupt__)) | Interrupt service rountine | void __attribute__((__interrupt__)) _INT0Interrupt(void); |
_ISRFAST | Fast interrupt service rountine | void _ISRFAST _T0Interrupt(void); |
- N must be a power of two, with a minimum value of 2.
<asm/types.h>
- The following maps the basic data types:
typedef unsigned char __u8; typedef char __s8; typedef unsigned int __u16; typedef int __s16; typedef unsigned long __u32; typedef long __s32; typedef unsigned long long __u64; typedef long long __s64; //to be used in <time.h> typedef unsigned long time_t;
- The following macros are the platform-dependent
/** Interrupt Request */ #define _IRQ __attribute__((__interrupt__)) /** TRAP IRQ for saving program counter: declare __u16 StkAddrLo, StkAddrHi in trap.c (order matters) */ #define _TRAP_IRQ __attribute__((__interrupt__(__preprologue__( \ "mov #_StkAddrHi,w1\n\tpop [w1--]\n\tpop [w1++]\n\tpush [w1--]\n\tpush [w1++]")))) /** IO Stub Functions are placed in .libc section so that the standard libraries can access these functions using short jumps. */ #define _LIBC __attribute__((section(".libc"))) /** FAST RAM */ #define _DMA __attribute__((space(dma),aligned(256)))
Custom Linker Script to Maximize Space for Constant Data
- Constant data declared using keyword const will be stored in the .const section in the flash memory.
- Normally, during compilation, the linker will assign these data after the program code (.text section).
- Since .const is accessed by auto-psv function, to maximize the space for constant data (32kb), the .const section needs to be aligned at 0x80000 boundary.
- This requires the following change in linker script:
__CONST_BASE = 0x8000; .text __CODE_BASE : { *(.reset); *(.handle); *(.libc) *(.libm) *(.libdsp); /* keep together in this order */ *(.lib*); /* *(.text); deleted to maximize space for const data */ } >program .const __CONST_BASE : { *(.const); } >program
- If your program is large, after this change in linker script, function calls may involve large jump in the memory map (>32kB). As a result, you may need to enable the large code and large memory model during compilation. In such case, use the following options in your build path:
-mlarge-code -mlarge-data
- Meanwhile, functions that are defined in the standard C libraries, but are replaced with your own implementations (e.g. I/O stubs: open(), read(), write(), lseek(), ioctl() etc.) may have the following linker error:
/usr/pic30-elf/lib//libc-elf.a(fflush.eo)(.libc+0x3c): In function '.LM11': : Link Error: relocation truncated to fit: PC RELATIVE BRANCH _write /usr/pic30-elf/lib//libc-elf.a(fclose.eo)(.libc+0x42): In function '.LM18': : Link Error: relocation truncated to fit: PC RELATIVE BRANCH _close
- To resolve the problem, you need to place the functions in the .libc section rather than in the .text section, like this:
int _LIBC open(const char *pathname, int flags){ ... } int _LIBC close(int fd){ ... } int _LIBC write(int fd, void* buf, int count) { ... } int _LIBC read(int fd, void* buf, int count) { ... } int _LIBC ioctl(int fd, int request, void* argp) { ... } int _LIBC lseek(int fd, int offset, int whence) { ... }
System Setup
Clock Speed
- System clock source can be provided by:
- Primary oscillator (OSC1, OSC2)
- Secondary oscillator (SOSCO and SOSCI) with 32kHz crystal
- Internal Fast RC (FRC) oscillator at 7.37MHz (7372800Hz)
- Low-Power RC (LPRC) oscillator (Watchdog Timer) at 512 kHz.
- These clock sources can be incorporated with interal Phase-locked-loop (PLL) x4, x8 or x16 to yield the osciallator frequrence FOSC
- The system clock is divided by 4 to yield the internal instruction cycle clock, FCY=FOSC/4
System Clock
- Each timer is 16-bit (i.e. counting from 0 to 65535).
- Prescale is the ratio between timer counts and system clock counts. Prescales of 1:1, 1:8, 1:64 and 1:256 are available.
- Let required time for ticking be PERIOD.
- Number of instruction cycles during PERIOD = PERIOD*FCY cycles
- Using a prescale of 1:x, the timer period count register = # of cycles/x
- e.g. PERIOD = 10ms; # of cycles = 10ms*40MHz = 400000 cycles; Using 1:8 Prescale, register setting = 400000/8 = 50000
void prvSetupTimerInterrupt (void) { T1CON = 0; TMR1 = 0; PR1 = 50000; //============================================================ IPC0bits.T1IP = configKERNEL_INTERRUPT_PRIORITY; IFS0bits.T1IF = 0; IEC0bits.T1IE = 1; //============================================================ T1CONbits.TCKPS0 = 1; T1CONbits.TCKPS1 = 0; T1CONbits.TON = 1; } //******************************************************************** void _IRQ _T1Interrupt (void) { IFS0bits.T1IF = 0; vTaskIncrementTick(); portYIELD(); }
<asm/system.h>
- Registers are involved in Interrupts includes:
- Interrupt Flag Status (IFS0-IFS2) registers
- Interrupt Enable Control (IEC0-IEC2) registers
- Interrupt Priority Control (IPC0-IPC10) registers
- Interrupt Priority Level (IPL) register
- Global Interrupt Control (INTCON1, INTCON2) registers
- Interrupt vector (INTTREG) register
- User may assign priority level 0-7 to a specific interrupt using IPC. Setting priority to 0 disable a specific interrupt. Level 7 interrupt has the highest priority.
- Current priority level is stored in bit<7:5> of Status Register (SR). Setting Interrupt Priority Level (IPL) to 7 disables all interrupts (except traps).
- sti() and cli() can be defined to enable and disable global interrupts for time critical functions:
#define IPL ( 0x00e0 ) #define cli() SR |= IPL //Set IPL to 7 #define sti() SR &= ~IPL //Set IPL to 0
POSIX System Call and Drivers
- POSIX System calls (open(), close(), read(), write(), lseek()) are used to access hardware devices related to data stream.
- The file descriptor return by open() for these devices are statically assigned at compile time.
UART
- Serves as the default communication channel for STDIN, STDOUT and STDERR.
- Implementation of this driver allows transparent operation of printf() in standard C library.
I2C
- A number of I2C devices can be added using this driver (e.g. I2C DAC, I2C EEPROM, etc)
- Two lines are devoted for the serial communication. SCL for clock, SDA for data.
- Standard communication speed includes
- Standard speed mode: 100kHz
- Fast speed mode: 400kHz
- High speed mode: 3.4MHz
- Pull-up resistors are required for both SCL and SDA. Minimum pull-up resistance is given by:
Pull-up resistor (min) = (Vdd-0.4)/0.003 ...... [See section 21.8 in Family reference manual]
- 2.2Kohm is typical for standard speed mode.
- After initiating a start/stop/restart bit, add a small delay (e.g. no operation) before polling the corresponding control bit (hardware controlled).
- After sending a byte and receiving an acknowledgment from the slave device, ensure to change to idle state.
ADC
- 12-bit ADC: (Max 18 Channels)
- ADC uses DMA to buffer the adc data.
- A maximum of 500kps of sampling rate when using auto sampling mode.
Simple PWM (Output Compare Module)
- The PWM module consists of 8 channels using the output compare module of dsPic.
- These channels are locate at pin 46 (OC1), 49 (OC2), 50 (OC3), 51 (OC4), 52 (OC5), 53 (OC6), 54 (OC7), 55 (OC8). These pins are shared with port D.
- The range of PWM freqeuencies obtainable is 2Hz to 15MHz (See Figure 6.3). Suggested range of operation is 2Hz to 120kHz. The relationship between resolution r and PWM frequency fPWM is given by:
fPWM = fCY/(Prescale*10rlog(2))
Resolution (bit) | Prescale=1 | Prescale=8 | Prescale=64 | Prescale=256 |
---|---|---|---|---|
1 | 15,000,000 | 1,875,000 | 234,375 | 58,594 |
2 | 7,500,000 | 937,500 | 117,188 | 29,297 |
3 | 3,750,000 | 468,750 | 58,594 | 14,648 |
4 | 1,875,000 | 234,375 | 29,297 | 7,324 |
5 | 937,500 | 117,188 | 14,648 | 3,662 |
6 | 468,750 | 58,594 | 7,324 | 1,831 |
7 | 234,375 | 29,297 | 3,662 | 916 |
8 | 117,188 | 14,648 | 1,831 | 458 |
9 | 58,594 | 7,324 | 916 | 229 |
10 | 29,297 | 3,662 | 458 | 114 |
11 | 14,648 | 1,831 | 229 | 57 |
12 | 7,324 | 916 | 114 | 29 |
13 | 3,662 | 458 | 57 | 14 |
14 | 1,831 | 229 | 29 | 7 |
15 | 916 | 114 | 14 | 4 |
16 | 458 | 57 | 7 | 2 |
Flash-emulated EEPROM
- Using built-in functions __builtin_tblpage(), __builtin_tbloffset() to set special-purpose registers to access flash memory
- Using assembly code to read and write flash memory.
DSP Library
- Not POSIX compliant
- Library functions in <dsp.h> include the following categories:
- Vector
- Window
- Matrix
- Filtering
- Transform
- Control
Data Types
- Signed Fractional Value (1.15 data format)
- Inputs and outputs of the dsp functions adopt 1.15 data format, which consumes 16 bits to represent values between -1 to 1-2-15 inclusive.
- Bit<15> is a signed bit, positive = 0, negative = 1.
- Bit<14:0> are the exponent bits e.
- Positive value = 1 - 2-15*(32768 - e)
- Negative value = 0 - 2-15*(32768 - e)
- 40-bit Accumulator operations (9.31 data format)
- The dsp functions use the 40 bits accumalators during arithmatic calculations.
- Bit<39:31> are signed bits, positive = 0x000, negative = 0x1FF.
- Bit<30:0> are exponent bits.
- IEEE Floating Point Values
- Fractional values can be converted to Floating point values using: fo = Fract2Float(fr); for fr = [-1, 1-2-15]
- Floating point values can be converted to Fractional values using: fr = Float2Fract(fo); or fr = Q15(fo); for fo = [-1, 1-2-15]
- Float2Fract() is same as Q15(), except having saturation control. When +ve >= 1, answer = 215-1 = 32767 (0x7FFF). When -ve < -1, answer = -215 = -32767 (0x8000)