Difference between revisions of "Programming Tips"
Jump to navigation
Jump to search
(New page: ==Memory Map for 5011== {| border="1" cellspacing="0" cellpadding="5" |+ Table 6.1 Memory Location ! Type !! Start Address !! End Address !! Size |-valign="top" | Flash || 0x000000 ||0x00A...) |
(merge sections) |
||
(8 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
− | ==Memory Map for | + | 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=== | ||
{| border="1" cellspacing="0" cellpadding="5" | {| border="1" cellspacing="0" cellpadding="5" | ||
− | |+ | + | |+ |
! Type !! Start Address !! End Address !! Size | ! Type !! Start Address !! End Address !! Size | ||
|-valign="top" | |-valign="top" | ||
− | | Flash || 0x000000 || | + | | Flash || 0x000000 ||0x02ABFF || 171K<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 || | + | | +--Flash: Alternate Vector Table || 0x000104 ||0x0001FF || 252 |
|-valign="top" | |-valign="top" | ||
− | | +--Flash: User Program || | + | | +--Flash: User Program || 0x000200 ||0x02ABFF || 170.5K |
|-valign="top" | |-valign="top" | ||
− | | | + | | Programming Executive || 0x800000 || 0x800FFF || 4K<sup>[1]</sup> |
|-valign="top" | |-valign="top" | ||
− | | | + | | Config Registers || 0xF80000 || 0xF80017 || 24 |
|-valign="top" | |-valign="top" | ||
− | + | | Device ID (0xF5) || 0xFF0000 || 0xFF0003 || 4 | |
− | |||
− | |||
− | |||
− | | Device ID || 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 | + | [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 fathom 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 39: | Line 38: | ||
|-valign="top" | |-valign="top" | ||
| _XDATA(N) <sup>[1]</sup> | | _XDATA(N) <sup>[1]</sup> | ||
− | | RAM Data in X-memory, aligned at N, with | + | | RAM Data in X-memory, aligned at N, with initialization |
| int _XDATA(32) xbuf[] = {1, 2, 3, 4, 5}; | | int _XDATA(32) xbuf[] = {1, 2, 3, 4, 5}; | ||
|-valign="top" | |-valign="top" | ||
| _YBSS(N) <sup>[1]</sup> | | _YBSS(N) <sup>[1]</sup> | ||
− | | RAM Data in Y-memory, aligned at N, no | + | | RAM Data in Y-memory, aligned at N, no initialization |
| int _YBSS(32) ybuf[16]; | | int _YBSS(32) ybuf[16]; | ||
|-valign="top" | |-valign="top" | ||
| _YDATA(N) <sup>[1]</sup> | | _YDATA(N) <sup>[1]</sup> | ||
− | | RAM Data in Y-memory, aligned at N, with | + | | RAM Data in Y-memory, aligned at N, with initialization |
| int _YDATA(32) ybuf[16] = {1, 2, 3, 4, 5}; | | int _YDATA(32) ybuf[16] = {1, 2, 3, 4, 5}; | ||
+ | |-valign="top" | ||
+ | | __attribute__((space(dma)) | ||
+ | | RAM Data in DMA | ||
+ | | int __attribute__((space(dma)) data[128]; | ||
|-valign="top" | |-valign="top" | ||
| __attribute__((space(const))) | | __attribute__((space(const))) | ||
Line 65: | Line 68: | ||
| Flash ROM data, read/write by (psv) | | Flash ROM data, read/write by (psv) | ||
| int i __attribute__((space(psv))); | | int i __attribute__((space(psv))); | ||
− | |||
− | |||
− | |||
− | |||
|-valign="top" | |-valign="top" | ||
| _PERSISTENT | | _PERSISTENT | ||
Line 78: | 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); |
− | |||
− | |||
− | |||
− | |||
|- | |- | ||
|} | |} | ||
Line 90: | Line 85: | ||
− | == | + | ===[http://chungyan5.no-ip.org/vc/trunk/posix/asm-dsPic/types.h?root=freertos_posix&view=markup <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))) | ||
+ | |||
+ | |||
+ | ===[http://chungyan5.no-ip.org/vc/trunk/demo_posix/dspic/dspic33/linker/p33FJ256GP506.gld?root=freertos_posix&view=markup 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 98: | Line 158: | ||
*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 | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | == | + | ===[http://chungyan5.no-ip.org/vc/trunk/demo_posix/dspic/dspic33/boot/boot.c?root=freertos_posix&view=markup 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(); | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | == | + | ===[http://chungyan5.no-ip.org/vc/trunk/posix/asm-dsPic/system.h?root=freertos_posix&view=markup <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 167: | Line 206: | ||
#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== | |
− | + | *[http://chungyan5.no-ip.org/vc/trunk/demo_posix/dspic/drivers/devices.c?root=freertos_posix&view=markup 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. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | === | + | ===[http://chungyan5.no-ip.org/vc/trunk/demo_posix/dspic/drivers/uart.c?root=freertos_posix&view=markup 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== | + | ===[http://chungyan5.no-ip.org/vc/trunk/demo_posix/dspic/drivers/i2c.c?root=freertos_posix&view=markup 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 400: | Line 225: | ||
#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. |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | ===[http://chungyan5.no-ip.org/vc/trunk/demo_posix/dspic/drivers/adc.c?root=freertos_posix&view=markup 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)== | + | ===[http://chungyan5.no-ip.org/vc/trunk/demo_posix/dspic/drivers/pwm.c?root=freertos_posix&view=markup 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 868: | Line 245: | ||
{| 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 905: | Line 282: | ||
|} | |} | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | === | + | === run-time self-programming flash === |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Some chips allow programs to write to flash memory (program memory); | |
− | + | this process is called RTSP (run-time self-programming). | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | == | + | [http://chungyan5.no-ip.org/vc/trunk/demo_posix/dspic/drivers/flash_eeprom.c?root=freertos_posix&view=markup Flash-emulated EEPROM] |
− | * | + | *Using built-in functions __builtin_tblpage(), __builtin_tbloffset() to set special-purpose registers to access flash memory |
− | * | + | *Using [http://chungyan5.no-ip.org/vc/trunk/demo_posix/dspic/drivers/rtsp.s?root=freertos_posix&view=markup assembly code] to read and write flash memory. |
− | |||
− | + | [http://electronics.stackexchange.com/questions/20970/trying-to-get-my-head-around-rtsp-and-failing-miserably "Trying to get my head around RTSP"] | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
+ | The KeaDrone project has some code for reading and writing flash on a PIC24F chip: | ||
+ | [http://keadrone.googlecode.com/svn-history/r2/trunk/KeaDrone/24F-source/flashSaveOperations.c ] | ||
==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,032: | Line 306: | ||
#Transform | #Transform | ||
#Control | #Control | ||
+ | |||
===Data Types=== | ===Data Types=== | ||
Line 1,050: | Line 325: | ||
− | == | + | ===Fast Fourier Transform=== |
− | * | + | *to be added |
− | |||
− | |||
− | |||
− | |||
− |
Latest revision as of 07:11, 19 October 2011
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[edit]
Memory Map for dsPIC33FJ256GP506[edit]
Type | Start Address | End Address | Size |
---|---|---|---|
Flash | 0x000000 | 0x02ABFF | 171K[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 | 0x02ABFF | 170.5K |
Programming Executive | 0x800000 | 0x800FFF | 4K[1] |
Config Registers | 0xF80000 | 0xF80017 | 24 |
Device ID (0xF5) | 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 fathom byte.
Data Location[edit]
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 initialization | int _XDATA(32) xbuf[] = {1, 2, 3, 4, 5}; |
_YBSS(N) [1] | RAM Data in Y-memory, aligned at N, no initialization | int _YBSS(32) ybuf[16]; |
_YDATA(N) [1] | RAM Data in Y-memory, aligned at N, with initialization | int _YDATA(32) ybuf[16] = {1, 2, 3, 4, 5}; |
__attribute__((space(dma)) | RAM Data in DMA | int __attribute__((space(dma)) data[128]; |
__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))); |
_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); |
- N must be a power of two, with a minimum value of 2.
<asm/types.h>[edit]
- 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[edit]
- 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[edit]
Clock Speed[edit]
- 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[edit]
- 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>[edit]
- 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[edit]
- 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[edit]
- 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[edit]
- 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[edit]
- 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)[edit]
- 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 |
run-time self-programming flash[edit]
Some chips allow programs to write to flash memory (program memory); this process is called RTSP (run-time self-programming).
- 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.
"Trying to get my head around RTSP"
The KeaDrone project has some code for reading and writing flash on a PIC24F chip: [1]
DSP Library[edit]
- Not POSIX compliant
- Library functions in <dsp.h> include the following categories:
- Vector
- Window
- Matrix
- Filtering
- Transform
- Control
Data Types[edit]
- 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)
Fast Fourier Transform[edit]
- to be added