30
30
#include "py/runtime.h"
31
31
32
32
#include "shared-bindings/microcontroller/__init__.h"
33
+ #include "shared-bindings/microcontroller/Pin.h"
33
34
34
- #define NO_PIN 0xff
35
+ #include "peripherals/broadcom/cpu.h"
36
+ #include "peripherals/broadcom/vcmailbox.h"
35
37
36
- // One second
37
- #define BUS_TIMEOUT_US 1000000
38
+ #define NUM_I2C (2)
38
39
39
- STATIC bool never_reset_i2c [2 ];
40
- // STATIC i2c_inst_t *i2c[2] = {i2c0, i2c1};
40
+ STATIC bool never_reset_i2c [NUM_I2C ];
41
+ STATIC bool in_use_i2c [NUM_I2C ];
42
+ STATIC BSC0_Type * i2c [2 ] = {BSC0 , BSC1 };
41
43
42
44
void reset_i2c (void ) {
43
45
for (size_t i = 0 ; i < 2 ; i ++ ) {
44
46
if (never_reset_i2c [i ]) {
45
47
continue ;
46
48
}
47
-
49
+ in_use_i2c [ i ] = false;
48
50
}
49
51
}
50
52
51
53
void common_hal_busio_i2c_construct (busio_i2c_obj_t * self ,
52
54
const mcu_pin_obj_t * scl , const mcu_pin_obj_t * sda , uint32_t frequency , uint32_t timeout ) {
55
+ size_t instance_index = NUM_I2C ;
56
+ if ((scl == & pin_GPIO1 || scl == & pin_GPIO29 || scl == & pin_GPIO45 ) &&
57
+ (sda == & pin_GPIO0 || sda == & pin_GPIO28 || sda == & pin_GPIO44 )) {
58
+ instance_index = 0 ;
59
+ } else if ((scl == & pin_GPIO44 || scl == & pin_GPIO3 ) &&
60
+ (sda == & pin_GPIO43 || sda == & pin_GPIO2 )) {
61
+ instance_index = 1 ;
62
+ }
63
+ if (instance_index == NUM_I2C ) {
64
+ mp_raise_ValueError (translate ("Invalid pins" ));
65
+ }
66
+ in_use_i2c [instance_index ] = true;
67
+ self -> index = instance_index ;
68
+ self -> peripheral = i2c [self -> index ];
69
+ self -> sda_pin = sda ;
70
+ self -> scl_pin = scl ;
71
+
72
+ uint32_t source_clock = vcmailbox_get_clock_rate_measured (VCMAILBOX_CLOCK_CORE );
73
+ uint16_t clock_divider = source_clock / frequency ;
74
+ self -> peripheral -> DIV_b .CDIV = clock_divider ;
75
+
76
+ gpio_set_function (sda -> number , GPIO_GPFSEL0_FSEL2_SDA1 );
77
+ gpio_set_function (scl -> number , GPIO_GPFSEL0_FSEL3_SCL1 );
53
78
}
54
79
55
80
bool common_hal_busio_i2c_deinited (busio_i2c_obj_t * self ) {
56
- return self -> sda_pin == NO_PIN ;
81
+ return self -> sda_pin == NULL ;
57
82
}
58
83
59
84
void common_hal_busio_i2c_deinit (busio_i2c_obj_t * self ) {
60
85
if (common_hal_busio_i2c_deinited (self )) {
61
86
return ;
62
87
}
63
- // never_reset_i2c[i2c_hw_index( self->peripheral) ] = false;
88
+ never_reset_i2c [self -> index ] = false;
64
89
65
- reset_pin_number (self -> sda_pin );
66
- reset_pin_number (self -> scl_pin );
67
- self -> sda_pin = NO_PIN ;
68
- self -> scl_pin = NO_PIN ;
90
+ common_hal_reset_pin (self -> sda_pin );
91
+ common_hal_reset_pin (self -> scl_pin );
92
+ self -> sda_pin = NULL ;
93
+ self -> scl_pin = NULL ;
69
94
}
70
95
71
96
bool common_hal_busio_i2c_probe (busio_i2c_obj_t * self , uint8_t addr ) {
72
- return common_hal_busio_i2c_write (self , addr , NULL , 0 , true) == 0 ;
97
+ uint8_t result = common_hal_busio_i2c_write (self , addr , NULL , 0 , true);
98
+ // mp_printf(&mp_plat_print, "result %d %d\n", addr, result);
99
+ return result == 0 ;
73
100
}
74
101
75
102
bool common_hal_busio_i2c_try_lock (busio_i2c_obj_t * self ) {
@@ -89,20 +116,111 @@ void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
89
116
self -> has_lock = false;
90
117
}
91
118
119
+ // Discussion of I2C implementation is here: https://github.com/raspberrypi/linux/issues/254
120
+
92
121
uint8_t common_hal_busio_i2c_write (busio_i2c_obj_t * self , uint16_t addr ,
93
122
const uint8_t * data , size_t len , bool transmit_stop_bit ) {
123
+ COMPLETE_MEMORY_READS ;
124
+ self -> peripheral -> S_b .DONE = true;
125
+ self -> peripheral -> A_b .ADDR = addr ;
126
+ size_t loop_len = len ;
127
+ // Prevent the stop bit by transmitting everything but the last byte. Doing
128
+ // so is left up to the subsequent read.
129
+ if (!transmit_stop_bit ) {
130
+ loop_len -= 1 ;
131
+ }
132
+ self -> peripheral -> DLEN_b .DLEN = len ;
133
+ self -> peripheral -> C = BSC0_C_ST_Msk | BSC0_C_I2CEN_Msk ;
134
+ // Wait for the transaction to start.
135
+ while (self -> peripheral -> S_b .TA == 0 ) {
136
+ RUN_BACKGROUND_TASKS ;
137
+ }
138
+ for (size_t i = 0 ; i < loop_len ; i ++ ) {
139
+ if (self -> peripheral -> S_b .ERR ) {
140
+ break ;
141
+ }
142
+ self -> peripheral -> FIFO_b .DATA = data [i ];
143
+ // Wait for the FIFO to empty enough that we can write more data.
144
+ while (self -> peripheral -> S_b .TXE == 0 ) {
145
+ RUN_BACKGROUND_TASKS ;
146
+ }
147
+ }
148
+ // Wait for the FIFO to empty completely, not DONE, because we may not complete the
149
+ // transaction with a write.
150
+ while (self -> peripheral -> S_b .ERR == 0 &&
151
+ ((!transmit_stop_bit && self -> peripheral -> S_b .TXE == 0 ) ||
152
+ (transmit_stop_bit && self -> peripheral -> S_b .TA == 1 ))) {
153
+ RUN_BACKGROUND_TASKS ;
154
+ }
155
+ self -> finish_write = false;
156
+ if (self -> peripheral -> S_b .ERR ) {
157
+ // Wait for the transfer to finish.
158
+ while (self -> peripheral -> S_b .TA == 1 ) {
159
+ RUN_BACKGROUND_TASKS ;
160
+ }
161
+ // Clear the flag by writing it and wait for it to clear.
162
+ self -> peripheral -> S_b .ERR = true;
163
+ while (self -> peripheral -> S_b .ERR == 1 ) {
164
+ RUN_BACKGROUND_TASKS ;
165
+ }
166
+ return MP_ENODEV ;
167
+ }
94
168
95
- return MP_ENODEV ;
169
+ if (loop_len < len ) {
170
+ self -> finish_write = true;
171
+ self -> last_write_data = data [len - 1 ];
172
+ }
173
+ return 0 ;
96
174
}
97
175
98
176
uint8_t common_hal_busio_i2c_read (busio_i2c_obj_t * self , uint16_t addr ,
99
177
uint8_t * data , size_t len ) {
100
- return MP_ENODEV ;
178
+ COMPLETE_MEMORY_READS ;
179
+ self -> peripheral -> A_b .ADDR = addr ;
180
+ if (self -> finish_write ) {
181
+ self -> finish_write = false;
182
+ if (self -> peripheral -> S_b .ERR == 1 ) {
183
+ return MP_ENODEV ;
184
+ }
185
+ self -> peripheral -> FIFO_b .DATA = self -> last_write_data ;
186
+ } else {
187
+ self -> peripheral -> S_b .DONE = true;
188
+ }
189
+ self -> peripheral -> DLEN_b .DLEN = len ;
190
+ self -> peripheral -> C = BSC0_C_READ_Msk | BSC0_C_ST_Msk | BSC0_C_I2CEN_Msk ;
191
+ // Wait for the transaction to start.
192
+ while (self -> peripheral -> S_b .TA == 0 ) {
193
+ RUN_BACKGROUND_TASKS ;
194
+ }
195
+ for (size_t i = 0 ; i < len ; i ++ ) {
196
+ if (self -> peripheral -> S_b .ERR ) {
197
+ break ;
198
+ }
199
+ // Wait for the FIFO to have enough data that we can read it. RXR is low
200
+ // once the transaction is done so we check the done bit too.
201
+ while (!self -> peripheral -> S_b .RXR && !self -> peripheral -> S_b .DONE ) {
202
+ RUN_BACKGROUND_TASKS ;
203
+ }
204
+ data [i ] = self -> peripheral -> FIFO_b .DATA ;
205
+ }
206
+ // Wait for the transaction to finish.
207
+ while (!self -> peripheral -> S_b .DONE && !self -> peripheral -> S_b .ERR ) {
208
+ RUN_BACKGROUND_TASKS ;
209
+ }
210
+ if (self -> peripheral -> S_b .ERR ) {
211
+ self -> peripheral -> S_b .ERR = true;
212
+ while (self -> peripheral -> S_b .ERR == 1 ) {
213
+ RUN_BACKGROUND_TASKS ;
214
+ }
215
+ return MP_ENODEV ;
216
+ }
217
+
218
+ return 0 ;
101
219
}
102
220
103
221
void common_hal_busio_i2c_never_reset (busio_i2c_obj_t * self ) {
104
- // never_reset_i2c[i2c_hw_index( self->peripheral) ] = true;
222
+ never_reset_i2c [self -> index ] = true;
105
223
106
- never_reset_pin_number (self -> scl_pin );
107
- never_reset_pin_number (self -> sda_pin );
224
+ common_hal_never_reset_pin (self -> scl_pin );
225
+ common_hal_never_reset_pin (self -> sda_pin );
108
226
}
0 commit comments