github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_rp2040_i2c.go (about) 1 //go:build rp2040 2 3 package machine 4 5 import ( 6 "device/rp" 7 "errors" 8 "internal/itoa" 9 ) 10 11 // I2C on the RP2040. 12 var ( 13 I2C0 = &_I2C0 14 _I2C0 = I2C{ 15 Bus: rp.I2C0, 16 } 17 I2C1 = &_I2C1 18 _I2C1 = I2C{ 19 Bus: rp.I2C1, 20 } 21 ) 22 23 // The I2C target implementation is based on the C implementation from 24 // here: https://github.com/vmilea/pico_i2c_slave 25 26 // Features: Taken from datasheet. 27 // Default controller mode, with target mode available (not simulataneously). 28 // Default target address of RP2040: 0x055 29 // Supports 10-bit addressing in controller mode 30 // 16-element transmit buffer 31 // 16-element receive buffer 32 // Can be driven from DMA 33 // Can generate interrupts 34 // Fast mode plus max transfer speed (1000kb/s) 35 36 // GPIO config 37 // Each controller must connect its clock SCL and data SDA to one pair of GPIOs. 38 // The I2C standard requires that drivers drivea signal low, or when not driven the signal will be pulled high. 39 // This applies to SCL and SDA. The GPIO pads should beconfigured for: 40 // Pull-up enabled 41 // Slew rate limited 42 // Schmitt trigger enabled 43 // Note: There should also be external pull-ups on the board as the internal pad pull-ups may not be strong enough to pull upexternal circuits. 44 45 // I2CConfig is used to store config info for I2C. 46 type I2CConfig struct { 47 Frequency uint32 48 // SDA/SCL Serial Data and clock pins. Refer to datasheet to see 49 // which pins match the desired bus. 50 SDA, SCL Pin 51 Mode I2CMode 52 } 53 54 type I2C struct { 55 Bus *rp.I2C0_Type 56 mode I2CMode 57 txInProgress bool 58 } 59 60 var ( 61 ErrInvalidI2CBaudrate = errors.New("invalid i2c baudrate") 62 ErrInvalidTgtAddr = errors.New("invalid target i2c address not in 0..0x80 or is reserved") 63 ErrI2CGeneric = errors.New("i2c error") 64 ErrRP2040I2CDisable = errors.New("i2c rp2040 peripheral timeout in disable") 65 errInvalidI2CSDA = errors.New("invalid I2C SDA pin") 66 errInvalidI2CSCL = errors.New("invalid I2C SCL pin") 67 ErrI2CAlreadyListening = errors.New("i2c already listening") 68 ErrI2CWrongMode = errors.New("i2c wrong mode") 69 ErrI2CUnderflow = errors.New("i2c underflow") 70 ) 71 72 // Tx performs a write and then a read transfer placing the result in 73 // in r. 74 // 75 // Passing a nil value for w or r skips the transfer corresponding to write 76 // or read, respectively. 77 // 78 // i2c.Tx(addr, nil, r) 79 // 80 // Performs only a read transfer. 81 // 82 // i2c.Tx(addr, w, nil) 83 // 84 // Performs only a write transfer. 85 func (i2c *I2C) Tx(addr uint16, w, r []byte) error { 86 if i2c.mode != I2CModeController { 87 return ErrI2CWrongMode 88 } 89 90 // timeout in microseconds. 91 const timeout = 40 * 1000 // 40ms is a reasonable time for a real-time system. 92 return i2c.tx(uint8(addr), w, r, timeout) 93 } 94 95 // Listen starts listening for I2C requests sent to specified address 96 // 97 // addr is the address to listen to 98 func (i2c *I2C) Listen(addr uint16) error { 99 if i2c.mode != I2CModeTarget { 100 return ErrI2CWrongMode 101 } 102 103 return i2c.listen(uint8(addr)) 104 } 105 106 // Configure initializes i2c peripheral and configures I2C config's pins passed. 107 // Here's a list of valid SDA and SCL GPIO pins on bus I2C0 of the rp2040: 108 // 109 // SDA: 0, 4, 8, 12, 16, 20 110 // SCL: 1, 5, 9, 13, 17, 21 111 // 112 // Same as above for I2C1 bus: 113 // 114 // SDA: 2, 6, 10, 14, 18, 26 115 // SCL: 3, 7, 11, 15, 19, 27 116 func (i2c *I2C) Configure(config I2CConfig) error { 117 const defaultBaud uint32 = 100_000 // 100kHz standard mode 118 if config.SCL == 0 && config.SDA == 0 { 119 // If config pins are zero valued or clock pin is invalid then we set default values. 120 switch i2c.Bus { 121 case rp.I2C0: 122 config.SCL = I2C0_SCL_PIN 123 config.SDA = I2C0_SDA_PIN 124 case rp.I2C1: 125 config.SCL = I2C1_SCL_PIN 126 config.SDA = I2C1_SDA_PIN 127 } 128 } 129 var okSCL, okSDA bool 130 switch i2c.Bus { 131 case rp.I2C0: 132 okSCL = (config.SCL+3)%4 == 0 133 okSDA = (config.SDA+4)%4 == 0 134 case rp.I2C1: 135 okSCL = (config.SCL+1)%4 == 0 136 okSDA = (config.SDA+2)%4 == 0 137 } 138 139 switch { 140 case !okSCL: 141 return errInvalidI2CSCL 142 case !okSDA: 143 return errInvalidI2CSDA 144 } 145 146 if config.Frequency == 0 { 147 config.Frequency = defaultBaud 148 } 149 config.SDA.Configure(PinConfig{PinI2C}) 150 config.SCL.Configure(PinConfig{PinI2C}) 151 return i2c.init(config) 152 } 153 154 // SetBaudRate sets the I2C frequency. It has the side effect of also 155 // enabling the I2C hardware if disabled beforehand. 156 // 157 //go:inline 158 func (i2c *I2C) SetBaudRate(br uint32) error { 159 160 if br == 0 { 161 return ErrInvalidI2CBaudrate 162 } 163 164 // I2C is synchronous design that runs from clk_sys 165 freqin := CPUFrequency() 166 167 // TODO there are some subtleties to I2C timing which we are completely ignoring here 168 period := (freqin + br/2) / br 169 lcnt := period * 3 / 5 // oof this one hurts 170 hcnt := period - lcnt 171 // Check for out-of-range divisors: 172 if hcnt > rp.I2C0_IC_FS_SCL_HCNT_IC_FS_SCL_HCNT_Msk || hcnt < 8 || lcnt > rp.I2C0_IC_FS_SCL_LCNT_IC_FS_SCL_LCNT_Msk || lcnt < 8 { 173 return ErrInvalidI2CBaudrate 174 } 175 176 // Per I2C-bus specification a device in standard or fast mode must 177 // internally provide a hold time of at least 300ns for the SDA signal to 178 // bridge the undefined region of the falling edge of SCL. A smaller hold 179 // time of 120ns is used for fast mode plus. 180 181 // sda_tx_hold_count = freq_in [cycles/s] * 300ns * (1s / 1e9ns) 182 // Reduce 300/1e9 to 3/1e7 to avoid numbers that don't fit in uint. 183 // Add 1 to avoid division truncation. 184 sdaTxHoldCnt := ((freqin * 3) / 10000000) + 1 185 if br >= 1_000_000 { 186 // sda_tx_hold_count = freq_in [cycles/s] * 120ns * (1s / 1e9ns) 187 // Reduce 120/1e9 to 3/25e6 to avoid numbers that don't fit in uint. 188 // Add 1 to avoid division truncation. 189 sdaTxHoldCnt = ((freqin * 3) / 25000000) + 1 190 } 191 192 if sdaTxHoldCnt > lcnt-2 { 193 return ErrInvalidI2CBaudrate 194 } 195 err := i2c.disable() 196 if err != nil { 197 return err 198 } 199 // Always use "fast" mode (<= 400 kHz, works fine for standard mode too) 200 201 i2c.Bus.IC_CON.ReplaceBits(rp.I2C0_IC_CON_SPEED_FAST<<rp.I2C0_IC_CON_SPEED_Pos, rp.I2C0_IC_CON_SPEED_Msk, 0) 202 i2c.Bus.IC_FS_SCL_HCNT.Set(hcnt) 203 i2c.Bus.IC_FS_SCL_LCNT.Set(lcnt) 204 205 i2c.Bus.IC_FS_SPKLEN.Set(u32max(1, lcnt/16)) 206 207 i2c.Bus.IC_SDA_HOLD.ReplaceBits(sdaTxHoldCnt<<rp.I2C0_IC_SDA_HOLD_IC_SDA_TX_HOLD_Pos, rp.I2C0_IC_SDA_HOLD_IC_SDA_TX_HOLD_Msk, 0) 208 i2c.enable() 209 return nil 210 } 211 212 //go:inline 213 func (i2c *I2C) enable() { 214 i2c.Bus.IC_ENABLE.ReplaceBits(rp.I2C0_IC_ENABLE_ENABLE<<rp.I2C0_IC_ENABLE_ENABLE_Pos, rp.I2C0_IC_ENABLE_ENABLE_Msk, 0) 215 } 216 217 // Implemented as per 4.3.10.3. Disabling DW_apb_i2c section. 218 // 219 //go:inline 220 func (i2c *I2C) disable() error { 221 const MAX_T_POLL_COUNT = 64 // 64 us timeout corresponds to around 1000kb/s i2c transfer rate. 222 deadline := ticks() + MAX_T_POLL_COUNT 223 i2c.Bus.IC_ENABLE.Set(0) 224 for i2c.Bus.IC_ENABLE_STATUS.Get()&1 != 0 { 225 if ticks() > deadline { 226 return ErrRP2040I2CDisable 227 } 228 } 229 return nil 230 } 231 232 //go:inline 233 func (i2c *I2C) init(config I2CConfig) error { 234 i2c.reset() 235 if err := i2c.disable(); err != nil { 236 return err 237 } 238 239 i2c.mode = config.Mode 240 241 // Configure as fast-mode with RepStart support, 7-bit addresses 242 mode := uint32(rp.I2C0_IC_CON_SPEED_FAST<<rp.I2C0_IC_CON_SPEED_Pos) | 243 rp.I2C0_IC_CON_IC_RESTART_EN | rp.I2C0_IC_CON_TX_EMPTY_CTRL // sets TX_EMPTY_CTRL to enable TX_EMPTY interrupt status 244 if config.Mode == I2CModeController { 245 mode |= rp.I2C0_IC_CON_MASTER_MODE | rp.I2C0_IC_CON_IC_SLAVE_DISABLE 246 } 247 i2c.Bus.IC_CON.Set(mode) 248 249 // Set FIFO watermarks to 1 to make things simpler. This is encoded by a register value of 0. 250 if config.Mode == I2CModeController { 251 i2c.Bus.IC_TX_TL.Set(0) 252 i2c.Bus.IC_RX_TL.Set(0) 253 } 254 255 // Always enable the DREQ signalling -- harmless if DMA isn't listening 256 i2c.Bus.IC_DMA_CR.Set(rp.I2C0_IC_DMA_CR_TDMAE | rp.I2C0_IC_DMA_CR_RDMAE) 257 return i2c.SetBaudRate(config.Frequency) 258 } 259 260 // reset sets I2C register RESET bits in the reset peripheral and then clears them. 261 // 262 //go:inline 263 func (i2c *I2C) reset() { 264 resetVal := i2c.deinit() 265 rp.RESETS.RESET.ClearBits(resetVal) 266 // Wait until reset is done. 267 for !rp.RESETS.RESET_DONE.HasBits(resetVal) { 268 } 269 } 270 271 // deinit sets reset bit for I2C. Must call reset to reenable I2C after deinit. 272 // 273 //go:inline 274 func (i2c *I2C) deinit() (resetVal uint32) { 275 switch { 276 case i2c.Bus == rp.I2C0: 277 resetVal = rp.RESETS_RESET_I2C0 278 case i2c.Bus == rp.I2C1: 279 resetVal = rp.RESETS_RESET_I2C1 280 } 281 // Perform I2C reset. 282 rp.RESETS.RESET.SetBits(resetVal) 283 284 return resetVal 285 } 286 287 // tx performs blocking write followed by read to I2C bus. 288 func (i2c *I2C) tx(addr uint8, tx, rx []byte, timeout_us uint64) (err error) { 289 deadline := ticks() + timeout_us 290 if addr >= 0x80 || isReservedI2CAddr(addr) { 291 return ErrInvalidTgtAddr 292 } 293 txlen := len(tx) 294 rxlen := len(rx) 295 // Quick return if possible. 296 if txlen == 0 && rxlen == 0 { 297 return nil 298 } 299 300 err = i2c.disable() 301 if err != nil { 302 return err 303 } 304 i2c.Bus.IC_TAR.Set(uint32(addr)) 305 i2c.enable() 306 abort := false 307 var abortReason i2cAbortError 308 txStop := rxlen == 0 309 for txCtr := 0; txCtr < txlen; txCtr++ { 310 if abort { 311 break 312 } 313 first := txCtr == 0 314 last := txCtr == txlen-1 && rxlen == 0 315 i2c.Bus.IC_DATA_CMD.Set( 316 (boolToBit(first) << rp.I2C0_IC_DATA_CMD_RESTART_Pos) | 317 (boolToBit(last && txStop) << rp.I2C0_IC_DATA_CMD_STOP_Pos) | 318 uint32(tx[txCtr])) 319 320 // Wait until the transmission of the address/data from the internal 321 // shift register has completed. For this to function correctly, the 322 // TX_EMPTY_CTRL flag in IC_CON must be set. The TX_EMPTY_CTRL flag 323 // was set in i2c_init. 324 325 // IC_RAW_INTR_STAT_TX_EMPTY: This bit is set to 1 when the transmit buffer is at or below 326 // the threshold value set in the IC_TX_TL register and the 327 // transmission of the address/data from the internal shift 328 // register for the most recently popped command is 329 // completed. It is automatically cleared by hardware when 330 // the buffer level goes above the threshold. When 331 // IC_ENABLE[0] is set to 0, the TX FIFO is flushed and held 332 // in reset. There the TX FIFO looks like it has no data within 333 // it, so this bit is set to 1, provided there is activity in the 334 // controller or target state machines. When there is no longer 335 // any activity, then with ic_en=0, this bit is set to 0. 336 for !i2c.interrupted(rp.I2C0_IC_RAW_INTR_STAT_TX_EMPTY) { 337 if ticks() > deadline { 338 return errI2CWriteTimeout // If there was a timeout, don't attempt to do anything else. 339 } 340 341 gosched() 342 } 343 344 abortReason = i2c.getAbortReason() 345 if abortReason != 0 { 346 i2c.clearAbortReason() 347 abort = true 348 } 349 if abort || last { 350 // If the transaction was aborted or if it completed 351 // successfully wait until the STOP condition has occured. 352 353 // TODO Could there be an abort while waiting for the STOP 354 // condition here? If so, additional code would be needed here 355 // to take care of the abort. 356 for !i2c.interrupted(rp.I2C0_IC_RAW_INTR_STAT_STOP_DET) { 357 if ticks() > deadline { 358 if abort { 359 return abortReason 360 } 361 return errI2CWriteTimeout 362 } 363 364 gosched() 365 } 366 i2c.Bus.IC_CLR_STOP_DET.Get() 367 } 368 } 369 370 // Midway check for abort. Related issue https://github.com/tinygo-org/tinygo/issues/3671. 371 // The root cause for an abort after writing registers was "tx data no ack" (abort code=8). 372 // If the abort code was not registered then the whole peripheral would remain in disabled state forever. 373 abortReason = i2c.getAbortReason() 374 if abortReason != 0 { 375 i2c.clearAbortReason() 376 abort = true 377 } 378 379 rxStart := txlen == 0 380 if rxlen > 0 && !abort { 381 for rxCtr := 0; rxCtr < rxlen; rxCtr++ { 382 first := rxCtr == 0 383 last := rxCtr == rxlen-1 384 for i2c.writeAvailable() == 0 { 385 gosched() 386 } 387 i2c.Bus.IC_DATA_CMD.Set( 388 boolToBit(first && rxStart)<<rp.I2C0_IC_DATA_CMD_RESTART_Pos | 389 boolToBit(last)<<rp.I2C0_IC_DATA_CMD_STOP_Pos | 390 rp.I2C0_IC_DATA_CMD_CMD) // -> 1 for read 391 392 for !abort && i2c.readAvailable() == 0 { 393 abortReason = i2c.getAbortReason() 394 if abortReason != 0 { 395 i2c.clearAbortReason() 396 abort = true 397 } 398 if ticks() > deadline { 399 return errI2CReadTimeout // If there was a timeout, don't attempt to do anything else. 400 } 401 402 gosched() 403 } 404 if abort { 405 break 406 } 407 rx[rxCtr] = uint8(i2c.Bus.IC_DATA_CMD.Get()) 408 } 409 } 410 // From Pico SDK: A lot of things could have just happened due to the ingenious and 411 // creative design of I2C. Try to figure things out. 412 if abort { 413 switch { 414 case abortReason == 0 || abortReason&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK != 0: 415 // No reported errors - seems to happen if there is nothing connected to the bus. 416 // Address byte not acknowledged 417 err = ErrI2CGeneric 418 case abortReason&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK != 0: 419 // Address acknowledged, some data not acknowledged 420 fallthrough 421 default: 422 err = abortReason 423 } 424 } 425 return err 426 } 427 428 // listen sets up for async handling of requests on the I2C bus. 429 func (i2c *I2C) listen(addr uint8) error { 430 if addr >= 0x80 || isReservedI2CAddr(addr) { 431 return ErrInvalidTgtAddr 432 } 433 434 err := i2c.disable() 435 if err != nil { 436 return err 437 } 438 439 i2c.Bus.IC_SAR.Set(uint32(addr)) 440 441 i2c.enable() 442 443 return nil 444 } 445 446 func (i2c *I2C) WaitForEvent(buf []byte) (evt I2CTargetEvent, count int, err error) { 447 rxPtr := 0 448 for { 449 stat := i2c.Bus.IC_RAW_INTR_STAT.Get() 450 451 if stat&rp.I2C0_IC_INTR_MASK_M_RX_FULL != 0 { 452 b := uint8(i2c.Bus.IC_DATA_CMD.Get()) 453 if rxPtr < len(buf) { 454 buf[rxPtr] = b 455 rxPtr++ 456 } 457 } 458 459 // Stop 460 if stat&rp.I2C0_IC_INTR_MASK_M_STOP_DET != 0 { 461 if rxPtr > 0 { 462 return I2CReceive, rxPtr, nil 463 } 464 465 i2c.Bus.IC_CLR_STOP_DET.Get() // clear 466 return I2CFinish, 0, nil 467 } 468 469 // Start or restart - ignore start, return on restart 470 if stat&rp.I2C0_IC_INTR_MASK_M_START_DET != 0 { 471 i2c.Bus.IC_CLR_START_DET.Get() // clear restart 472 473 // Restart 474 if rxPtr > 0 { 475 return I2CReceive, rxPtr, nil 476 } 477 } 478 479 // Read request - leave flag set until we start to reply. 480 if stat&rp.I2C0_IC_INTR_MASK_M_RD_REQ != 0 { 481 return I2CRequest, 0, nil 482 } 483 484 gosched() 485 } 486 } 487 488 func (i2c *I2C) Reply(buf []byte) error { 489 txPtr := 0 490 491 stat := i2c.Bus.IC_RAW_INTR_STAT.Get() 492 493 if stat&rp.I2C0_IC_INTR_MASK_M_RD_REQ == 0 { 494 return ErrI2CWrongMode 495 } 496 i2c.Bus.IC_CLR_RD_REQ.Get() // clear restart 497 498 // Clear any dangling TX abort 499 if stat&rp.I2C0_IC_INTR_MASK_M_TX_ABRT != 0 { 500 i2c.Bus.IC_CLR_TX_ABRT.Get() 501 } 502 503 for txPtr < len(buf) { 504 if stat&rp.I2C0_IC_INTR_MASK_M_TX_EMPTY != 0 { 505 i2c.Bus.IC_DATA_CMD.Set(uint32(buf[txPtr])) 506 txPtr++ 507 } 508 509 // This Tx abort is a normal case - we're sending more 510 // data than controller wants to receive 511 if stat&rp.I2C0_IC_INTR_MASK_M_TX_ABRT != 0 { 512 i2c.Bus.IC_CLR_TX_ABRT.Get() 513 return nil 514 } 515 516 gosched() 517 } 518 519 return nil 520 } 521 522 // writeAvailable determines non-blocking write space available 523 // 524 //go:inline 525 func (i2c *I2C) writeAvailable() uint32 { 526 return rp.I2C0_IC_COMP_PARAM_1_TX_BUFFER_DEPTH_Pos - i2c.Bus.IC_TXFLR.Get() 527 } 528 529 // readAvailable determines number of bytes received 530 // 531 //go:inline 532 func (i2c *I2C) readAvailable() uint32 { 533 return i2c.Bus.IC_RXFLR.Get() 534 } 535 536 // Equivalent to IC_CLR_TX_ABRT.Get() (side effect clears ABORT_REASON) 537 // 538 //go:inline 539 func (i2c *I2C) clearAbortReason() { 540 // Note clearing the abort flag also clears the reason, and 541 // this instance of flag is clear-on-read! Note also the 542 // IC_CLR_TX_ABRT register always reads as 0. 543 i2c.Bus.IC_CLR_TX_ABRT.Get() 544 } 545 546 // getAbortReason reads IC_TX_ABRT_SOURCE register. 547 // 548 //go:inline 549 func (i2c *I2C) getAbortReason() i2cAbortError { 550 return i2cAbortError(i2c.Bus.IC_TX_ABRT_SOURCE.Get()) 551 } 552 553 // returns true if RAW_INTR_STAT bits in mask are all set. performs: 554 // 555 // RAW_INTR_STAT & mask == mask 556 // 557 //go:inline 558 func (i2c *I2C) interrupted(mask uint32) bool { 559 reg := i2c.Bus.IC_RAW_INTR_STAT.Get() 560 return reg&mask == mask 561 } 562 563 type i2cAbortError uint32 564 565 func (b i2cAbortError) Error() string { 566 return "i2c abort, reason " + itoa.Uitoa(uint(b)) 567 } 568 569 func (b i2cAbortError) Reasons() (reasons []string) { 570 if b == 0 { 571 return nil 572 } 573 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK != 0 { 574 reasons = append(reasons, "7-bit address no ack") 575 } 576 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK != 0 { 577 reasons = append(reasons, "10-bit address first byte no ack") 578 } 579 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK != 0 { 580 reasons = append(reasons, "10-bit address second byte no ack") 581 } 582 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK != 0 { 583 reasons = append(reasons, "tx data no ack") 584 } 585 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK != 0 { 586 reasons = append(reasons, "general call no ack") 587 } 588 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ != 0 { 589 reasons = append(reasons, "general call read") 590 } 591 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET != 0 { 592 reasons = append(reasons, "high speed ack detect") 593 } 594 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET != 0 { 595 reasons = append(reasons, "start byte ack detect") 596 } 597 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT != 0 { 598 reasons = append(reasons, "high speed no restart") 599 } 600 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT != 0 { 601 reasons = append(reasons, "start byte no restart") 602 } 603 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT != 0 { 604 reasons = append(reasons, "10-bit read no restart") 605 } 606 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS != 0 { 607 reasons = append(reasons, "master disabled") 608 } 609 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ARB_LOST != 0 { 610 reasons = append(reasons, "arbitration lost") 611 } 612 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO != 0 { 613 reasons = append(reasons, "slave flush tx fifo") 614 } 615 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST != 0 { 616 reasons = append(reasons, "slave arbitration lost") 617 } 618 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX != 0 { 619 reasons = append(reasons, "slave read while inactive") 620 } 621 if b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT != 0 { 622 reasons = append(reasons, "user abort") 623 } 624 return reasons 625 } 626 627 //go:inline 628 func boolToBit(a bool) uint32 { 629 if a { 630 return 1 631 } 632 return 0 633 } 634 635 //go:inline 636 func u32max(a, b uint32) uint32 { 637 if a > b { 638 return a 639 } 640 return b 641 } 642 643 //go:inline 644 func isReservedI2CAddr(addr uint8) bool { 645 return (addr&0x78) == 0 || (addr&0x78) == 0x78 646 }