5555
5656#define nrfx_twi_xfer_desc_t nrfx_twim_xfer_desc_t
5757
58+ #define nrfx_twi_evt_handler_t nrfx_twim_evt_handler_t
59+ #define nrfx_twi_evt_t nrfx_twim_evt_t
60+ #define nrfx_twi_evt_type_t nrfx_twim_evt_type_t
61+
5862#define NRFX_TWI_XFER_DESC_RX NRFX_TWIM_XFER_DESC_RX
5963#define NRFX_TWI_XFER_DESC_TX NRFX_TWIM_XFER_DESC_TX
6064
6165#define NRFX_TWI_INSTANCE NRFX_TWIM_INSTANCE
6266
67+ #define NRFX_TWI_EVT_DONE NRFX_TWIM_EVT_DONE
68+ #define NRFX_TWI_EVT_ADDRESS_NACK NRFX_TWIM_EVT_ADDRESS_NACK
69+ #define NRFX_TWI_EVT_DATA_NACK NRFX_TWIM_EVT_DATA_NACK
70+ #define NRFX_TWI_EVT_BUS_ERROR NRFX_TWIM_EVT_BUS_ERROR
71+
6372#define NRF_TWI_FREQ_100K NRF_TWIM_FREQ_100K
6473#define NRF_TWI_FREQ_250K NRF_TWIM_FREQ_250K
6574#define NRF_TWI_FREQ_400K NRF_TWIM_FREQ_400K
6978typedef struct _machine_hard_i2c_obj_t {
7079 mp_obj_base_t base ;
7180 nrfx_twi_t p_twi ; // Driver instance
81+ uint32_t timeout ;
82+ volatile bool xfer_done ;
83+ volatile nrfx_twi_evt_type_t xfer_evt ;
7284} machine_hard_i2c_obj_t ;
7385
74- static const machine_hard_i2c_obj_t machine_hard_i2c_obj [] = {
86+ static machine_hard_i2c_obj_t machine_hard_i2c_obj [] = {
7587 {{& machine_i2c_type }, .p_twi = NRFX_TWI_INSTANCE (0 )},
7688 {{& machine_i2c_type }, .p_twi = NRFX_TWI_INSTANCE (1 )},
7789};
7890
7991void i2c_init0 (void ) {
8092}
8193
94+ static void twi_event_handler (nrfx_twi_evt_t const * p_event , void * p_context ) {
95+ machine_hard_i2c_obj_t * self = (machine_hard_i2c_obj_t * )p_context ;
96+ self -> xfer_evt = p_event -> type ;
97+ self -> xfer_done = true;
98+ }
99+
82100static int i2c_find (mp_obj_t id ) {
83101 // given an integer id
84102 int i2c_id = mp_obj_get_int (id );
@@ -90,7 +108,7 @@ static int i2c_find(mp_obj_t id) {
90108
91109static void machine_hard_i2c_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
92110 machine_hard_i2c_obj_t * self = self_in ;
93- mp_printf (print , "I2C(%u)" , self -> p_twi .drv_inst_idx );
111+ mp_printf (print , "I2C(%u, timeout=%u )" , self -> p_twi .drv_inst_idx , self -> timeout );
94112}
95113
96114/******************************************************************************/
@@ -99,12 +117,13 @@ static void machine_hard_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp
99117mp_obj_t machine_hard_i2c_make_new (const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * all_args ) {
100118 MP_MACHINE_I2C_CHECK_FOR_LEGACY_SOFTI2C_CONSTRUCTION (n_args , n_kw , all_args );
101119
102- enum { ARG_id , ARG_scl , ARG_sda , ARG_freq };
120+ enum { ARG_id , ARG_scl , ARG_sda , ARG_freq , ARG_timeout };
103121 static const mp_arg_t allowed_args [] = {
104122 { MP_QSTR_id , MP_ARG_REQUIRED | MP_ARG_OBJ },
105123 { MP_QSTR_scl , MP_ARG_REQUIRED | MP_ARG_OBJ },
106124 { MP_QSTR_sda , MP_ARG_REQUIRED | MP_ARG_OBJ },
107125 { MP_QSTR_freq , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = -1 } },
126+ { MP_QSTR_timeout , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 50000 } },
108127 };
109128
110129 // parse args
@@ -113,7 +132,9 @@ mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz
113132
114133 // get static peripheral object
115134 int i2c_id = i2c_find (args [ARG_id ].u_obj );
116- const machine_hard_i2c_obj_t * self = & machine_hard_i2c_obj [i2c_id ];
135+ machine_hard_i2c_obj_t * self = & machine_hard_i2c_obj [i2c_id ];
136+
137+ self -> timeout = args [ARG_timeout ].u_int ;
117138
118139 nrfx_twi_config_t config ;
119140 #if NRFX_TWI_ENABLED
@@ -139,8 +160,8 @@ mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz
139160 // First reset the TWI
140161 nrfx_twi_uninit (& self -> p_twi );
141162
142- // Set context to this object.
143- nrfx_twi_init (& self -> p_twi , & config , NULL , (void * )self );
163+ // Set context to this object, use non-blocking mode with event handler .
164+ nrfx_twi_init (& self -> p_twi , & config , twi_event_handler , (void * )self );
144165
145166 return MP_OBJ_FROM_PTR (self );
146167}
@@ -150,6 +171,9 @@ int machine_hard_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, size
150171
151172 nrfx_twi_enable (& self -> p_twi );
152173
174+ self -> xfer_done = false;
175+ self -> xfer_evt = NRFX_TWI_EVT_DONE ;
176+
153177 nrfx_err_t err_code ;
154178 int transfer_ret = 0 ;
155179 if (flags & MP_MACHINE_I2C_FLAG_READ ) {
@@ -162,6 +186,7 @@ int machine_hard_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, size
162186 }
163187
164188 if (err_code != NRFX_SUCCESS ) {
189+ nrfx_twi_disable (& self -> p_twi );
165190 if (err_code == NRFX_ERROR_DRV_TWI_ERR_ANACK ) {
166191 return - MP_ENODEV ;
167192 } else if (err_code == NRFX_ERROR_DRV_TWI_ERR_DNACK ) {
@@ -170,8 +195,27 @@ int machine_hard_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, size
170195 return - MP_ETIMEDOUT ;
171196 }
172197
198+ // Poll for transfer completion with timeout.
199+ mp_uint_t start = mp_hal_ticks_us ();
200+ while (!self -> xfer_done ) {
201+ if (self -> timeout > 0 && (mp_hal_ticks_us () - start ) >= self -> timeout ) {
202+ nrfx_twi_disable (& self -> p_twi );
203+ nrfx_twi_enable (& self -> p_twi );
204+ return - MP_ETIMEDOUT ;
205+ }
206+ MICROPY_EVENT_POLL_HOOK ;
207+ }
208+
173209 nrfx_twi_disable (& self -> p_twi );
174210
211+ if (self -> xfer_evt == NRFX_TWI_EVT_ADDRESS_NACK ) {
212+ return - MP_ENODEV ;
213+ } else if (self -> xfer_evt == NRFX_TWI_EVT_DATA_NACK ) {
214+ return - MP_EIO ;
215+ } else if (self -> xfer_evt != NRFX_TWI_EVT_DONE ) {
216+ return - MP_EIO ;
217+ }
218+
175219 return transfer_ret ;
176220}
177221
0 commit comments