1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
#include "LPC17xx.h"
#include "GLCD.h"
#include <stdio.h>
//------- ITM Stimulus Port definitions for printf ------------------- //
#define ITM_Port8(n) (*((volatile unsigned char *)(0xE0000000+4*n)))
#define ITM_Port16(n) (*((volatile unsigned short*)(0xE0000000+4*n)))
#define ITM_Port32(n) (*((volatile unsigned long *)(0xE0000000+4*n)))
#define DEMCR (*((volatile unsigned long *)(0xE000EDFC)))
#define TRCENA 0x01000000
struct __FILE { int handle; };
FILE __stdout;
FILE __stdin;
int fputc(int ch, FILE *f) {
if (DEMCR & TRCENA) {
while (ITM_Port32(0) == 0);
ITM_Port8(0) = ch;
}
return(ch);
}
//------------------------------------------------------------------- //
#define __USE_LCD 0 // Uncomment to use the LCD
#define __FI 1 // Font index 16x24
// Bit Band Macros used to calculate the alias address at run time
#define ADDRESS(x) (*((volatile unsigned long *)(x)))
#define BitBand(x, y) ADDRESS(((unsigned long)(x) & 0xF0000000) | 0x02000000 |(((unsigned long)(x) & 0x000FFFFF) << 5) | ((y) << 2))
#ifdef __USE_LCD
static inline void method2lcd(unsigned char* msg) {
GLCD_DisplayString(6, 8, __FI, msg);
}
#endif
// Simple register masking
static void method_mask(){
LPC_GPIO1->FIOPIN ^= (1 << 28);
LPC_GPIO2->FIOPIN ^= (1 << 2);
}
// Define pointer with bitband method
static void method_function(){
volatile unsigned long* bit1 = &BitBand(&LPC_GPIO1->FIOPIN, 29);
volatile unsigned long* bit2 = &BitBand(&LPC_GPIO2->FIOPIN, 3);
static _Bool state = 1;
*bit1 = *bit2 = state;
state = !state;
}
// Raw bitbanding
static void method_bitbanding() {
const size_t addr1 = 0x22000000 + (0x2009C034 * 32UL) + (31 * 4);
const size_t addr2 = 0x22000000 + (0x2009C054 * 32UL) + (4 * 4);
static _Bool state = 1;
ADDRESS(addr1) = ADDRESS(addr2) = state;
state = !state;
}
void SysTick_Handler(void) {
static size_t tick = 0;
static size_t state = 0;
if (tick++ < 500) { return; }
tick = 0;
// Uses MOVS instruction to implement jump table
if (state == 0) { method_mask(); state++; }
else if (state == 1) { method_function(); state++; }
else if (state == 2) { method_bitbanding(); state = 0; }
#ifdef __USE_LCD
if (state == 1) { method2lcd("MASK "); }
else if (state == 2) { method2lcd("FUNCTION"); }
else if (state == 0) { method2lcd("BITBAND "); }
#endif
}
int main(void){
LPC_SC->PCONP |= (1 << 15); /* enable power to GPIO & IOCON */
LPC_GPIO1->FIODIR |= 0xB0000000; /* LEDs on PORT1 are output */
LPC_GPIO2->FIODIR |= 0x0000007C; /* LEDs on PORT2 are output */
// Configure SysTick with interrupt and internal clock source
ADDRESS(0xE000E010) = (1 << 0) | (1 << 1) | (1 << 2);
// Run handler every 1ms
ADDRESS(0xE000E014) = 99999;
#ifdef __USE_LCD
GLCD_Init(); /* Initialize graphical LCD (if enabled */
GLCD_Clear(White); /* Clear graphical LCD display */
GLCD_SetBackColor(Blue);
GLCD_SetTextColor(Yellow);
GLCD_DisplayString(0, 0, __FI, " COE718 Lab 2 ");
GLCD_SetTextColor(White);
GLCD_DisplayString(1, 0, __FI, " bitband.c ");
GLCD_DisplayString(2, 0, __FI, " Watch the LEDs! ");
GLCD_SetBackColor(White);
GLCD_SetTextColor(Blue);
GLCD_DisplayString(6, 0, __FI, "Method:");
#endif
// Let SysTick callback run in background
while (1) {}
}
|