YAHAL
Yet Another Hardware Abstraction Library
Loading...
Searching...
No Matches
gpio_msp432.cpp
1/*
2 * gpio_msp432.cpp
3 *
4 * Created on: 29.02.2016
5 * Author: Andreas Terstegge
6 */
7
8#include "msp.h"
9#include "gpio_msp432.h"
10#include <cassert>
11
12// GPIO register offsets
13#define PORT_IN_OFS 0x00
14#define PORT_OUT_OFS 0x02
15#define PORT_DIR_OFS 0x04
16#define PORT_REN_OFS 0x06
17#define PORT_SEL0_OFS 0x0a
18#define PORT_SEL1_OFS 0x0c
19#define PORT_IES_OFS 0x18
20#define PORT_IE_OFS 0x1a
21#define PORT_IFG_OFS 0x1c
22
23// Bit-Band base addresses of the 10 GPIO ports
24volatile uint8_t *port_base[10] = {
25 &BITBAND_PERI(P1->IN, 0),
26 &BITBAND_PERI(P2->IN, 0),
27 &BITBAND_PERI(P3->IN, 0),
28 &BITBAND_PERI(P4->IN, 0),
29 &BITBAND_PERI(P5->IN, 0),
30 &BITBAND_PERI(P6->IN, 0),
31 &BITBAND_PERI(P7->IN, 0),
32 &BITBAND_PERI(P8->IN, 0),
33 &BITBAND_PERI(P9->IN, 0),
34 &BITBAND_PERI(P10->IN, 0)
35};
36
37#define DIO_BIT(p, bit, off) (*((__IO uint8_t *) (port_base[p-1] + (bit<<2) + (off<<5))))
38
39function<void()> gpio_msp432::_intHandler[6][8];
40bool gpio_msp432::_both[6][8] = {0};
41
42void gpio_msp432::gpioMode(uint16_t mode) {
43 setSEL(0);
44 setMode(mode);
45}
46
47bool gpio_msp432::gpioRead() const {
48 assert((_port > 0) && (_port < 11) && (_pin < 8));
49 return DIO_BIT(_port, _pin, PORT_IN_OFS);
50}
51
52void gpio_msp432::gpioWrite(bool value) {
53 assert((_port > 0) && (_port < 11) && (_pin < 8));
54 if (_open_drain) {
55 if (_pull_up) {
56 if (value) {
57 DIO_BIT(_port, _pin, PORT_DIR_OFS) = LOW;
58 DIO_BIT(_port, _pin, PORT_OUT_OFS) = HIGH;
59 } else {
60 DIO_BIT(_port, _pin, PORT_OUT_OFS) = LOW;
61 DIO_BIT(_port, _pin, PORT_DIR_OFS) = HIGH;
62 }
63 } else {
64 // Open drain without pullup
65 DIO_BIT(_port, _pin, PORT_DIR_OFS) = !value;
66 }
67 } else if (_open_source) {
68 if (_pull_down) {
69 if (value) {
70 DIO_BIT(_port, _pin, PORT_OUT_OFS) = HIGH;
71 DIO_BIT(_port, _pin, PORT_DIR_OFS) = HIGH;
72 } else {
73 DIO_BIT(_port, _pin, PORT_DIR_OFS) = LOW;
74 DIO_BIT(_port, _pin, PORT_OUT_OFS) = LOW;
75 }
76 } else {
77 // Open source without pull down
78 DIO_BIT(_port, _pin, PORT_DIR_OFS) = value;
79 }
80 } else {
81 // No open drain/source
82 DIO_BIT(_port, _pin, PORT_OUT_OFS) = value;
83 }
84}
85
86void gpio_msp432::gpioToggle() {
87 assert((_port > 0) && (_port < 11) && (_pin < 8));
88 gpioWrite(!DIO_BIT(_port, _pin, PORT_IN_OFS));
89}
90
91void gpio_msp432::gpioAttachIrq(gpio_mode_t mode,
92 function<void()> handler) {
93 assert((_port > 0) && (_port < 11) && (_pin < 8));
94 switch (mode) {
95 case GPIO::RISING: {
96 DIO_BIT(_port, _pin, PORT_IES_OFS) = 0;
97 _both[_port - 1][_pin] = false;
98 break;
99 }
100 case GPIO::FALLING: {
101 DIO_BIT(_port, _pin, PORT_IES_OFS) = 1;
102 _both[_port - 1][_pin] = false;
103 break;
104 }
105 case GPIO::FALLING | GPIO::RISING: {
106 DIO_BIT(_port, _pin, PORT_IES_OFS) = DIO_BIT(_port, _pin, PORT_IN_OFS);
107 _both[_port - 1][_pin] = true;
108 break;
109 }
110 default:
111 assert(false);
112 }
113 // store handler addr
114 _intHandler[_port - 1][_pin] = handler;
115
116 // Reset all pending IRQs
117 for (uint32_t i = 0; i < 8; ++i) {
118 DIO_BIT(_port, i, PORT_IFG_OFS) = 0;
119 }
120 gpioEnableIrq();
121}
122
123void gpio_msp432::gpioDetachIrq() {
124 assert((_port > 0) && (_port < 11) && (_pin < 8));
125 gpioDisableIrq();
126 _intHandler[_port - 1][_pin] = 0;
127}
128
129void gpio_msp432::gpioEnableIrq() {
130 assert((_port > 0) && (_port < 11) && (_pin < 8));
131 // Clear pending interrupts
132 DIO_BIT(_port, _pin, PORT_IFG_OFS) = LOW;
133 DIO_BIT(_port, _pin, PORT_IE_OFS) = HIGH;
134 NVIC_EnableIRQ((IRQn_Type) (34 + _port));
135}
136
137void gpio_msp432::gpioDisableIrq() {
138 assert((_port > 0) && (_port < 11) && (_pin < 8));
139 DIO_BIT(_port, _pin, PORT_IE_OFS) = LOW;
140}
141
142void gpio_msp432::handleIrq(uint8_t port, uint8_t pin) {
143 _intHandler[port - 1][pin]();
144 if (_both[port - 1][pin]) {
145 DIO_BIT(port, pin, PORT_IES_OFS) = DIO_BIT(port, pin, PORT_IN_OFS);
146 // Make sure we don't accidentally trigger a irq!
147 DIO_BIT(port, pin, PORT_IFG_OFS) = 0;
148 }
149}
150
151void gpio_msp432::setSEL(uint8_t mode) const {
152 assert((_port > 0) && (_port < 11) && (_pin < 8));
153 DIO_BIT(_port, _pin, PORT_SEL0_OFS) = mode & 0x01;
154 DIO_BIT(_port, _pin, PORT_SEL1_OFS) = (mode >> 1) & 0x01;
155}
156
157void gpio_msp432::setMode(uint16_t mode) {
158 assert((_port > 0) && (_port < 11) && (_pin < 8));
159 // Set mode to default state
160 _open_drain = false;
161 _open_source= false;
162 _pull_up = false;
163 _pull_down = false;
164 DIO_BIT(_port, _pin, PORT_DIR_OFS) = LOW;
165 DIO_BIT(_port, _pin, PORT_REN_OFS) = LOW;
166 DIO_BIT(_port, _pin, PORT_OUT_OFS) = LOW;
167
168 if (mode & GPIO::INPUT) {
169 // Default is okay
170 }
171 if (mode & GPIO::OUTPUT) {
172 DIO_BIT(_port, _pin, PORT_DIR_OFS) = HIGH;
173 }
174 if (mode & GPIO::OUTPUT_OPEN_DRAIN) {
175 _open_drain = true;
176 }
177 if (mode & GPIO::OUTPUT_OPEN_SOURCE) {
178 _open_source = true;
179 DIO_BIT(_port, _pin, PORT_OUT_OFS) = HIGH;
180 }
181 if (mode & GPIO::PULLUP) {
182 _pull_up = true;
183 DIO_BIT(_port, _pin, PORT_REN_OFS) = HIGH;
184 DIO_BIT(_port, _pin, PORT_OUT_OFS) = HIGH;
185 }
186 if (mode & GPIO::PULLDOWN) {
187 _pull_down = true;
188 DIO_BIT(_port, _pin, PORT_REN_OFS) = HIGH;
189 }
190 if (mode & (GPIO::SLOW | GPIO::FAST)) {
191 assert(false);
192 }
193 if (mode & GPIO::INIT_HIGH) {
194 gpioWrite(HIGH);
195 }
196 if (mode & GPIO::INIT_LOW) {
197 gpioWrite(LOW);
198 }
199}
200
201// Interrupt handler for P1...P6
203extern "C" {
204void PORT1_IRQHandler(void) {
205 uint32_t pin = P1->IV >> 1;
206 if (pin--) {
207 gpio_msp432::handleIrq(1, pin);
208 }
209}
210void PORT2_IRQHandler(void) {
211 uint32_t pin = P2->IV >> 1;
212 if (pin--) {
213 gpio_msp432::handleIrq(2, pin);
214 }
215}
216void PORT3_IRQHandler(void) {
217 uint32_t pin = P3->IV >> 1;
218 if (pin--) {
219 gpio_msp432::handleIrq(3, pin);
220 }
221}
222void PORT4_IRQHandler(void) {
223 uint32_t pin = P4->IV >> 1;
224 if (pin--) {
225 gpio_msp432::handleIrq(4, pin);
226 }
227}
228void PORT5_IRQHandler(void) {
229 uint32_t pin = P5->IV >> 1;
230 if (pin--) {
231 gpio_msp432::handleIrq(5, pin);
232 }
233}
234void PORT6_IRQHandler(void) {
235 uint32_t pin = P6->IV >> 1;
236 if (pin--) {
237 gpio_msp432::handleIrq(6, pin);
238 }
239}
240} // extern "C"
241