3434#include "nrfx_twim.h"
3535#include "nrf_gpio.h"
3636
37+ #include "nrfx_spim.h"
38+ #include "nrf_gpio.h"
39+
40+ STATIC twim_peripheral_t twim_peripherals [] = {
41+ #if NRFX_CHECK (NRFX_TWIM0_ENABLED )
42+ // SPIM0 and TWIM0 share an address.
43+ { .twim = NRFX_TWIM_INSTANCE (0 ),
44+ .in_use = false,
45+ .max_xfer_size = TWIM0_EASYDMA_MAXCNT_SIZE ,
46+ },
47+ #endif
48+ #if NRFX_CHECK (NRFX_TWIM1_ENABLED )
49+ // SPIM1 and TWIM1 share an address.
50+ { .twim = NRFX_TWIM_INSTANCE (1 ),
51+ .in_use = false,
52+ .max_xfer_size = TWIM1_EASYDMA_MAXCNT_SIZE ,
53+ },
54+ #endif
55+ };
56+
3757#define INST_NO 0
38- #define MAX_XFER_SIZE ((1U << NRFX_CONCAT_3(TWIM, INST_NO, _EASYDMA_MAXCNT_SIZE)) - 1)
3958
4059static uint8_t twi_error_to_mp (const nrfx_err_t err ) {
4160 switch (err ) {
@@ -54,11 +73,23 @@ static uint8_t twi_error_to_mp(const nrfx_err_t err) {
5473}
5574
5675void common_hal_busio_i2c_construct (busio_i2c_obj_t * self , const mcu_pin_obj_t * scl , const mcu_pin_obj_t * sda , uint32_t frequency , uint32_t timeout ) {
57- if (scl -> number == sda -> number )
76+ if (scl -> number == sda -> number ) {
5877 mp_raise_ValueError (translate ("Invalid pins" ));
78+ }
79+
80+ // Find a free instance.
81+ self -> twim_peripheral = NULL ;
82+ for (size_t i = 0 ; i < MP_ARRAY_SIZE (twim_peripherals ); i ++ ) {
83+ if (!twim_peripherals [i ].in_use ) {
84+ self -> twim_peripheral = & twim_peripherals [i ];
85+ self -> twim_peripheral -> in_use = true;
86+ break ;
87+ }
88+ }
5989
60- const nrfx_twim_t instance = NRFX_TWIM_INSTANCE (INST_NO );
61- self -> twim = instance ;
90+ if (self -> twim_peripheral == NULL ) {
91+ mp_raise_ValueError (translate ("All I2C peripherals are in use" ));
92+ }
6293
6394 nrfx_twim_config_t config = NRFX_TWIM_DEFAULT_CONFIG ;
6495 config .scl = scl -> number ;
@@ -76,12 +107,12 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *
76107 claim_pin (sda );
77108 claim_pin (scl );
78109
79- nrfx_err_t err = nrfx_twim_init (& self -> twim , & config , NULL , NULL );
110+ nrfx_err_t err = nrfx_twim_init (& self -> twim_peripheral -> twim , & config , NULL , NULL );
80111
81112 // A soft reset doesn't uninit the driver so we might end up with a invalid state
82113 if (err == NRFX_ERROR_INVALID_STATE ) {
83- nrfx_twim_uninit (& self -> twim );
84- err = nrfx_twim_init (& self -> twim , & config , NULL , NULL );
114+ nrfx_twim_uninit (& self -> twim_peripheral -> twim );
115+ err = nrfx_twim_init (& self -> twim_peripheral -> twim , & config , NULL , NULL );
85116 }
86117
87118 if (err != NRFX_SUCCESS ) {
@@ -99,20 +130,22 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) {
99130 if (common_hal_busio_i2c_deinited (self ))
100131 return ;
101132
102- nrfx_twim_uninit (& self -> twim );
133+ nrfx_twim_uninit (& self -> twim_peripheral -> twim );
103134
104135 reset_pin_number (self -> sda_pin_number );
105136 reset_pin_number (self -> scl_pin_number );
106137 self -> sda_pin_number = NO_PIN ;
107138 self -> scl_pin_number = NO_PIN ;
139+
140+ self -> twim_peripheral -> in_use = false;
108141}
109142
110143// nrfx_twim_tx doesn't support 0-length data so we fall back to the hal API
111144bool common_hal_busio_i2c_probe (busio_i2c_obj_t * self , uint8_t addr ) {
112- NRF_TWIM_Type * reg = self -> twim .p_twim ;
145+ NRF_TWIM_Type * reg = self -> twim_peripheral -> twim .p_twim ;
113146 bool found = true;
114147
115- nrfx_twim_enable (& self -> twim );
148+ nrfx_twim_enable (& self -> twim_peripheral -> twim );
116149
117150 nrf_twim_address_set (reg , addr );
118151 nrf_twim_tx_buffer_set (reg , NULL , 0 );
@@ -135,19 +168,19 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
135168 found = false;
136169 }
137170
138- nrfx_twim_disable (& self -> twim );
171+ nrfx_twim_disable (& self -> twim_peripheral -> twim );
139172
140173 return found ;
141174}
142175
143176bool common_hal_busio_i2c_try_lock (busio_i2c_obj_t * self ) {
144177 bool grabbed_lock = false;
145- // CRITICAL_SECTION_ENTER()
146- if (!self -> has_lock ) {
147- grabbed_lock = true;
148- self -> has_lock = true;
149- }
150- // CRITICAL_SECTION_LEAVE ();
178+ // NRFX_CRITICAL_SECTION_ENTER();
179+ if (!self -> has_lock ) {
180+ grabbed_lock = true;
181+ self -> has_lock = true;
182+ }
183+ // NRFX_CRITICAL_SECTION_EXIT ();
151184 return grabbed_lock ;
152185}
153186
@@ -163,22 +196,23 @@ uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const u
163196 if (len == 0 )
164197 return common_hal_busio_i2c_probe (self , addr ) ? 0 : MP_ENODEV ;
165198
166- const uint32_t parts = len / MAX_XFER_SIZE ;
167- const uint32_t remainder = len % MAX_XFER_SIZE ;
199+ const uint32_t max_xfer_size = self -> twim_peripheral -> max_xfer_size ;
200+ const uint32_t parts = len / max_xfer_size ;
201+ const uint32_t remainder = len % max_xfer_size ;
168202 nrfx_err_t err = NRFX_SUCCESS ;
169203
170- nrfx_twim_enable (& self -> twim );
204+ nrfx_twim_enable (& self -> twim_peripheral -> twim );
171205
172206 for (uint32_t i = 0 ; i < parts ; ++ i ) {
173- err = nrfx_twim_tx (& self -> twim , addr , data + i * MAX_XFER_SIZE , MAX_XFER_SIZE , !stopBit );
207+ err = nrfx_twim_tx (& self -> twim_peripheral -> twim , addr , data + i * max_xfer_size , max_xfer_size , !stopBit );
174208 if (err != NRFX_SUCCESS )
175209 break ;
176210 }
177211
178212 if ((remainder > 0 ) && (err == NRFX_SUCCESS ))
179- err = nrfx_twim_tx (& self -> twim , addr , data + parts * MAX_XFER_SIZE , remainder , !stopBit );
213+ err = nrfx_twim_tx (& self -> twim_peripheral -> twim , addr , data + parts * max_xfer_size , remainder , !stopBit );
180214
181- nrfx_twim_disable (& self -> twim );
215+ nrfx_twim_disable (& self -> twim_peripheral -> twim );
182216
183217 return twi_error_to_mp (err );
184218}
@@ -187,22 +221,23 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t
187221 if (len == 0 )
188222 return 0 ;
189223
190- const uint32_t parts = len / MAX_XFER_SIZE ;
191- const uint32_t remainder = len % MAX_XFER_SIZE ;
224+ const uint32_t max_xfer_size = self -> twim_peripheral -> max_xfer_size ;
225+ const uint32_t parts = len / max_xfer_size ;
226+ const uint32_t remainder = len % max_xfer_size ;
192227 nrfx_err_t err = NRFX_SUCCESS ;
193228
194- nrfx_twim_enable (& self -> twim );
229+ nrfx_twim_enable (& self -> twim_peripheral -> twim );
195230
196231 for (uint32_t i = 0 ; i < parts ; ++ i ) {
197- err = nrfx_twim_rx (& self -> twim , addr , data + i * MAX_XFER_SIZE , MAX_XFER_SIZE );
232+ err = nrfx_twim_rx (& self -> twim_peripheral -> twim , addr , data + i * max_xfer_size , max_xfer_size );
198233 if (err != NRFX_SUCCESS )
199234 break ;
200235 }
201236
202237 if ((remainder > 0 ) && (err == NRFX_SUCCESS ))
203- err = nrfx_twim_rx (& self -> twim , addr , data + parts * MAX_XFER_SIZE , remainder );
238+ err = nrfx_twim_rx (& self -> twim_peripheral -> twim , addr , data + parts * max_xfer_size , remainder );
204239
205- nrfx_twim_disable (& self -> twim );
240+ nrfx_twim_disable (& self -> twim_peripheral -> twim );
206241
207242 return twi_error_to_mp (err );
208243}
0 commit comments