Skip to content

Commit a81ea5e

Browse files
committed
Add complete BUSIO driver structure for SPI & I2C.
TODO: - Figure out assigning CS Pins for SPI - Test & Debug SPI / I2C Signed-off-by: Brandon-Hurst <[email protected]>
1 parent 6967949 commit a81ea5e

File tree

6 files changed

+267
-26
lines changed

6 files changed

+267
-26
lines changed

ports/analog/common-hal/busio/I2C.c

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,28 +200,72 @@ void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
200200
}
201201

202202
// Write data to the device selected by address
203+
// todo test
203204
uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr,
204205
const uint8_t *data, size_t len) {
205206

206-
// FIXME: Implement
207+
int ret;
208+
mxc_i2c_req_t wr_req = {
209+
.addr = addr,
210+
.i2c = self->i2c_regs,
211+
.tx_buf = (uint8_t *)data,
212+
.tx_len = len,
213+
.rx_buf = NULL,
214+
.rx_len = 0,
215+
.callback = NULL
216+
};
217+
ret = MXC_I2C_MasterTransaction(&wr_req);
218+
if (ret) {
219+
mp_raise_RuntimeError(MP_ERROR_TEXT("ERROR during I2C Transaction\n"));
220+
}
221+
207222
return 0;
208223
}
209224

210225
// Read into buffer from the device selected by address
226+
// todo test
211227
uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self,
212228
uint16_t addr,
213229
uint8_t *data, size_t len) {
214230

215-
// FIXME: Implement
231+
int ret;
232+
mxc_i2c_req_t rd_req = {
233+
.addr = addr,
234+
.i2c = self->i2c_regs,
235+
.tx_buf = NULL,
236+
.tx_len = 0,
237+
.rx_buf = data,
238+
.rx_len = len,
239+
.callback = NULL
240+
};
241+
ret = MXC_I2C_MasterTransaction(&rd_req);
242+
if (ret) {
243+
mp_raise_RuntimeError(MP_ERROR_TEXT("ERROR during I2C Transaction\n"));
244+
}
245+
216246
return 0;
217247
}
218248

219249
// Write the bytes from out_data to the device selected by address,
250+
// todo test
220251
uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr,
221252
uint8_t *out_data, size_t out_len,
222253
uint8_t *in_data, size_t in_len) {
223254

224-
// FIXME: Implement
255+
int ret;
256+
mxc_i2c_req_t wr_rd_req = {
257+
.addr = addr,
258+
.i2c = self->i2c_regs,
259+
.tx_buf = out_data,
260+
.tx_len = out_len,
261+
.rx_buf = in_data,
262+
.rx_len = in_len,
263+
.callback = NULL
264+
};
265+
ret = MXC_I2C_MasterTransaction(&wr_rd_req);
266+
if (ret) {
267+
mp_raise_RuntimeError(MP_ERROR_TEXT("ERROR during I2C Transaction\n"));
268+
}
225269

226270
return 0;
227271
}

ports/analog/common-hal/busio/SPI.c

Lines changed: 202 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,29 +31,105 @@
3131
#include "supervisor/board.h"
3232
#include "shared-bindings/microcontroller/Pin.h"
3333

34+
#include "max32_port.h"
35+
#include "spi_reva1.h"
36+
3437
// Note that any bugs introduced in this file can cause crashes
3538
// at startupfor chips using external SPI flash.
3639

40+
#define SPI_PRIORITY 1
41+
42+
typedef enum {
43+
SPI_FREE = 0,
44+
SPI_BUSY,
45+
SPI_NEVER_RESET,
46+
} spi_status_t;
47+
48+
// Set each bit to indicate an active SPI
49+
// will be checked by ISR Handler for which ones to call
50+
static uint8_t spi_active = 0;
51+
static spi_status_t spi_status[NUM_SPI];
52+
static volatile int spi_err;
53+
54+
// SPI Interrupt Handler
55+
void spi_isr(void) {
56+
for (int i = 0; i < NUM_SPI; i++) {
57+
if (spi_active & (1 << i)) {
58+
MXC_SPI_AsyncHandler(MXC_SPI_GET_SPI(i));
59+
}
60+
}
61+
}
62+
3763
// Reset SPI when reload
3864
void spi_reset(void) {
3965
// FIXME: Implement
4066
return;
4167
}
4268

4369
// Construct SPI protocol, this function init SPI peripheral
70+
// todo: figure out Chip select behavior
4471
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
4572
const mcu_pin_obj_t *sck,
4673
const mcu_pin_obj_t *mosi,
4774
const mcu_pin_obj_t *miso,
4875
bool half_duplex) {
76+
int temp, err = 0;
4977

78+
// Check for NULL Pointers && valid I2C settings
79+
assert(self);
5080

51-
// FIXME: Implement
81+
// Assign I2C ID based on pins
82+
temp = pinsToSpi(mosi, miso, sck);
83+
if (temp == -1) {
84+
// Error will be indicated by pinsToUart(tx, rx) function
85+
return;
86+
} else {
87+
self->spi_id = temp;
88+
self->spi_regs = MXC_SPI_GET_SPI(temp);
89+
}
90+
91+
assert((self->spi_id >= 0) && (self->spi_id < NUM_SPI));
92+
93+
// Init I2C as main / controller node (0x00 is ignored)
94+
// FIXME: MUST map the SPI pins to a spi_pins_t struct
95+
if ((mosi != NULL) && (miso != NULL) && (sck != NULL)) {
96+
// spi, mastermode, quadModeUsed, numSubs, ssPolarity, frequency
97+
err = MXC_SPI_RevA1_Init((mxc_spi_reva_regs_t *)self->spi_regs, 1, 0, 1, 0x00, 1000000);
98+
if (err) {
99+
mp_raise_RuntimeError(MP_ERROR_TEXT("Failed to init SPI.\n"));
100+
}
101+
} else {
102+
mp_raise_NotImplementedError(MP_ERROR_TEXT("SPI needs MOSI, MISO, and SCK"));
103+
}
104+
105+
// Attach SPI pins
106+
self->mosi = mosi;
107+
self->miso = miso;
108+
self->sck = sck;
109+
common_hal_mcu_pin_claim(self->mosi);
110+
common_hal_mcu_pin_claim(self->miso);
111+
common_hal_mcu_pin_claim(self->sck);
112+
113+
// Indicate to this module that the SPI is active
114+
spi_active |= (1 << self->spi_id);
115+
116+
/* Setup I2C interrupt */
117+
NVIC_ClearPendingIRQ(MXC_SPI_GET_IRQ(self->spi_id));
118+
NVIC_DisableIRQ(MXC_SPI_GET_IRQ(self->spi_id));
119+
NVIC_SetPriority(MXC_SPI_GET_IRQ(self->spi_id), SPI_PRIORITY);
120+
NVIC_SetVector(MXC_SPI_GET_IRQ(self->spi_id), (uint32_t)spi_isr);
121+
122+
return;
52123
}
53124

54125
// Never reset SPI when reload
55126
void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) {
56-
// FIXME: Implement
127+
common_hal_never_reset_pin(self->mosi);
128+
common_hal_never_reset_pin(self->miso);
129+
common_hal_never_reset_pin(self->sck);
130+
common_hal_never_reset_pin(self->nss);
131+
132+
spi_status[self->spi_id] = SPI_NEVER_RESET;
57133
}
58134

59135
// Check SPI status, deinited or not
@@ -64,7 +140,16 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) {
64140
// Deinit SPI obj
65141
void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
66142

67-
// FIXME: Implement
143+
MXC_SPI_Shutdown(self->spi_regs);
144+
common_hal_reset_pin(self->mosi);
145+
common_hal_reset_pin(self->miso);
146+
common_hal_reset_pin(self->sck);
147+
common_hal_reset_pin(self->nss);
148+
149+
self->mosi = NULL;
150+
self->miso = NULL;
151+
self->sck = NULL;
152+
self->nss = NULL;
68153
}
69154

70155
// Configures the SPI bus. The SPI object must be locked.
@@ -74,14 +159,58 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
74159
uint8_t phase,
75160
uint8_t bits) {
76161

77-
// FIXME: Implement
162+
mxc_spi_clkmode_t clk_mode;
163+
int ret;
164+
165+
self->baudrate = baudrate;
166+
self->polarity = polarity;
167+
self->phase = phase;
168+
self->bits = bits;
169+
170+
switch ((polarity << 1) | (phase)) {
171+
case 0b00:
172+
clk_mode = MXC_SPI_CLKMODE_0;
173+
break;
174+
case 0b01:
175+
clk_mode = MXC_SPI_CLKMODE_1;
176+
break;
177+
case 0b10:
178+
clk_mode = MXC_SPI_CLKMODE_2;
179+
break;
180+
case 0b11:
181+
clk_mode = MXC_SPI_CLKMODE_3;
182+
break;
183+
default:
184+
mp_raise_ValueError(MP_ERROR_TEXT("CPOL / CPHA must both be either 0 or 1\n"));
185+
return false;
186+
}
187+
188+
ret = MXC_SPI_SetFrequency(self->spi_regs, baudrate);
189+
if (ret) {
190+
mp_raise_ValueError(MP_ERROR_TEXT("Failed to set SPI Frequency\n"));
191+
return false;
192+
}
193+
ret = MXC_SPI_SetDataSize(self->spi_regs, bits);
194+
if (ret) {
195+
mp_raise_ValueError(MP_ERROR_TEXT("Failed to set SPI Frame Size\n"));
196+
return false;
197+
}
198+
ret = MXC_SPI_SetMode(self->spi_regs, clk_mode);
199+
if (ret) {
200+
mp_raise_ValueError(MP_ERROR_TEXT("Failed to set SPI Clock Mode\n"));
201+
return false;
202+
}
78203
return true;
79204
}
80205

81206
// Lock SPI bus
82207
bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) {
83-
// FIXME: Implement
84-
return false;
208+
if (spi_status[self->spi_id] != SPI_BUSY) {
209+
self->has_lock = true;
210+
return true;
211+
} else {
212+
return false;
213+
}
85214
}
86215

87216
// Check SPI lock status
@@ -98,18 +227,60 @@ void common_hal_busio_spi_unlock(busio_spi_obj_t *self) {
98227
bool common_hal_busio_spi_write(busio_spi_obj_t *self,
99228
const uint8_t *data,
100229
size_t len) {
230+
int ret = 0;
101231

102-
// FIXME: Implement
103-
return false;
232+
mxc_spi_req_t wr_req = {
233+
.spi = self->spi_regs,
234+
.ssIdx = 0,
235+
.txCnt = 0,
236+
.rxCnt = 0,
237+
.txData = (uint8_t *)data,
238+
.txLen = len,
239+
.rxData = NULL,
240+
.rxLen = 0,
241+
.ssDeassert = 1,
242+
.completeCB = NULL,
243+
.txDummyValue = 0xFF,
244+
};
245+
ret = MXC_SPI_MasterTransaction(&wr_req);
246+
if (ret) {
247+
return false;
248+
} else {
249+
return true;
250+
}
104251
}
105252

106253
// Read data into buffer
107254
bool common_hal_busio_spi_read(busio_spi_obj_t *self,
108255
uint8_t *data, size_t len,
109256
uint8_t write_value) {
110257

111-
// FIXME: Implement
112-
return false;
258+
int ret = 0;
259+
// uint8_t tx_buffer[len] = {0x0};
260+
261+
// for (int i = 0; i < len; i++) {
262+
// tx_buffer[i] = write_value;
263+
// }
264+
265+
mxc_spi_req_t rd_req = {
266+
.spi = self->spi_regs,
267+
.ssIdx = 0,
268+
.txCnt = 0,
269+
.rxCnt = 0,
270+
.txData = NULL,
271+
.txLen = len,
272+
.rxData = data,
273+
.rxLen = len,
274+
.ssDeassert = 1,
275+
.completeCB = NULL,
276+
.txDummyValue = write_value,
277+
};
278+
ret = MXC_SPI_MasterTransaction(&rd_req);
279+
if (ret) {
280+
return false;
281+
} else {
282+
return true;
283+
}
113284
}
114285

115286
// Write out the data in data_out
@@ -119,8 +290,27 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self,
119290
uint8_t *data_in,
120291
size_t len) {
121292

122-
// FIXME: Implement
123-
return false;
293+
int ret = 0;
294+
295+
mxc_spi_req_t rd_req = {
296+
.spi = self->spi_regs,
297+
.ssIdx = 0,
298+
.txCnt = 0,
299+
.rxCnt = 0,
300+
.txData = (uint8_t *)data_out,
301+
.txLen = len,
302+
.rxData = data_in,
303+
.rxLen = len,
304+
.ssDeassert = 1,
305+
.completeCB = NULL,
306+
.txDummyValue = 0xFF,
307+
};
308+
ret = MXC_SPI_MasterTransaction(&rd_req);
309+
if (ret) {
310+
return false;
311+
} else {
312+
return true;
313+
}
124314
}
125315

126316
// Get SPI baudrate

ports/analog/common-hal/busio/SPI.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,24 @@
1717
// Define a struct for what BUSIO.SPI should carry
1818
typedef struct {
1919
mp_obj_base_t base;
20+
21+
// Spi regs & pins
22+
int spi_id;
2023
mxc_spi_regs_t *spi_regs;
21-
bool has_lock;
2224
const mcu_pin_obj_t *sck;
2325
const mcu_pin_obj_t *mosi;
2426
const mcu_pin_obj_t *miso;
2527
const mcu_pin_obj_t *nss;
28+
29+
// Configuration
2630
uint32_t baudrate;
2731
uint16_t prescaler;
2832
uint8_t polarity;
2933
uint8_t phase;
3034
uint8_t bits;
35+
36+
// Synch data
37+
bool has_lock;
3138
} busio_spi_obj_t;
3239

3340
void spi_reset(void);

ports/analog/max32_port.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
// UART Ports & pins
2626
#include "peripherals/max32690/max32_uart.h"
2727
#include "peripherals/max32690/max32_i2c.h"
28+
#include "peripherals/max32690/max32_spi.h"
2829

2930
/** START: GPIO4 Handling specific to MAX32690 */
3031
#define GPIO4_PIN_MASK 0x00000003

0 commit comments

Comments
 (0)