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
3864void 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
4471void 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
55126void 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
65141void 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
82207bool 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) {
98227bool 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
107254bool 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
0 commit comments