SHOW:
|
|
- or go back to the newest paste.
| 1 | diff --git a/libmaple/i2c.c b/libmaple/i2c.c | |
| 2 | - | index 9c93d3f..2a98b79 100644 |
| 2 | + | index 9c93d3f..4902ec3 100644 |
| 3 | --- a/libmaple/i2c.c | |
| 4 | +++ b/libmaple/i2c.c | |
| 5 | @@ -154,6 +154,7 @@ void i2c_bus_reset(const i2c_dev *dev) {
| |
| 6 | void i2c_init(i2c_dev *dev) {
| |
| 7 | rcc_reset_dev(dev->clk_id); | |
| 8 | rcc_clk_enable(dev->clk_id); | |
| 9 | + _i2c_irq_priority_fixup(dev); | |
| 10 | } | |
| 11 | ||
| 12 | /* Hack for deprecated bit of STM32F1 functionality */ | |
| 13 | - | @@ -198,12 +199,26 @@ void i2c_master_enable(i2c_dev *dev, uint32 flags) {
|
| 13 | + | @@ -198,12 +199,30 @@ void i2c_master_enable(i2c_dev *dev, uint32 flags) {
|
| 14 | nvic_irq_enable(dev->er_nvic_line); | |
| 15 | i2c_enable_irq(dev, I2C_IRQ_EVENT | I2C_IRQ_BUFFER | I2C_IRQ_ERROR); | |
| 16 | ||
| 17 | + /* Configure the slave unit */ | |
| 18 | + if (flags & I2C_SLAVE_DUAL_ADDRESS) {
| |
| 19 | + i2c_slave_dual_address_enable(dev); | |
| 20 | + } | |
| 21 | + | |
| 22 | + if (flags & I2C_SLAVE_GENERAL_CALL) {
| |
| 23 | + i2c_slave_general_call_enable(dev); | |
| 24 | + } | |
| 25 | + | |
| 26 | + /* store all of the flags */ | |
| 27 | + dev->config_flags = flags; | |
| 28 | + | |
| 29 | /* Make it go! */ | |
| 30 | i2c_peripheral_enable(dev); | |
| 31 | + i2c_enable_ack(dev); | |
| 32 | ||
| 33 | dev->state = I2C_STATE_IDLE; | |
| 34 | } | |
| 35 | ||
| 36 | +void i2c_slave_enable(i2c_dev *dev, uint32 flags) {
| |
| 37 | + i2c_disable(dev); | |
| 38 | + i2c_master_enable(dev, dev->config_flags | flags); | |
| 39 | +} | |
| 40 | - | @@ -303,149 +318,297 @@ void _i2c_irq_handler(i2c_dev *dev) {
|
| 40 | + | |
| 41 | /** | |
| 42 | * @brief Process an i2c transaction. | |
| 43 | * | |
| 44 | @@ -303,150 +322,296 @@ void _i2c_irq_handler(i2c_dev *dev) {
| |
| 45 | */ | |
| 46 | dev->timestamp = systick_uptime(); | |
| 47 | ||
| 48 | - /* | |
| 49 | - * EV5: Start condition sent | |
| 50 | + /* Add Slave support | |
| 51 | + * Barry Carter 2012 | |
| 52 | + * [email protected] | |
| 53 | */ | |
| 54 | - if (sr1 & I2C_SR1_SB) {
| |
| 55 | - msg->xferred = 0; | |
| 56 | - i2c_enable_irq(dev, I2C_IRQ_BUFFER); | |
| 57 | - | |
| 58 | - /* | |
| 59 | - * Master receiver | |
| 60 | - */ | |
| 61 | - if (read) {
| |
| 62 | - i2c_enable_ack(dev); | |
| 63 | + | |
| 64 | + /* Check to see if MSL master slave bit is set */ | |
| 65 | + if ((sr2 & I2C_SR2_MSL) != I2C_SR2_MSL) { /* 0 = slave mode 1 = master */
| |
| 66 | + | |
| 67 | + dev->state = I2C_STATE_BUSY; | |
| 68 | + | |
| 69 | + /* Check for address match */ | |
| 70 | + if (sr1 & I2C_SR1_ADDR) {
| |
| 71 | + /* Find out which address was matched */ | |
| 72 | + /* Check the general call address first */ | |
| 73 | + if (sr2 & I2C_SR2_GENCALL) {
| |
| 74 | + dev->i2c_slave_msg->addr = 0; | |
| 75 | + } | |
| 76 | + /* We matched the secondary address */ | |
| 77 | + else if (sr2 & I2C_SR2_DUALF) {
| |
| 78 | + dev->i2c_slave_msg->addr = dev->regs->OAR2 & 0xFE; | |
| 79 | + } | |
| 80 | + /* We matched the primary address */ | |
| 81 | + else if ((sr2 & I2C_SR2_DUALF) != I2C_SR2_DUALF) {
| |
| 82 | + dev->i2c_slave_msg->addr = dev->regs->OAR1 & 0xFE; | |
| 83 | + } | |
| 84 | + /* Shouldn't get here */ | |
| 85 | + else {
| |
| 86 | + dev->i2c_slave_msg->addr = -1; /* uh oh */ | |
| 87 | + } | |
| 88 | + | |
| 89 | + /* if we have buffered io */ | |
| 90 | + if ((dev->config_flags & I2C_SLAVE_USE_RX_BUFFER) || | |
| 91 | + (dev->config_flags & I2C_SLAVE_USE_TX_BUFFER)) {
| |
| 92 | + | |
| 93 | + /* if receiving then this would be a repeated start | |
| 94 | + * | |
| 95 | + *if we have some bytes already | |
| 96 | + */ | |
| 97 | + if (((sr1 & I2C_SR1_TXE) != I2C_SR1_TXE) && | |
| 98 | + (dev->i2c_slave_msg->xferred > 0) && | |
| 99 | + (dev->config_flags & I2C_SLAVE_USE_RX_BUFFER)) {
| |
| 100 | + /* Call the callback with the contents of the data */ | |
| 101 | + if (dev->i2c_slave_recv_callback != NULL) {
| |
| 102 | + (*(dev->i2c_slave_recv_callback))(dev->i2c_slave_msg); | |
| 103 | + } | |
| 104 | + } | |
| 105 | + | |
| 106 | + /* Reset the message back to defaults. | |
| 107 | + * We are starting a new message | |
| 108 | + */ | |
| 109 | + dev->i2c_slave_msg->flags = 0; | |
| 110 | + dev->i2c_slave_msg->length = 0; | |
| 111 | + dev->i2c_slave_msg->xferred = 0; | |
| 112 | + dev->msgs_left = 0; | |
| 113 | + dev->timestamp = systick_uptime(); | |
| 114 | + | |
| 115 | + /* We have been addressed with SLA+R so | |
| 116 | + * the master wants us to transmit | |
| 117 | + */ | |
| 118 | + if ((sr1 & I2C_SR1_TXE) && | |
| 119 | + (dev->config_flags & I2C_SLAVE_USE_TX_BUFFER)) {
| |
| 120 | + /* Call the transmit callback so it can populate the msg | |
| 121 | + * data with the bytes to go | |
| 122 | + */ | |
| 123 | + if (dev->i2c_slave_transmit_callback != NULL) {
| |
| 124 | + (*(dev->i2c_slave_transmit_callback))(dev->i2c_slave_msg); | |
| 125 | + } | |
| 126 | + } | |
| 127 | + } | |
| 128 | + | |
| 129 | + sr1 = sr2 = 0; | |
| 130 | + } | |
| 131 | + | |
| 132 | + /* EV3: Master requesting data from slave. Transmit a byte*/ | |
| 133 | + if (sr1 & I2C_SR1_TXE) {
| |
| 134 | + if (dev->config_flags & I2C_SLAVE_USE_TX_BUFFER) {
| |
| 135 | + if (dev->i2c_slave_msg->xferred >= dev->i2c_slave_msg->length) {
| |
| 136 | + /* End of the transmit buffer? If so we NACK */ | |
| 137 | + i2c_disable_ack(dev); | |
| 138 | + /* We have to either issue a STOP or write something here. | |
| 139 | + * STOP here seems to screw up some masters, | |
| 140 | + * For now padding with 0 | |
| 141 | + */ | |
| 142 | + i2c_write(dev, 0); | |
| 143 | + /*i2c_stop_condition(dev); // This is causing bus lockups way more than it should !? Seems some I2C master devices freak out here*/ | |
| 144 | + } | |
| 145 | + else | |
| 146 | + {
| |
| 147 | + /* NACk the last byte */ | |
| 148 | + if (dev->i2c_slave_msg->xferred == dev->i2c_slave_msg->length-1) {
| |
| 149 | + i2c_disable_ack(dev); | |
| 150 | + } | |
| 151 | + else {
| |
| 152 | + i2c_enable_ack(dev); | |
| 153 | + } | |
| 154 | + i2c_write(dev, dev->i2c_slave_msg->data[dev->i2c_slave_msg->xferred++]); | |
| 155 | + } | |
| 156 | + } | |
| 157 | + else | |
| 158 | + {
| |
| 159 | + /* Call the callback to get the data we need. | |
| 160 | + * The callback is expected to write using i2c_write(...) | |
| 161 | + * If the slave is going to terminate the transfer, this function should | |
| 162 | + * also do a NACK on the last byte! | |
| 163 | + */ | |
| 164 | + if (dev->i2c_slave_transmit_callback != NULL) (*(dev->i2c_slave_transmit_callback))(dev->i2c_slave_msg); | |
| 165 | + } | |
| 166 | + | |
| 167 | + sr1 = sr2 = 0; | |
| 168 | + } | |
| 169 | + | |
| 170 | + /* EV2: Slave received data from a master. Get from DR */ | |
| 171 | + if (sr1 & I2C_SR1_RXNE) {
| |
| 172 | + if (dev->config_flags & I2C_SLAVE_USE_RX_BUFFER) {
| |
| 173 | + /* Fill the buffer with the contents of the data register */ | |
| 174 | + dev->i2c_slave_msg->data[dev->i2c_slave_msg->xferred++] = dev->regs->DR; | |
| 175 | + dev->i2c_slave_msg->length++; | |
| 176 | + } | |
| 177 | + else {
| |
| 178 | + /* Call the callback with the contents of the data */ | |
| 179 | + dev->i2c_slave_msg->data[0] = dev->regs->DR; | |
| 180 | + if (dev->i2c_slave_recv_callback != NULL) (*(dev->i2c_slave_recv_callback))(dev->i2c_slave_msg); | |
| 181 | + } | |
| 182 | + sr1 = sr2 = 0; | |
| 183 | } | |
| 184 | ||
| 185 | - i2c_send_slave_addr(dev, msg->addr, read); | |
| 186 | - sr1 = sr2 = 0; | |
| 187 | - } | |
| 188 | + /* EV4: Slave has detected a STOP condition on the bus */ | |
| 189 | + if (sr1 & I2C_SR1_STOPF) {
| |
| 190 | + dev->regs->CR1 |= I2C_CR1_PE; | |
| 191 | ||
| 192 | - /* | |
| 193 | - * EV6: Slave address sent | |
| 194 | - */ | |
| 195 | - if (sr1 & I2C_SR1_ADDR) {
| |
| 196 | - /* | |
| 197 | - * Special case event EV6_1 for master receiver. | |
| 198 | - * Generate NACK and restart/stop condition after ADDR | |
| 199 | - * is cleared. | |
| 200 | - */ | |
| 201 | - if (read) {
| |
| 202 | - if (msg->length == 1) {
| |
| 203 | - i2c_disable_ack(dev); | |
| 204 | - if (dev->msgs_left > 1) {
| |
| 205 | - i2c_start_condition(dev); | |
| 206 | - I2C_CRUMB(RX_ADDR_START, 0, 0); | |
| 207 | - } else {
| |
| 208 | - i2c_stop_condition(dev); | |
| 209 | - I2C_CRUMB(RX_ADDR_STOP, 0, 0); | |
| 210 | - } | |
| 211 | - } | |
| 212 | - } else {
| |
| 213 | - /* | |
| 214 | - * Master transmitter: write first byte to fill shift | |
| 215 | - * register. We should get another TXE interrupt | |
| 216 | - * immediately to fill DR again. | |
| 217 | - */ | |
| 218 | - if (msg->length != 1) {
| |
| 219 | - i2c_write(dev, msg->data[msg->xferred++]); | |
| 220 | - } | |
| 221 | - | + (dev->config_flags & I2C_SLAVE_USE_RX_BUFFER)) {
|
| 221 | + | |
| 222 | - sr1 = sr2 = 0; | |
| 223 | - } | |
| 224 | + if ((dev->config_flags & I2C_SLAVE_USE_RX_BUFFER) || | |
| 225 | + (dev->config_flags & I2C_SLAVE_USE_TX_BUFFER)) {
| |
| 226 | ||
| 227 | - /* | |
| 228 | - * EV8: Master transmitter | |
| 229 | - * Transmit buffer empty, but we haven't finished transmitting the last | |
| 230 | - * byte written. | |
| 231 | - */ | |
| 232 | - if ((sr1 & I2C_SR1_TXE) && !(sr1 & I2C_SR1_BTF)) {
| |
| 233 | - I2C_CRUMB(TXE_ONLY, 0, 0); | |
| 234 | - if (dev->msgs_left) {
| |
| 235 | - i2c_write(dev, msg->data[msg->xferred++]); | |
| 236 | - if (msg->xferred == msg->length) {
| |
| 237 | - /* | |
| 238 | - * End of this message. Turn off TXE/RXNE and wait for | |
| 239 | - * BTF to send repeated start or stop condition. | |
| 240 | - */ | |
| 241 | - i2c_disable_irq(dev, I2C_IRQ_BUFFER); | |
| 242 | - dev->msgs_left--; | |
| 243 | - } | |
| 244 | - } else {
| |
| 245 | - /* | |
| 246 | - * This should be impossible... | |
| 247 | - */ | |
| 248 | - ASSERT(0); | |
| 249 | - | + * This is handled in the error IRQ |
| 249 | + | |
| 250 | - sr1 = sr2 = 0; | |
| 251 | - } | |
| 252 | + /* The callback with the data will happen on a NACK of the last data byte. | |
| 253 | + * This is handled in the error IRQ (AF bit) | |
| 254 | + */ | |
| 255 | + } | |
| 256 | ||
| 257 | - /* | |
| 258 | - * EV8_2: Master transmitter | |
| 259 | - * Last byte sent, program repeated start/stop | |
| 260 | - */ | |
| 261 | - if ((sr1 & I2C_SR1_TXE) && (sr1 & I2C_SR1_BTF)) {
| |
| 262 | - I2C_CRUMB(TXE_BTF, 0, 0); | |
| 263 | - if (dev->msgs_left) {
| |
| 264 | - I2C_CRUMB(TEST, 0, 0); | |
| 265 | - /* | |
| 266 | - * Repeated start insanity: We can't disable ITEVTEN or else SB | |
| 267 | - * won't interrupt, but if we don't disable ITEVTEN, BTF will | |
| 268 | - * continually interrupt us. What the fuck ST? | |
| 269 | - */ | |
| 270 | - i2c_start_condition(dev); | |
| 271 | - while (!(dev->regs->SR1 & I2C_SR1_SB)) | |
| 272 | - ; | |
| 273 | - dev->msg++; | |
| 274 | - } else {
| |
| 275 | - i2c_stop_condition(dev); | |
| 276 | - | |
| 277 | - /* | |
| 278 | - * Turn off event interrupts to keep BTF from firing until | |
| 279 | - * the end of the stop condition. Why on earth they didn't | |
| 280 | - * have a start/stop condition request clear BTF is beyond | |
| 281 | - * me. | |
| 282 | - */ | |
| 283 | - i2c_disable_irq(dev, I2C_IRQ_EVENT); | |
| 284 | - I2C_CRUMB(STOP_SENT, 0, 0); | |
| 285 | - dev->state = I2C_STATE_XFER_DONE; | |
| 286 | + sr1 = sr2 = 0; | |
| 287 | + dev->state = I2C_STATE_IDLE; | |
| 288 | } | |
| 289 | - sr1 = sr2 = 0; | |
| 290 | - } | |
| 291 | ||
| 292 | - /* | |
| 293 | - * EV7: Master Receiver | |
| 294 | - */ | |
| 295 | - if (sr1 & I2C_SR1_RXNE) {
| |
| 296 | - I2C_CRUMB(RXNE_ONLY, 0, 0); | |
| 297 | - msg->data[msg->xferred++] = dev->regs->DR; | |
| 298 | - | |
| 299 | - /* | |
| 300 | - * EV7_1: Second to last byte in the reception? Set NACK and generate | |
| 301 | - * stop/restart condition in time for the last byte. We'll get one more | |
| 302 | - * RXNE interrupt before shutting things down. | |
| 303 | - */ | |
| 304 | - if (msg->xferred == (msg->length - 1)) {
| |
| 305 | - i2c_disable_ack(dev); | |
| 306 | - if (dev->msgs_left > 2) {
| |
| 307 | - i2c_start_condition(dev); | |
| 308 | - I2C_CRUMB(RXNE_START_SENT, 0, 0); | |
| 309 | - } else {
| |
| 310 | - i2c_stop_condition(dev); | |
| 311 | - I2C_CRUMB(RXNE_STOP_SENT, 0, 0); | |
| 312 | - } | |
| 313 | - } else if (msg->xferred == msg->length) {
| |
| 314 | - dev->msgs_left--; | |
| 315 | - if (dev->msgs_left == 0) {
| |
| 316 | - /* | |
| 317 | - * We're done. | |
| 318 | - */ | |
| 319 | - I2C_CRUMB(RXNE_DONE, 0, 0); | |
| 320 | - dev->state = I2C_STATE_XFER_DONE; | |
| 321 | - } else {
| |
| 322 | - dev->msg++; | |
| 323 | - } | |
| 324 | - | + /* Process the master code */ |
| 324 | + | |
| 325 | - | + /*if ((sr2 & I2C_SR2_MSL) == I2C_SR2_MSL)*/ { /* 0 = slave mode 1 = master */
|
| 325 | + | |
| 326 | } | |
| 327 | - | + * EV5: Start condition sent |
| 327 | + | |
| 328 | + /* | |
| 329 | - | + if (sr1 & I2C_SR1_SB) {
|
| 329 | + | + * EV5: Start condition sent |
| 330 | - | + msg->xferred = 0; |
| 330 | + | + */ |
| 331 | - | + i2c_enable_irq(dev, I2C_IRQ_BUFFER); |
| 331 | + | + if (sr1 & I2C_SR1_SB) {
|
| 332 | + msg->xferred = 0; | |
| 333 | + i2c_enable_irq(dev, I2C_IRQ_BUFFER); | |
| 334 | - | + * Master receiver |
| 334 | + | |
| 335 | + /* | |
| 336 | - | + if (read) {
|
| 336 | + | + * Master receiver |
| 337 | - | + i2c_enable_ack(dev); |
| 337 | + | |
| 338 | + if (read) {
| |
| 339 | + i2c_enable_ack(dev); | |
| 340 | - | + i2c_send_slave_addr(dev, msg->addr, read); |
| 340 | + | |
| 341 | - | + sr1 = sr2 = 0; |
| 341 | + | |
| 342 | + i2c_send_slave_addr(dev, msg->addr, read); | |
| 343 | + sr1 = sr2 = 0; | |
| 344 | + } | |
| 345 | - | + * EV6: Slave address sent |
| 345 | + | |
| 346 | + /* | |
| 347 | - | + if (sr1 & I2C_SR1_ADDR) {
|
| 347 | + | + * EV6: Slave address sent |
| 348 | + */ | |
| 349 | - | + * Special case event EV6_1 for master receiver. |
| 349 | + | + if (sr1 & I2C_SR1_ADDR) {
|
| 350 | - | + * Generate NACK and restart/stop condition after ADDR |
| 350 | + | |
| 351 | - | + * is cleared. |
| 351 | + | + * Special case event EV6_1 for master receiver. |
| 352 | + * Generate NACK and restart/stop condition after ADDR | |
| 353 | - | + if (read) {
|
| 353 | + | + * is cleared. |
| 354 | - | + if (msg->length == 1) {
|
| 354 | + | |
| 355 | - | + i2c_disable_ack(dev); |
| 355 | + | + if (read) {
|
| 356 | - | + if (dev->msgs_left > 1) {
|
| 356 | + | + if (msg->length == 1) {
|
| 357 | - | + i2c_start_condition(dev); |
| 357 | + | |
| 358 | - | + I2C_CRUMB(RX_ADDR_START, 0, 0); |
| 358 | + | + if (dev->msgs_left > 1) {
|
| 359 | - | + } else {
|
| 359 | + | |
| 360 | - | + i2c_stop_condition(dev); |
| 360 | + | + I2C_CRUMB(RX_ADDR_START, 0, 0); |
| 361 | - | + I2C_CRUMB(RX_ADDR_STOP, 0, 0); |
| 361 | + | |
| 362 | + i2c_stop_condition(dev); | |
| 363 | + I2C_CRUMB(RX_ADDR_STOP, 0, 0); | |
| 364 | + } | |
| 365 | + } | |
| 366 | - | + * Master transmitter: write first byte to fill shift |
| 366 | + | + } else {
|
| 367 | - | + * register. We should get another TXE interrupt |
| 367 | + | |
| 368 | - | + * immediately to fill DR again. |
| 368 | + | + * Master transmitter: write first byte to fill shift |
| 369 | + * register. We should get another TXE interrupt | |
| 370 | - | + if (msg->length != 1) {
|
| 370 | + | + * immediately to fill DR again. |
| 371 | - | + i2c_write(dev, msg->data[msg->xferred++]); |
| 371 | + | |
| 372 | + if (msg->length != 1) {
| |
| 373 | + i2c_write(dev, msg->data[msg->xferred++]); | |
| 374 | - | + sr1 = sr2 = 0; |
| 374 | + | |
| 375 | + } | |
| 376 | + sr1 = sr2 = 0; | |
| 377 | + } | |
| 378 | - | + * EV8: Master transmitter |
| 378 | + | |
| 379 | - | + * Transmit buffer empty, but we haven't finished transmitting the last |
| 379 | + | + /* |
| 380 | - | + * byte written. |
| 380 | + | + * EV8: Master transmitter |
| 381 | + * Transmit buffer empty, but we haven't finished transmitting the last | |
| 382 | - | + if ((sr1 & I2C_SR1_TXE) && !(sr1 & I2C_SR1_BTF)) {
|
| 382 | + | + * byte written. |
| 383 | - | + I2C_CRUMB(TXE_ONLY, 0, 0); |
| 383 | + | + */ |
| 384 | - | + if (dev->msgs_left) {
|
| 384 | + | + if ((sr1 & I2C_SR1_TXE) && !(sr1 & I2C_SR1_BTF)) {
|
| 385 | + I2C_CRUMB(TXE_ONLY, 0, 0); | |
| 386 | - | + if (msg->xferred == msg->length) {
|
| 386 | + | + if (dev->msgs_left) {
|
| 387 | - | + /* |
| 387 | + | + i2c_write(dev, msg->data[msg->xferred++]); |
| 388 | - | + * End of this message. Turn off TXE/RXNE and wait for |
| 388 | + | + if (msg->xferred == msg->length) {
|
| 389 | - | + * BTF to send repeated start or stop condition. |
| 389 | + | |
| 390 | - | + */ |
| 390 | + | + * End of this message. Turn off TXE/RXNE and wait for |
| 391 | - | + i2c_disable_irq(dev, I2C_IRQ_BUFFER); |
| 391 | + | + * BTF to send repeated start or stop condition. |
| 392 | - | + dev->msgs_left--; |
| 392 | + | |
| 393 | + i2c_disable_irq(dev, I2C_IRQ_BUFFER); | |
| 394 | + dev->msgs_left--; | |
| 395 | + } | |
| 396 | - | + * This should be impossible... |
| 396 | + | + } else {
|
| 397 | + /* | |
| 398 | - | + ASSERT(0); |
| 398 | + | + * This should be impossible... |
| 399 | + */ | |
| 400 | - | + sr1 = sr2 = 0; |
| 400 | + | + ASSERT(0); |
| 401 | + } | |
| 402 | + sr1 = sr2 = 0; | |
| 403 | + } | |
| 404 | - | + * EV8_2: Master transmitter |
| 404 | + | |
| 405 | - | + * Last byte sent, program repeated start/stop |
| 405 | + | + /* |
| 406 | + * EV8_2: Master transmitter | |
| 407 | - | + if ((sr1 & I2C_SR1_TXE) && (sr1 & I2C_SR1_BTF)) {
|
| 407 | + | + * Last byte sent, program repeated start/stop |
| 408 | - | + I2C_CRUMB(TXE_BTF, 0, 0); |
| 408 | + | + */ |
| 409 | - | + if (dev->msgs_left) {
|
| 409 | + | + if ((sr1 & I2C_SR1_TXE) && (sr1 & I2C_SR1_BTF)) {
|
| 410 | - | + I2C_CRUMB(TEST, 0, 0); |
| 410 | + | + I2C_CRUMB(TXE_BTF, 0, 0); |
| 411 | + if (dev->msgs_left) {
| |
| 412 | - | + * Repeated start insanity: We can't disable ITEVTEN or else SB |
| 412 | + | + I2C_CRUMB(TEST, 0, 0); |
| 413 | - | + * won't interrupt, but if we don't disable ITEVTEN, BTF will |
| 413 | + | |
| 414 | - | + * continually interrupt us. What the fuck ST? |
| 414 | + | + * Repeated start insanity: We can't disable ITEVTEN or else SB |
| 415 | + * won't interrupt, but if we don't disable ITEVTEN, BTF will | |
| 416 | + * continually interrupt us. What the fuck ST? | |
| 417 | - | + while (!(dev->regs->SR1 & I2C_SR1_SB)) |
| 417 | + | |
| 418 | - | + ; |
| 418 | + | + i2c_start_condition(dev); |
| 419 | + while (!(dev->regs->SR1 & I2C_SR1_SB)) | |
| 420 | + ; | |
| 421 | + dev->msg++; | |
| 422 | + } else {
| |
| 423 | + i2c_stop_condition(dev); | |
| 424 | - | + * Turn off event interrupts to keep BTF from firing until |
| 424 | + | |
| 425 | - | + * the end of the stop condition. Why on earth they didn't |
| 425 | + | |
| 426 | - | + * have a start/stop condition request clear BTF is beyond |
| 426 | + | + * Turn off event interrupts to keep BTF from firing until |
| 427 | - | + * me. |
| 427 | + | + * the end of the stop condition. Why on earth they didn't |
| 428 | + * have a start/stop condition request clear BTF is beyond | |
| 429 | - | + i2c_disable_irq(dev, I2C_IRQ_EVENT); |
| 429 | + | + * me. |
| 430 | - | + I2C_CRUMB(STOP_SENT, 0, 0); |
| 430 | + | |
| 431 | + i2c_disable_irq(dev, I2C_IRQ_EVENT); | |
| 432 | + I2C_CRUMB(STOP_SENT, 0, 0); | |
| 433 | - | + sr1 = sr2 = 0; |
| 433 | + | + dev->state = I2C_STATE_XFER_DONE; |
| 434 | + } | |
| 435 | + sr1 = sr2 = 0; | |
| 436 | + } | |
| 437 | - | + * EV7: Master Receiver |
| 437 | + | |
| 438 | + /* | |
| 439 | - | + if (sr1 & I2C_SR1_RXNE) {
|
| 439 | + | + * EV7: Master Receiver |
| 440 | - | + I2C_CRUMB(RXNE_ONLY, 0, 0); |
| 440 | + | + */ |
| 441 | - | + msg->data[msg->xferred++] = dev->regs->DR; |
| 441 | + | + if (sr1 & I2C_SR1_RXNE) {
|
| 442 | + I2C_CRUMB(RXNE_ONLY, 0, 0); | |
| 443 | + msg->data[msg->xferred++] = dev->regs->DR; | |
| 444 | - | + * EV7_1: Second to last byte in the reception? Set NACK and generate |
| 444 | + | |
| 445 | - | + * stop/restart condition in time for the last byte. We'll get one more |
| 445 | + | |
| 446 | - | + * RXNE interrupt before shutting things down. |
| 446 | + | + * EV7_1: Second to last byte in the reception? Set NACK and generate |
| 447 | + * stop/restart condition in time for the last byte. We'll get one more | |
| 448 | - | + if (msg->xferred == (msg->length - 1)) {
|
| 448 | + | + * RXNE interrupt before shutting things down. |
| 449 | + */ | |
| 450 | - | + if (dev->msgs_left > 2) {
|
| 450 | + | + if (msg->xferred == (msg->length - 1)) {
|
| 451 | + i2c_disable_ack(dev); | |
| 452 | - | + I2C_CRUMB(RXNE_START_SENT, 0, 0); |
| 452 | + | + if (dev->msgs_left > 2) {
|
| 453 | + i2c_start_condition(dev); | |
| 454 | + I2C_CRUMB(RXNE_START_SENT, 0, 0); | |
| 455 | - | + I2C_CRUMB(RXNE_STOP_SENT, 0, 0); |
| 455 | + | |
| 456 | + i2c_stop_condition(dev); | |
| 457 | - | + } else if (msg->xferred == msg->length) {
|
| 457 | + | + I2C_CRUMB(RXNE_STOP_SENT, 0, 0); |
| 458 | + } | |
| 459 | - | + if (dev->msgs_left == 0) {
|
| 459 | + | + } else if (msg->xferred == msg->length) {
|
| 460 | - | + /* |
| 460 | + | + dev->msgs_left--; |
| 461 | - | + * We're done. |
| 461 | + | + if (dev->msgs_left == 0) {
|
| 462 | - | + */ |
| 462 | + | |
| 463 | - | + I2C_CRUMB(RXNE_DONE, 0, 0); |
| 463 | + | + * We're done. |
| 464 | - | + dev->state = I2C_STATE_XFER_DONE; |
| 464 | + | |
| 465 | + I2C_CRUMB(RXNE_DONE, 0, 0); | |
| 466 | - | + dev->msg++; |
| 466 | + | |
| 467 | + } else {
| |
| 468 | + dev->msg++; | |
| 469 | + } | |
| 470 | + } | |
| 471 | + } | |
| 472 | + | |
| 473 | - | @@ -456,10 +619,46 @@ void _i2c_irq_handler(i2c_dev *dev) {
|
| 473 | + | |
| 474 | ||
| 475 | /* | |
| 476 | @@ -456,10 +621,46 @@ void _i2c_irq_handler(i2c_dev *dev) {
| |
| 477 | void _i2c_irq_error_handler(i2c_dev *dev) {
| |
| 478 | I2C_CRUMB(ERROR_ENTRY, dev->regs->SR1, dev->regs->SR2); | |
| 479 | ||
| 480 | - dev->error_flags = dev->regs->SR2 & (I2C_SR1_BERR | | |
| 481 | + dev->error_flags = dev->regs->SR1 & (I2C_SR1_BERR | | |
| 482 | I2C_SR1_ARLO | | |
| 483 | I2C_SR1_AF | | |
| 484 | I2C_SR1_OVR); | |
| 485 | + | |
| 486 | + /* Are we in slave mode? */ | |
| 487 | + if ((dev->regs->SR2 & I2C_SR2_MSL) != I2C_SR2_MSL) {
| |
| 488 | + /* Check to see if the master device did a NAK on the last bit | |
| 489 | + * This is perfectly valid for a master to do this on the bus. | |
| 490 | + * We ignore this. Any further error processing takes us into dead | |
| 491 | + * loop waiting for the stop condition that will never arrive | |
| 492 | + */ | |
| 493 | + if (dev->regs->SR1 & I2C_SR1_AF) {
| |
| 494 | + /* Clear flags */ | |
| 495 | + dev->regs->SR1 = 0; | |
| 496 | + dev->regs->SR2 = 0; | |
| 497 | + /* We need to write something to CR1 to clear the flag. | |
| 498 | + * This isn't really mentioned but seems important */ | |
| 499 | + i2c_enable_ack(dev); | |
| 500 | + dev->state = I2C_STATE_IDLE; | |
| 501 | + | |
| 502 | + if (dev->config_flags & I2C_SLAVE_USE_RX_BUFFER && dev->i2c_slave_msg->xferred > 0) {
| |
| 503 | + /* Call the callback with the contents of the data */ | |
| 504 | + if (dev->i2c_slave_recv_callback != NULL) (*(dev->i2c_slave_recv_callback))(dev->i2c_slave_msg); | |
| 505 | + } | |
| 506 | + return; | |
| 507 | + } | |
| 508 | + /* Catch any other strange errors while in slave mode. | |
| 509 | + * I have seen BERR caused by an over fast master device | |
| 510 | + * as well as several overflows and arbitration failures. | |
| 511 | + * We are going to reset SR flags and carry on at this point which | |
| 512 | + * is not the best thing to do, but stops the bus locking up completely | |
| 513 | + * If we carry on below and send the stop bit, the code spins forever */ | |
| 514 | + /* Clear flags */ | |
| 515 | + dev->regs->SR1 = 0; | |
| 516 | + dev->regs->SR2 = 0; | |
| 517 | + dev->state = I2C_STATE_IDLE; | |
| 518 | + return; | |
| 519 | + } | |
| 520 | + | |
| 521 | - | @@ -507,3 +706,31 @@ static void set_ccr_trise(i2c_dev *dev, uint32 flags) {
|
| 521 | + | |
| 522 | dev->regs->SR1 = 0; | |
| 523 | dev->regs->SR2 = 0; | |
| 524 | @@ -507,3 +708,31 @@ static void set_ccr_trise(i2c_dev *dev, uint32 flags) {
| |
| 525 | i2c_set_clk_control(dev, ccr); | |
| 526 | i2c_set_trise(dev, trise); | |
| 527 | } | |
| 528 | + | |
| 529 | + | |
| 530 | +/** | |
| 531 | + * @brief callback for when the device acts as a slave. If using an rx buffer, this is triggered | |
| 532 | + * after the last byte, otherwise it is called for every incoming packet. | |
| 533 | + * @param dev I2C device | |
| 534 | + * @param msg The dev_msg to pass to the slave init code | |
| 535 | + * @param func The function pointer to call | |
| 536 | + */ | |
| 537 | +void i2c_slave_attach_recv_handler(i2c_dev *dev, i2c_msg *msg, i2c_slave_recv_callback_func func) {
| |
| 538 | + dev->i2c_slave_recv_callback = func; | |
| 539 | + dev->i2c_slave_msg = msg; | |
| 540 | + msg->xferred = 0; | |
| 541 | +} | |
| 542 | + | |
| 543 | + | |
| 544 | +/** | |
| 545 | + * @brief callback for when the device acts as a slave. If using a tx buffer, this is triggered | |
| 546 | + * after the device is successsfully addressed with SLA+R. | |
| 547 | + * @param dev I2C device | |
| 548 | + * @param msg The dev_msg to pass to the slave init code | |
| 549 | + * @param func The function pointer to call | |
| 550 | + */ | |
| 551 | +void i2c_slave_attach_transmit_handler(i2c_dev *dev, i2c_msg *msg, i2c_slave_transmit_callback_func func) {
| |
| 552 | + dev->i2c_slave_transmit_callback = func; | |
| 553 | - | diff --git a/libmaple/i2c_private.h b/libmaple/i2c_private.h |
| 553 | + | |
| 554 | - | index 5b79516..7d25ae4 100644 |
| 554 | + | |
| 555 | - | --- a/libmaple/i2c_private.h |
| 555 | + | |
| 556 | - | +++ b/libmaple/i2c_private.h |
| 556 | + | |
| 557 | - | @@ -76,4 +76,5 @@ static inline struct gpio_dev* sda_port(const i2c_dev *dev) {
|
| 557 | + | index ff1c313..d4eac61 100644 |
| 558 | - | * i2c_master_enable(). */ |
| 558 | + | |
| 559 | - | void _i2c_set_ccr_trise(i2c_dev *dev, uint32 flags); |
| 559 | + | |
| 560 | @@ -93,6 +93,7 @@ typedef struct i2c_msg {
| |
| 561 | ||
| 562 | - | #endif /* _LIBMAPLE_I2C_PRIVATE_H_ */ |
| 562 | + | |
| 563 | #define I2C_MSG_10BIT_ADDR 0x2 | |
| 564 | - | index ff1c313..146c880 100644 |
| 564 | + | |
| 565 | /** | |
| 566 | * Bitwise OR of: | |
| 567 | * - I2C_MSG_READ (write is default) | |
| 568 | @@ -197,6 +198,10 @@ typedef struct i2c_msg {
| |
| 569 | #define I2C_DUTY_16_9 0x2 // 16/9 duty ratio | |
| 570 | /* Flag 0x4 is reserved; DO NOT USE. */ | |
| 571 | #define I2C_BUS_RESET 0x8 // Perform a bus reset | |
| 572 | +#define I2C_SLAVE_USE_RX_BUFFER 0x10 // Use a buffered message when doing a slave recv | |
| 573 | +#define I2C_SLAVE_USE_TX_BUFFER 0x20 // Use a buffered message when doing a slave transmit | |
| 574 | +#define I2C_SLAVE_DUAL_ADDRESS 0x40 // Enable the dual slave address scheme | |
| 575 | +#define I2C_SLAVE_GENERAL_CALL 0x80 // Enable the dual slave address scheme | |
| 576 | void i2c_master_enable(i2c_dev *dev, uint32 flags); | |
| 577 | ||
| 578 | #define I2C_ERROR_PROTOCOL (-1) | |
| 579 | - | +#define I2C_SLAVE_USE_RX_BUFFER 0x10 // Use a buffered message when doing a slave recv |
| 579 | + | |
| 580 | - | +#define I2C_SLAVE_USE_TX_BUFFER 0x20 // Use a buffered message when doing a slave transmit |
| 580 | + | |
| 581 | - | +#define I2C_SLAVE_DUAL_ADDRESS 0x40 // Enable the dual slave address scheme |
| 581 | + | |
| 582 | - | +#define I2C_SLAVE_GENERAL_CALL 0x80 // Enable the dual slave address scheme |
| 582 | + | |
| 583 | +/* Barry Carter | |
| 584 | + * Slave support | |
| 585 | + */ | |
| 586 | + | |
| 587 | +/** | |
| 588 | + * @brief Enable Dual addressing mode to allow peripheral to have 2 addresses | |
| 589 | + * @param dev I2C device | |
| 590 | + */ | |
| 591 | +static inline void i2c_slave_dual_address_enable(i2c_dev *dev) {
| |
| 592 | + dev->regs->OAR2 |= I2C_OAR2_ENDUAL; | |
| 593 | +} | |
| 594 | + | |
| 595 | +/** | |
| 596 | + * @brief Enable General Call to allow the unit to respond on addr 0x00 | |
| 597 | + * @param dev I2C device | |
| 598 | + */ | |
| 599 | +static inline void i2c_slave_general_call_enable(i2c_dev *dev) {
| |
| 600 | + dev->regs->CR1 |= I2C_CR1_ENGC; | |
| 601 | +} | |
| 602 | + | |
| 603 | +/* callback functions */ | |
| 604 | +/* Callback handler for data received over the bus */ | |
| 605 | +void i2c_slave_attach_recv_handler(i2c_dev *dev, i2c_msg *msg, i2c_slave_recv_callback_func func); | |
| 606 | + | |
| 607 | +/* Callback handler for data being requested over the bus | |
| 608 | + * The callback function must call i2c_write to get the data over the bus | |
| 609 | + */ | |
| 610 | +void i2c_slave_attach_transmit_handler(i2c_dev *dev, i2c_msg *msg, i2c_slave_transmit_callback_func func); | |
| 611 | + | |
| 612 | +/** | |
| 613 | + * @brief Set the primary I2c slave address | |
| 614 | + * @param dev I2C device | |
| 615 | + * @param address the 8 or 10 bit i2c address | |
| 616 | + */ | |
| 617 | +static inline void i2c_slave_set_own_address(i2c_dev *dev, uint16 address) {
| |
| 618 | + dev->regs->OAR1 = address <<1; | |
| 619 | +} | |
| 620 | + | |
| 621 | +/** | |
| 622 | + * @brief Set the secondary I2c slave address | |
| 623 | + * @param dev I2C device | |
| 624 | + * @param address the 8 or 10 bit i2c address | |
| 625 | + */ | |
| 626 | +static inline void i2c_slave_set_own_address2(i2c_dev *dev, uint16 address) {
| |
| 627 | +dev->regs->OAR2 = (address <<1 ) | I2C_OAR2_ENDUAL; | |
| 628 | +} | |
| 629 | + | |
| 630 | #ifdef __cplusplus | |
| 631 | } | |
| 632 | #endif | |
| 633 | diff --git a/libmaple/include/libmaple/i2c_common.h b/libmaple/include/libmaple/i2c_common.h | |
| 634 | - | + dev->regs->OAR2 = (address <<1 ) | I2C_OAR2_ENDUAL; |
| 634 | + | index 17cabe3..a855d4b 100644 |
| 635 | --- a/libmaple/include/libmaple/i2c_common.h | |
| 636 | +++ b/libmaple/include/libmaple/i2c_common.h | |
| 637 | @@ -55,6 +55,8 @@ typedef enum i2c_state {
| |
| 638 | I2C_STATE_ERROR = -1 /**< Error occurred */ | |
| 639 | } i2c_state; | |
| 640 | ||
| 641 | - | index 17cabe3..7337240 100644 |
| 641 | + | |
| 642 | +typedef void (*i2c_slave_transmit_callback_func)(struct i2c_msg *); | |
| 643 | /** | |
| 644 | * @brief I2C device type. | |
| 645 | */ | |
| 646 | @@ -88,6 +90,17 @@ typedef struct i2c_dev {
| |
| 647 | nvic_irq_num ev_nvic_line; /**< Event IRQ number */ | |
| 648 | nvic_irq_num er_nvic_line; /**< Error IRQ number */ | |
| 649 | volatile i2c_state state; /**< Device state */ | |
| 650 | + uint32 config_flags; /**< Configuration flags */ | |
| 651 | + | |
| 652 | + /* Barry Carter | |
| 653 | + * Slave implementation. Callback functions in this struct allow | |
| 654 | + * for a separate callback function for each I2C unit available onboard | |
| 655 | + */ | |
| 656 | + i2c_slave_transmit_callback_func i2c_slave_transmit_callback; | |
| 657 | - | + uint32 config_flags; /**< Configuration flags */ |
| 657 | + | |
| 658 | + | |
| 659 | + struct i2c_msg *i2c_slave_msg; /* the message that the i2c slave will use */ | |
| 660 | + | |
| 661 | } i2c_dev; | |
| 662 | ||
| 663 | #endif |