The PIC32 library include files contain numerous examples of definitions of bit fields for the manipulation of the control bits in various special function registers (SFRs).
Below is an example from the PIC32, where the Timer1 module control register T1CON is defined and each individual control bit is exposed:
extern volatile unsigned int T1CON __attribute__((section("sfrs"))); typedef union { struct { unsigned :1; unsigned TCS:1; unsigned TSYNC:1; unsigned :1; unsigned TCKPS0:1; unsigned TCKPS1:1; unsigned :1; unsigned TGATE:1; unsigned :3; unsigned TWIP:1; unsigned TWDIS:1; unsigned SIDL:1; unsigned FRZ:1; unsigned ON:1; }; struct { unsigned :4; unsigned TCKPS:2; unsigned :7; unsigned TSIDL:1; unsigned :1; unsigned TON:1; }; struct { unsigned w:32; }; } __T1CONbits_t; extern volatile __T1CONbits_t T1CONbits asm ("T1CON") __attribute__((section("sfrs")));
The example program, modified from timer3, uses Timer1 to schedule changes to an LED. The example uses bit fields to control the timer and LED.
Of particuliar interest, we observe the disassembly of line 39:
39: T1CONbits.TCKPS = 3; // Set prescaller to 1:256 lui a0,0xbf80 a0 <= base address (0xbf800000) lw v0,1536(a0) v0 <= T1CONbits (a0+1536)note 1 addiu v1,zero,3 v1 <= 3 ins v0,v1,4,2 v0 <= insert_bitfield(v1,4,2) sw v0,1536(a0) T1CONbits <= v0where the ins instruction (insert bitfield) is used. This is the companion instruction to ext (extract bitfield).
Note 1: T1CON address = 0xBF800600 and 0x600 = 153610
C Source: bitfields.zip
01: /* bitfield3.c 02: * 03: */ 04: 05: #include <plib.h> 06: 07: void wait(); 08: 09: typedef union { 10: struct { 11: unsigned int LED1: 1; 12: unsigned int LED2: 1; 13: unsigned int LED3: 1; 14: }; 15: unsigned int w; 16: } leds_t; 17: 18: 19: 20: int main() 21: { 22: int i; 23: leds_t leds; 24: leds.w = 0; 25: leds.LED2 = 1; 26: mPORTDSetPinsDigitalOut(leds.w); /* Make selected leds output */ 27: mPORTDClearBits(leds.w); /* Turn off selected leds on startup */ 28: while (1) { 29: mPORTDToggleBits(leds.w); /* Toggle selected leds */ 30: wait(); 31: } 32: return 0; 33: } 34: 35: void wait() 36: { 37: const int DLY = 5000; 38: T1CON = 0; // turn timer off and clear all bits 39: T1CONbits.TCKPS = 3; // Set prescaller to 1:256 40: TMR1 = 0; 41: PR1 = 0xFFFF; 42: T1CONbits.TON = 1; // start timer 43: while (TMR1 < DLY) { 44: // just wait 45: } 46: T1CONbits.TON = 0; // stop timer 47: }
--- C:\pic32\test\bitfield3.c ------------------------------------------------------------------ 1: /* bitfield3.c 2: * 3: */ 4: 5: #include6: 7: void wait(); 8: 9: typedef union { 10: struct { 11: unsigned int LED1: 1; 12: unsigned int LED2: 1; 13: unsigned int LED3: 1; 14: }; 15: unsigned int w; 16: } leds_t; 17: 18: 19: 20: int main() 21: { 9D000018 27BDFFE0 addiu sp,sp,-32 9D00001C AFBF001C sw ra,28(sp) 9D000020 AFBE0018 sw s8,24(sp) 9D000024 03A0F021 addu s8,sp,zero 22: int i; 23: leds_t leds; 24: leds.w = 0; 9D000028 AFC00014 sw zero,20(s8) 25: leds.LED2 = 1; 9D00002C 8FC20014 lw v0,20(s8) 9D000030 34420002 ori v0,v0,0x2 9D000034 AFC20014 sw v0,20(s8) 26: mPORTDSetPinsDigitalOut(leds.w); /* Make selected leds output */ 9D000038 3C03BF88 lui v1,0xbf88 9D00003C 8FC20014 lw v0,20(s8) 9D000040 AC6260C4 sw v0,24772(v1) 27: mPORTDClearBits(leds.w); /* Turn off selected leds on startup */ 9D000044 3C03BF88 lui v1,0xbf88 9D000048 8FC20014 lw v0,20(s8) 9D00004C AC6260E4 sw v0,24804(v1) 28: while (1) { 29: mPORTDToggleBits(leds.w); /* Toggle selected leds */ 9D000050 3C03BF88 lui v1,0xbf88 9D000054 8FC20014 lw v0,20(s8) 9D000058 AC6260EC sw v0,24812(v1) 30: wait(); 9D00005C 0F40001B jal 0x9d00006c 9D000060 00000000 nop 9D000064 1000FFFA beq zero,zero,0x9d000050 9D000068 00000000 nop 31: } 32: return 0; 33: } 34: 35: void wait() 36: { 9D00006C 27BDFFF0 addiu sp,sp,-16 9D000070 AFBE0008 sw s8,8(sp) 9D000074 03A0F021 addu s8,sp,zero 37: const int DLY = 5000; 9D000078 24021388 addiu v0,zero,5000 9D00007C AFC20000 sw v0,0(s8) 38: T1CON = 0; // turn timer off and clear all bits 9D000080 3C02BF80 lui v0,0xbf80 9D000084 AC400600 sw zero,1536(v0) 39: T1CONbits.TCKPS = 3; // Set prescaller to 1:256 9D000088 3C04BF80 lui a0,0xbf80 9D00008C 8C820600 lw v0,1536(a0) 9D000090 24030003 addiu v1,zero,3 9D000094 7C622904 ins v0,v1,4,2 9D000098 AC820600 sw v0,1536(a0) 40: TMR1 = 0; 9D00009C 3C02BF80 lui v0,0xbf80 9D0000A0 AC400610 sw zero,1552(v0) 41: PR1 = 0xFFFF; 9D0000A4 3C03BF80 lui v1,0xbf80 9D0000A8 3402FFFF ori v0,zero,0xffff 9D0000AC AC620620 sw v0,1568(v1) 42: T1CONbits.TON = 1; // start timer 9D0000B0 3C04BF80 lui a0,0xbf80 9D0000B4 90830601 lbu v1,1537(a0) 9D0000B8 2402FF80 addiu v0,zero,-128 9D0000BC 00621025 or v0,v1,v0 9D0000C0 A0820601 sb v0,1537(a0) 43: while (TMR1 < DLY) { 9D0000C4 3C02BF80 lui v0,0xbf80 9D0000C8 8FC30000 lw v1,0(s8) 9D0000CC 8C420610 lw v0,1552(v0) 9D0000D0 0043102B sltu v0,v0,v1 9D0000D4 10400003 beq v0,zero,0x9d0000e4 9D0000D8 00000000 nop 9D0000DC 1000FFF9 beq zero,zero,0x9d0000c4 9D0000E0 00000000 nop 44: // just wait 45: } 46: T1CONbits.TON = 0; // stop timer 9D0000E4 3C02BF80 lui v0,0xbf80 9D0000E8 90430601 lbu v1,1537(v0) 9D0000EC 3063007F andi v1,v1,0x7f 9D0000F0 A0430601 sb v1,1537(v0) 47: } 9D0000F4 03C0E821 addu sp,s8,zero 9D0000F8 8FBE0008 lw s8,8(sp) 9D0000FC 27BD0010 addiu sp,sp,16 9D000100 03E00008 jr ra 9D000104 00000000 nop
Maintained by John Loomis, updated Fri Aug 08 15:39:44 2008