3
3
* Copyright (c) 2015 Arduino LLC
4
4
* Copyright (c) 2016 Sandeep Mistry All right reserved.
5
5
* Copyright (c) 2017 hathach
6
+ * Copyright (c) 2018 Artur Pacholec
6
7
*
7
8
* This library is free software; you can redistribute it and/or
8
9
* modify it under the terms of the GNU Lesser General Public
19
20
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
21
*/
21
22
22
-
23
23
#include "shared-bindings/busio/SPI.h"
24
24
#include "py/mperrno.h"
25
25
#include "py/runtime.h"
26
26
27
- #include "nrf.h"
28
- #include "pins.h"
29
-
30
- // Convert frequency to clock-speed-dependent value. Return 0 if out of range.
31
- static uint32_t baudrate_to_reg (const uint32_t baudrate ) {
32
- uint32_t value ;
33
-
34
- if (baudrate <= 125000 ) {
35
- value = SPI_FREQUENCY_FREQUENCY_K125 ;
36
- } else if (baudrate <= 250000 ) {
37
- value = SPI_FREQUENCY_FREQUENCY_K250 ;
38
- } else if (baudrate <= 500000 ) {
39
- value = SPI_FREQUENCY_FREQUENCY_K500 ;
40
- } else if (baudrate <= 1000000 ) {
41
- value = SPI_FREQUENCY_FREQUENCY_M1 ;
42
- } else if (baudrate <= 2000000 ) {
43
- value = SPI_FREQUENCY_FREQUENCY_M2 ;
44
- } else if (baudrate <= 4000000 ) {
45
- value = SPI_FREQUENCY_FREQUENCY_M4 ;
46
- } else {
47
- value = SPI_FREQUENCY_FREQUENCY_M8 ;
48
- }
27
+ #include "nrfx_spim.h"
28
+ #include "nrf_gpio.h"
29
+
30
+ #if NRFX_SPIM3_ENABLED
31
+ #define INST_NO 3
32
+ #else
33
+ #define INST_NO 2
34
+ #endif
35
+
36
+ // Convert frequency to clock-speed-dependent value
37
+ static nrf_spim_frequency_t baudrate_to_spim_frequency (const uint32_t baudrate ) {
38
+ if (baudrate <= 125000 )
39
+ return NRF_SPIM_FREQ_125K ;
40
+
41
+ if (baudrate <= 250000 )
42
+ return NRF_SPIM_FREQ_250K ;
43
+
44
+ if (baudrate <= 500000 )
45
+ return NRF_SPIM_FREQ_500K ;
46
+
47
+ if (baudrate <= 1000000 )
48
+ return NRF_SPIM_FREQ_1M ;
49
+
50
+ if (baudrate <= 2000000 )
51
+ return NRF_SPIM_FREQ_2M ;
52
+
53
+ if (baudrate <= 4000000 )
54
+ return NRF_SPIM_FREQ_4M ;
55
+
56
+ if (baudrate <= 8000000 )
57
+ return NRF_SPIM_FREQ_8M ;
58
+
59
+ #ifdef SPIM_FREQUENCY_FREQUENCY_M16
60
+ if (baudrate <= 16000000 )
61
+ return NRF_SPIM_FREQ_16M ;
62
+ #endif
49
63
50
- return value ;
64
+ #ifdef SPIM_FREQUENCY_FREQUENCY_M32
65
+ return NRF_SPIM_FREQ_32M ;
66
+ #else
67
+ return NRF_SPIM_FREQ_8M ;
68
+ #endif
51
69
}
52
70
53
71
void common_hal_busio_spi_construct (busio_spi_obj_t * self , const mcu_pin_obj_t * clock , const mcu_pin_obj_t * mosi , const mcu_pin_obj_t * miso ) {
72
+ const nrfx_spim_t instance = NRFX_SPIM_INSTANCE (INST_NO );
73
+ self -> spim = instance ;
54
74
55
- // 1 for I2C, 0 for SPI
56
- self -> spi = NRF_SPI0 ;
75
+ nrfx_spim_config_t config = NRFX_SPIM_DEFAULT_CONFIG ;
76
+ config . frequency = NRF_SPIM_FREQ_8M ;
57
77
58
- self -> spi -> PSELSCK = clock -> pin ;
59
- self -> spi -> PSELMOSI = mosi -> pin ;
60
- self -> spi -> PSELMISO = miso -> pin ;
78
+ config .sck_pin = NRF_GPIO_PIN_MAP (clock -> port , clock -> pin );
61
79
80
+ if (mosi != (mcu_pin_obj_t * )& mp_const_none_obj )
81
+ config .mosi_pin = NRF_GPIO_PIN_MAP (mosi -> port , mosi -> pin );
62
82
63
- #if NRF52840_XXAA
64
- self -> spi -> PSELSCK |= (clock -> port << SPI_PSEL_SCK_PORT_Pos );
65
- self -> spi -> PSELMOSI |= (mosi -> port << SPI_PSEL_MOSI_PORT_Pos );
66
- self -> spi -> PSELMISO |= (miso -> port << SPI_PSEL_MISO_PORT_Pos );
67
- #endif
83
+ if (miso != (mcu_pin_obj_t * )& mp_const_none_obj )
84
+ config .miso_pin = NRF_GPIO_PIN_MAP (miso -> port , miso -> pin );
85
+
86
+ nrfx_err_t err = nrfx_spim_init (& self -> spim , & config , NULL , NULL );
87
+
88
+ // A soft reset doesn't uninit the driver so we might end up with a invalid state
89
+ if (err == NRFX_ERROR_INVALID_STATE ) {
90
+ nrfx_spim_uninit (& self -> spim );
91
+ err = nrfx_spim_init (& self -> spim , & config , NULL , NULL );
92
+ }
93
+
94
+ if (err != NRFX_SUCCESS )
95
+ mp_raise_OSError (MP_EIO );
96
+
97
+ self -> inited = true;
68
98
}
69
99
70
100
bool common_hal_busio_spi_deinited (busio_spi_obj_t * self ) {
71
- return self -> spi == NULL ;
101
+ return ! self -> inited ;
72
102
}
73
103
74
104
void common_hal_busio_spi_deinit (busio_spi_obj_t * self ) {
75
- if (common_hal_busio_spi_deinited (self )) {
105
+ if (common_hal_busio_spi_deinited (self ))
76
106
return ;
77
- }
78
107
79
- #ifdef NRF52840_XXAA
80
- self -> spi -> PSEL .SCK = SPI_PSEL_SCK_CONNECT_Disconnected ;
81
- self -> spi -> PSEL .MOSI = SPI_PSEL_MOSI_CONNECT_Disconnected ;
82
- self -> spi -> PSEL .MISO = SPI_PSEL_MISO_CONNECT_Disconnected ;
83
- #else
84
- self -> spi -> PSELSCK = SPI_PSEL_SCK_PSELSCK_Disconnected ;
85
- self -> spi -> PSELMOSI = SPI_PSEL_MOSI_PSELMOSI_Disconnected ;
86
- self -> spi -> PSELMISO = SPI_PSEL_MISO_PSELMISO_Disconnected ;
87
- #endif
88
- // reset_pin(self->clock_pin);
89
- // reset_pin(self->MOSI_pin);
90
- // reset_pin(self->MISO_pin);
108
+ nrfx_spim_uninit (& self -> spim );
91
109
92
- self -> spi = NULL ;
110
+ self -> inited = false ;
93
111
}
94
112
95
113
bool common_hal_busio_spi_configure (busio_spi_obj_t * self , uint32_t baudrate , uint8_t polarity , uint8_t phase , uint8_t bits ) {
96
114
// nrf52 does not support 16 bit
97
- if ( bits != 8 ) return false;
98
-
99
- self -> spi -> ENABLE = (SPI_ENABLE_ENABLE_Disabled << SPI_ENABLE_ENABLE_Pos );
115
+ if (bits != 8 )
116
+ return false;
100
117
101
- uint32_t config = ( SPI_CONFIG_ORDER_MsbFirst << SPI_CONFIG_ORDER_Pos );
118
+ nrf_spim_frequency_set ( self -> spim . p_reg , baudrate_to_spim_frequency ( baudrate ) );
102
119
103
- config |= ((polarity ? SPI_CONFIG_CPOL_ActiveLow : SPI_CONFIG_CPOL_ActiveHigh ) << SPI_CONFIG_CPOL_Pos );
104
- config |= ((phase ? SPI_CONFIG_CPHA_Trailing : SPI_CONFIG_CPHA_Leading ) << SPI_CONFIG_CPHA_Pos );
105
-
106
- self -> spi -> CONFIG = config ;
107
- self -> spi -> FREQUENCY = baudrate_to_reg (baudrate );
120
+ nrf_spim_mode_t mode = NRF_SPIM_MODE_0 ;
121
+ if (polarity ) {
122
+ mode = (phase ) ? NRF_SPIM_MODE_3 : NRF_SPIM_MODE_2 ;
123
+ } else {
124
+ mode = (phase ) ? NRF_SPIM_MODE_1 : NRF_SPIM_MODE_0 ;
125
+ }
108
126
109
- self -> spi -> ENABLE = ( SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos );
127
+ nrf_spim_configure ( self -> spim . p_reg , mode , NRF_SPIM_BIT_ORDER_MSB_FIRST );
110
128
111
129
return true;
112
130
}
@@ -131,87 +149,59 @@ void common_hal_busio_spi_unlock(busio_spi_obj_t *self) {
131
149
}
132
150
133
151
bool common_hal_busio_spi_write (busio_spi_obj_t * self , const uint8_t * data , size_t len ) {
134
- if (len == 0 ) {
135
- return true;
136
- }
137
-
138
- while (len )
139
- {
140
- self -> spi -> TXD = * data ;
152
+ if (len == 0 )
153
+ return true;
141
154
142
- while (!self -> spi -> EVENTS_READY );
143
-
144
- (void ) self -> spi -> RXD ;
145
- data ++ ;
146
- len -- ;
147
-
148
- self -> spi -> EVENTS_READY = 0x0UL ;
149
- }
155
+ const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX (data , len );
156
+ const nrfx_err_t err = nrfx_spim_xfer (& self -> spim , & xfer , 0 );
150
157
151
- return true ;
158
+ return ( err == NRFX_SUCCESS ) ;
152
159
}
153
160
154
161
bool common_hal_busio_spi_read (busio_spi_obj_t * self , uint8_t * data , size_t len , uint8_t write_value ) {
155
- if (len == 0 ) {
156
- return true;
157
- }
158
-
159
- while (len )
160
- {
161
- self -> spi -> TXD = write_value ;
162
+ if (len == 0 )
163
+ return true;
162
164
163
- while (!self -> spi -> EVENTS_READY );
165
+ const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX (data , len );
166
+ const nrfx_err_t err = nrfx_spim_xfer (& self -> spim , & xfer , 0 );
164
167
165
- * data = self -> spi -> RXD ;
166
-
167
- data ++ ;
168
- len -- ;
169
-
170
- self -> spi -> EVENTS_READY = 0x0UL ;
171
- }
172
-
173
- return true;
168
+ return (err == NRFX_SUCCESS );
174
169
}
175
170
176
171
bool common_hal_busio_spi_transfer (busio_spi_obj_t * self , uint8_t * data_out , uint8_t * data_in , size_t len ) {
177
- if (len == 0 ) {
178
- return true;
179
- }
180
-
181
- while (len )
182
- {
183
- self -> spi -> TXD = * data_out ;
184
-
185
- while (!self -> spi -> EVENTS_READY );
186
-
187
- * data_in = self -> spi -> RXD ;
172
+ if (len == 0 )
173
+ return true;
188
174
189
- data_out ++ ;
190
- data_in ++ ;
191
- len -- ;
175
+ const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER (data_out , len , data_in , len );
176
+ const nrfx_err_t err = nrfx_spim_xfer (& self -> spim , & xfer , 0 );
192
177
193
- self -> spi -> EVENTS_READY = 0x0UL ;
194
- }
195
-
196
- return true;
178
+ return (err == NRFX_SUCCESS );
197
179
}
198
-
180
+
199
181
uint32_t common_hal_busio_spi_get_frequency (busio_spi_obj_t * self ) {
200
- switch (self -> spi -> FREQUENCY ) {
201
- case SPI_FREQUENCY_FREQUENCY_K125 :
182
+ switch (self -> spim . p_reg -> FREQUENCY ) {
183
+ case NRF_SPIM_FREQ_125K :
202
184
return 125000 ;
203
- case SPI_FREQUENCY_FREQUENCY_K250 :
185
+ case NRF_SPIM_FREQ_250K :
204
186
return 250000 ;
205
- case SPI_FREQUENCY_FREQUENCY_K500 :
187
+ case NRF_SPIM_FREQ_500K :
206
188
return 500000 ;
207
- case SPI_FREQUENCY_FREQUENCY_M1 :
189
+ case NRF_SPIM_FREQ_1M :
208
190
return 1000000 ;
209
- case SPI_FREQUENCY_FREQUENCY_M2 :
191
+ case NRF_SPIM_FREQ_2M :
210
192
return 2000000 ;
211
- case SPI_FREQUENCY_FREQUENCY_M4 :
193
+ case NRF_SPIM_FREQ_4M :
212
194
return 4000000 ;
213
- case SPI_FREQUENCY_FREQUENCY_M8 :
195
+ case NRF_SPIM_FREQ_8M :
214
196
return 8000000 ;
197
+ #ifdef SPIM_FREQUENCY_FREQUENCY_M16
198
+ case NRF_SPIM_FREQ_16M :
199
+ return 16000000 ;
200
+ #endif
201
+ #ifdef SPIM_FREQUENCY_FREQUENCY_M32
202
+ case NRF_SPIM_FREQ_32M :
203
+ return 32000000 ;
204
+ #endif
215
205
default :
216
206
return 0 ;
217
207
}
0 commit comments