各プロセッサには、そのプロセッサのSFR名やマクロを定義したヘッダファイルが用意されています。このファイルは、
#include <p30fxx.h> // xxは、プロセッサのデバイス番号
のように読み込め、既定では/Microchip/MPLAB C30/support/dsPIC30F/h/にあります。
プロセッサ ヘッダファイル内では次のような定義がなされており、SFR名を変数名のようにしてレジスタにアクセスできるようになっています。
/* CORCON: CPU Mode control Register */ extern volatile unsigned int CORCON __attribute__((__sfr__)); typedef struct tagCORCONBITS { unsigned IF :1; /* Integer/Fractional mode */ unsigned RND :1; /* Rounding mode */ unsigned PSV :1; /* Program Space Visibility enable */ unsigned IPL3 :1; /* CPU Interrupt Priority Level bit 3 */ unsigned ACCSAT :1; /* Acc saturation mode */ unsigned SATDW :1; /* Data space write saturation enable */ unsigned SATB :1; /* Acc B saturation enable */ unsigned SATA :1; /* Acc A saturation enable */ unsigned DL :3; /* DO loop nesting level status */ unsigned EDT :1; /* Early DO loop termination control */ unsigned US :1; /* Signed/Unsigned mode */ unsigned :3; } CORCONBITS; extern volatile CORCONBITS CORCONbits __attribute__((__sfr__));※__attribute__((__sfr__))は、変数がSFRであることを宣言するMPLAB Cコンパイラのキーワード
レジスタの各ビットにアクセスするには、
CORCONbits.IF
のように記述します。または、
/* CORCON */
#define _IF CORCONbits.IF
#define _RND CORCONbits.RND
#define _PSV CORCONbits.PSV
#define _IPL3 CORCONbits.IPL3
#define _ACCSAT CORCONbits.ACCSAT
#define _SATDW CORCONbits.SATDW
#define _SATB CORCONbits.SATB
#define _SATA CORCONbits.SATA
#define _DL CORCONbits.DL
#define _EDT CORCONbits.EDT
#define _US CORCONbits.US
のようなマクロが定義されているので、「_IF」とも記述できます。
プロセッサ ヘッダファイルではSFRの名前が定義されているだけであり、SFRのアドレスは/Microchip/MPLAB C30/support/dsPIC30F/gld/にあるレジスタ定義ファイルで定義されています。
プロセッサ ヘッダファイルには、上記のSFRに加え次のマクロが定義されています。
コンフィギュレーションの設定を行います。このマクロは、
extern __attribute__((space(prog))) int _FOSC; #define _FOSC(x) __attribute__((section("__FOSC.sec"),space(prog))) int _FOSC = (x);
のようなもので、
_FOSC( OPT1_ON & OPT2_OFF & OPT3_PLL );
のように使用します。
C言語内でアセンブリコードを定義するマクロで、次の4つがあります。
#define Nop() __builtin_nop() #define ClrWdt() {__asm__ volatile ("clrwdt");} #define Sleep() {__asm__ volatile ("pwrsav #0");} #define Idle() {__asm__ volatile ("pwrsav #1");}
この内、下の3つは関数の呼び出しではなく、直接アセンブリコードに展開されます。
データメモリ内に空間を割り当てるマクロです。
#define _XBSS(N) __attribute__((space(xmemory),aligned(N))) #define _XDATA(N) __attribute__((space(xmemory),aligned(N))) #define _YBSS(N) __attribute__((space(ymemory),aligned(N))) #define _YDATA(N) __attribute__((space(ymemory),aligned(N))) #define _EEDATA(N) __attribute__((space(eedata),aligned(N)))
32バイトアドレスに整列されるXメモリ内の初期化されていない配列を宣言するには、
int _XBSS(32) xbuf[16];
とします。presistentデータメモリ、またはnearメータメモリ内に変数を配置するには、
#define _PERSISTENT __attribute__((persistent)) #define _NEAR __attribute__((near))
の2つのマクロがあります。
ISR (割り込みサービスルーチン) を宣言するマクロです。
#define _ISR __attribute__((interrupt)) #define _ISRFAST __attribute__((interrupt, shadow))
CPU割り込み優先順位を設定するマクロです。
#define SET_CPU_IPL(ipl) { \ int DISI_save; \ \ DISI_save = DISICNT; \ asm volatile ("disi #0x3FFF"); \ SRbits.IPL = ipl; \ DISICNT = DISI_save; } (void) 0; #define SET_AND_SAVE_CPU_IPL(save_to, ipl) { \ save_to = SRbits.IPL; \ SET_CPU_IPL(ipl); } (void) 0; #define RESTORE_CPU_IPL(saved_to) SET_CPU_IPL(saved_to)