github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_k210.go (about) 1 //go:build k210 2 3 package machine 4 5 import ( 6 "device/kendryte" 7 "device/riscv" 8 "errors" 9 "runtime/interrupt" 10 "unsafe" 11 ) 12 13 const deviceName = kendryte.Device 14 15 func CPUFrequency() uint32 { 16 return 390000000 17 } 18 19 type fpioaPullMode uint8 20 type PinChange uint8 21 22 // Pin modes. 23 const ( 24 PinInput PinMode = iota 25 PinInputPullup 26 PinInputPulldown 27 PinOutput 28 ) 29 30 // Deprecated: use PinInputPullup and PinInputPulldown instead. 31 const ( 32 PinInputPullUp = PinInputPullup 33 PinInputPullDown = PinInputPulldown 34 ) 35 36 // FPIOA internal pull resistors. 37 const ( 38 fpioaPullNone fpioaPullMode = iota 39 fpioaPullDown 40 fpioaPullUp 41 ) 42 43 // GPIOHS pin interrupt events. 44 const ( 45 PinRising PinChange = 1 << iota 46 PinFalling 47 PinToggle = PinRising | PinFalling 48 ) 49 50 var ( 51 errUnsupportedSPIController = errors.New("SPI controller not supported. Use SPI0 or SPI1.") 52 errI2CTxAbort = errors.New("I2C transmition has been aborted.") 53 ) 54 55 func (p Pin) setFPIOAIOPull(pull fpioaPullMode) { 56 switch pull { 57 case fpioaPullNone: 58 kendryte.FPIOA.IO[uint8(p)].ClearBits(kendryte.FPIOA_IO_PU & kendryte.FPIOA_IO_PD) 59 case fpioaPullUp: 60 kendryte.FPIOA.IO[uint8(p)].SetBits(kendryte.FPIOA_IO_PU) 61 kendryte.FPIOA.IO[uint8(p)].ClearBits(kendryte.FPIOA_IO_PD) 62 case fpioaPullDown: 63 kendryte.FPIOA.IO[uint8(p)].ClearBits(kendryte.FPIOA_IO_PU) 64 kendryte.FPIOA.IO[uint8(p)].SetBits(kendryte.FPIOA_IO_PD) 65 } 66 } 67 68 // SetFPIOAFunction is used to configure the pin for one of the FPIOA functions. 69 // Each pin on the Kendryte K210 can be configured with any of the available FPIOA functions. 70 func (p Pin) SetFPIOAFunction(f FPIOAFunction) { 71 kendryte.FPIOA.IO[uint8(p)].Set(fpioaFuncDefaults[uint8(f)]) 72 } 73 74 // FPIOAFunction returns the current FPIOA function of the pin. 75 func (p Pin) FPIOAFunction() FPIOAFunction { 76 return FPIOAFunction((kendryte.FPIOA.IO[uint8(p)].Get() & kendryte.FPIOA_IO_CH_SEL_Msk)) 77 } 78 79 // Configure this pin with the given configuration. 80 // The pin must already be set as GPIO or GPIOHS pin. 81 func (p Pin) Configure(config PinConfig) { 82 var input bool 83 84 // Check if the current pin's FPIOA function is either GPIO or GPIOHS. 85 f := p.FPIOAFunction() 86 if f < FUNC_GPIOHS0 || f > FUNC_GPIO7 { 87 return // The pin is not configured as GPIO or GPIOHS. 88 } 89 90 // Configure pin. 91 kendryte.FPIOA.IO[uint8(p)].SetBits(kendryte.FPIOA_IO_OE_EN | kendryte.FPIOA_IO_IE_EN | kendryte.FPIOA_IO_ST | kendryte.FPIOA_IO_DS_Msk) 92 93 switch config.Mode { 94 case PinInput: 95 p.setFPIOAIOPull(fpioaPullNone) 96 input = true 97 case PinInputPullup: 98 p.setFPIOAIOPull(fpioaPullUp) 99 input = true 100 case PinInputPulldown: 101 p.setFPIOAIOPull(fpioaPullDown) 102 input = true 103 case PinOutput: 104 p.setFPIOAIOPull(fpioaPullNone) 105 input = false 106 } 107 108 if f >= FUNC_GPIO0 && f <= FUNC_GPIO7 { 109 // Converts the IO pin number in the effective GPIO number (based on the FPIOA function). 110 gpioPin := uint8(f - FUNC_GPIO0) 111 112 if input { 113 kendryte.GPIO.DIRECTION.ClearBits(1 << gpioPin) 114 } else { 115 kendryte.GPIO.DIRECTION.SetBits(1 << gpioPin) 116 } 117 } else if f >= FUNC_GPIOHS0 && f <= FUNC_GPIOHS31 { 118 // Converts the IO pin number in the effective GPIOHS number (based on the FPIOA function). 119 gpioPin := uint8(f - FUNC_GPIOHS0) 120 121 if input { 122 kendryte.GPIOHS.INPUT_EN.SetBits(1 << gpioPin) 123 kendryte.GPIOHS.OUTPUT_EN.ClearBits(1 << gpioPin) 124 } else { 125 kendryte.GPIOHS.OUTPUT_EN.SetBits(1 << gpioPin) 126 kendryte.GPIOHS.INPUT_EN.ClearBits(1 << gpioPin) 127 } 128 } 129 } 130 131 // Set the pin to high or low. 132 func (p Pin) Set(high bool) { 133 134 // Check if the current pin's FPIOA function is either GPIO or GPIOHS. 135 f := p.FPIOAFunction() 136 if f < FUNC_GPIOHS0 || f > FUNC_GPIO7 { 137 return // The pin is not configured as GPIO or GPIOHS. 138 } 139 140 if f >= FUNC_GPIO0 && f <= FUNC_GPIO7 { 141 gpioPin := uint8(f - FUNC_GPIO0) 142 143 if high { 144 kendryte.GPIO.DATA_OUTPUT.SetBits(1 << gpioPin) 145 } else { 146 kendryte.GPIO.DATA_OUTPUT.ClearBits(1 << gpioPin) 147 } 148 } else if f >= FUNC_GPIOHS0 && f <= FUNC_GPIOHS31 { 149 gpioPin := uint8(f - FUNC_GPIOHS0) 150 151 if high { 152 kendryte.GPIOHS.OUTPUT_VAL.SetBits(1 << gpioPin) 153 } else { 154 kendryte.GPIOHS.OUTPUT_VAL.ClearBits(1 << gpioPin) 155 } 156 } 157 } 158 159 // Get returns the current value of a GPIO pin. 160 func (p Pin) Get() bool { 161 162 // Check if the current pin's FPIOA function is either GPIO or GPIOHS. 163 f := p.FPIOAFunction() 164 if f < FUNC_GPIOHS0 || f > FUNC_GPIO7 { 165 return false // The pin is not configured as GPIO or GPIOHS. 166 } 167 168 var val uint32 169 if f >= FUNC_GPIO0 && f <= FUNC_GPIO7 { 170 gpioPin := uint8(f - FUNC_GPIO0) 171 val = kendryte.GPIO.DATA_INPUT.Get() & (1 << gpioPin) 172 } else if f >= FUNC_GPIOHS0 && f <= FUNC_GPIOHS31 { 173 gpioPin := uint8(f - FUNC_GPIOHS0) 174 val = kendryte.GPIOHS.INPUT_VAL.Get() & (1 << gpioPin) 175 } 176 return (val > 0) 177 } 178 179 // Callbacks to be called for GPIOHS pins configured with SetInterrupt. 180 var pinCallbacks [32]func(Pin) 181 182 // SetInterrupt sets an interrupt to be executed when a particular pin changes 183 // state. The pin should already be configured as an input, including a pull up 184 // or down if no external pull is provided. 185 // 186 // You can pass a nil func to unset the pin change interrupt. If you do so, 187 // the change parameter is ignored and can be set to any value (such as 0). 188 // If the pin is already configured with a callback, you must first unset 189 // this pins interrupt before you can set a new callback. 190 func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error { 191 192 // Check if the pin is a GPIOHS pin. 193 f := p.FPIOAFunction() 194 if f < FUNC_GPIOHS0 || f > FUNC_GPIOHS31 { 195 return ErrInvalidDataPin 196 } 197 198 gpioPin := uint8(f - FUNC_GPIOHS0) 199 200 // Clear all interrupts. 201 kendryte.GPIOHS.RISE_IE.ClearBits(1 << gpioPin) 202 kendryte.GPIOHS.FALL_IE.ClearBits(1 << gpioPin) 203 kendryte.GPIOHS.HIGH_IE.ClearBits(1 << gpioPin) 204 kendryte.GPIOHS.LOW_IE.ClearBits(1 << gpioPin) 205 206 // Clear all the pending bits for this pin. 207 kendryte.GPIOHS.RISE_IP.SetBits(1 << gpioPin) 208 kendryte.GPIOHS.FALL_IP.SetBits(1 << gpioPin) 209 kendryte.GPIOHS.HIGH_IP.SetBits(1 << gpioPin) 210 kendryte.GPIOHS.LOW_IP.SetBits(1 << gpioPin) 211 212 if callback == nil { 213 if pinCallbacks[gpioPin] != nil { 214 pinCallbacks[gpioPin] = nil 215 } 216 return nil 217 } 218 219 if pinCallbacks[gpioPin] != nil { 220 // The pin was already configured. 221 // To properly re-configure a pin, unset it first and set a new 222 // configuration. 223 return ErrNoPinChangeChannel 224 } 225 226 pinCallbacks[gpioPin] = callback 227 228 // Enable interrupts. 229 if change&PinRising != 0 { 230 kendryte.GPIOHS.RISE_IE.SetBits(1 << gpioPin) 231 } 232 if change&PinFalling != 0 { 233 kendryte.GPIOHS.FALL_IE.SetBits(1 << gpioPin) 234 } 235 236 handleInterrupt := func(inter interrupt.Interrupt) { 237 238 pin := uint8(inter.GetNumber() - kendryte.IRQ_GPIOHS0) 239 240 if kendryte.GPIOHS.RISE_IE.HasBits(1 << pin) { 241 kendryte.GPIOHS.RISE_IE.ClearBits(1 << pin) 242 // Acknowledge interrupt atomically. 243 riscv.AsmFull( 244 "amoor.w {}, {mask}, ({reg})", 245 map[string]interface{}{ 246 "mask": uint32(1 << pin), 247 "reg": uintptr(unsafe.Pointer(&kendryte.GPIOHS.RISE_IP.Reg)), 248 }) 249 kendryte.GPIOHS.RISE_IE.SetBits(1 << pin) 250 } 251 252 if kendryte.GPIOHS.FALL_IE.HasBits(1 << pin) { 253 kendryte.GPIOHS.FALL_IE.ClearBits(1 << pin) 254 // Acknowledge interrupt atomically. 255 riscv.AsmFull( 256 "amoor.w {}, {mask}, ({reg})", 257 map[string]interface{}{ 258 "mask": uint32(1 << pin), 259 "reg": uintptr(unsafe.Pointer(&kendryte.GPIOHS.FALL_IP.Reg)), 260 }) 261 kendryte.GPIOHS.FALL_IE.SetBits(1 << pin) 262 } 263 264 pinCallbacks[pin](Pin(pin)) 265 } 266 267 var ir interrupt.Interrupt 268 269 switch f { 270 case FUNC_GPIOHS0: 271 ir = interrupt.New(kendryte.IRQ_GPIOHS0, handleInterrupt) 272 case FUNC_GPIOHS1: 273 ir = interrupt.New(kendryte.IRQ_GPIOHS1, handleInterrupt) 274 case FUNC_GPIOHS2: 275 ir = interrupt.New(kendryte.IRQ_GPIOHS2, handleInterrupt) 276 case FUNC_GPIOHS3: 277 ir = interrupt.New(kendryte.IRQ_GPIOHS3, handleInterrupt) 278 case FUNC_GPIOHS4: 279 ir = interrupt.New(kendryte.IRQ_GPIOHS4, handleInterrupt) 280 case FUNC_GPIOHS5: 281 ir = interrupt.New(kendryte.IRQ_GPIOHS5, handleInterrupt) 282 case FUNC_GPIOHS6: 283 ir = interrupt.New(kendryte.IRQ_GPIOHS6, handleInterrupt) 284 case FUNC_GPIOHS7: 285 ir = interrupt.New(kendryte.IRQ_GPIOHS7, handleInterrupt) 286 case FUNC_GPIOHS8: 287 ir = interrupt.New(kendryte.IRQ_GPIOHS8, handleInterrupt) 288 case FUNC_GPIOHS9: 289 ir = interrupt.New(kendryte.IRQ_GPIOHS9, handleInterrupt) 290 case FUNC_GPIOHS10: 291 ir = interrupt.New(kendryte.IRQ_GPIOHS10, handleInterrupt) 292 case FUNC_GPIOHS11: 293 ir = interrupt.New(kendryte.IRQ_GPIOHS11, handleInterrupt) 294 case FUNC_GPIOHS12: 295 ir = interrupt.New(kendryte.IRQ_GPIOHS12, handleInterrupt) 296 case FUNC_GPIOHS13: 297 ir = interrupt.New(kendryte.IRQ_GPIOHS13, handleInterrupt) 298 case FUNC_GPIOHS14: 299 ir = interrupt.New(kendryte.IRQ_GPIOHS14, handleInterrupt) 300 case FUNC_GPIOHS15: 301 ir = interrupt.New(kendryte.IRQ_GPIOHS15, handleInterrupt) 302 case FUNC_GPIOHS16: 303 ir = interrupt.New(kendryte.IRQ_GPIOHS16, handleInterrupt) 304 case FUNC_GPIOHS17: 305 ir = interrupt.New(kendryte.IRQ_GPIOHS17, handleInterrupt) 306 case FUNC_GPIOHS18: 307 ir = interrupt.New(kendryte.IRQ_GPIOHS18, handleInterrupt) 308 case FUNC_GPIOHS19: 309 ir = interrupt.New(kendryte.IRQ_GPIOHS19, handleInterrupt) 310 case FUNC_GPIOHS20: 311 ir = interrupt.New(kendryte.IRQ_GPIOHS20, handleInterrupt) 312 case FUNC_GPIOHS21: 313 ir = interrupt.New(kendryte.IRQ_GPIOHS21, handleInterrupt) 314 case FUNC_GPIOHS22: 315 ir = interrupt.New(kendryte.IRQ_GPIOHS22, handleInterrupt) 316 case FUNC_GPIOHS23: 317 ir = interrupt.New(kendryte.IRQ_GPIOHS23, handleInterrupt) 318 case FUNC_GPIOHS24: 319 ir = interrupt.New(kendryte.IRQ_GPIOHS24, handleInterrupt) 320 case FUNC_GPIOHS25: 321 ir = interrupt.New(kendryte.IRQ_GPIOHS25, handleInterrupt) 322 case FUNC_GPIOHS26: 323 ir = interrupt.New(kendryte.IRQ_GPIOHS26, handleInterrupt) 324 case FUNC_GPIOHS27: 325 ir = interrupt.New(kendryte.IRQ_GPIOHS27, handleInterrupt) 326 case FUNC_GPIOHS28: 327 ir = interrupt.New(kendryte.IRQ_GPIOHS28, handleInterrupt) 328 case FUNC_GPIOHS29: 329 ir = interrupt.New(kendryte.IRQ_GPIOHS29, handleInterrupt) 330 case FUNC_GPIOHS30: 331 ir = interrupt.New(kendryte.IRQ_GPIOHS30, handleInterrupt) 332 case FUNC_GPIOHS31: 333 ir = interrupt.New(kendryte.IRQ_GPIOHS31, handleInterrupt) 334 } 335 336 ir.SetPriority(5) 337 ir.Enable() 338 339 return nil 340 341 } 342 343 type UART struct { 344 Bus *kendryte.UARTHS_Type 345 Buffer *RingBuffer 346 } 347 348 var ( 349 UART0 = &_UART0 350 _UART0 = UART{Bus: kendryte.UARTHS, Buffer: NewRingBuffer()} 351 ) 352 353 func (uart *UART) Configure(config UARTConfig) { 354 355 // Use default baudrate if not set. 356 if config.BaudRate == 0 { 357 config.BaudRate = 115200 358 } 359 360 // Use default pins if not set. 361 if config.TX == 0 && config.RX == 0 { 362 config.TX = UART_TX_PIN 363 config.RX = UART_RX_PIN 364 } 365 366 config.TX.SetFPIOAFunction(FUNC_UARTHS_TX) 367 config.RX.SetFPIOAFunction(FUNC_UARTHS_RX) 368 369 div := CPUFrequency()/config.BaudRate - 1 370 371 uart.Bus.DIV.Set(div) 372 uart.Bus.TXCTRL.Set(kendryte.UARTHS_TXCTRL_TXEN) 373 uart.Bus.RXCTRL.Set(kendryte.UARTHS_RXCTRL_RXEN) 374 375 // Enable interrupts on receive. 376 uart.Bus.IE.Set(kendryte.UARTHS_IE_RXWM) 377 378 intr := interrupt.New(kendryte.IRQ_UARTHS, _UART0.handleInterrupt) 379 intr.SetPriority(5) 380 intr.Enable() 381 } 382 383 func (uart *UART) handleInterrupt(interrupt.Interrupt) { 384 rxdata := uart.Bus.RXDATA.Get() 385 c := byte(rxdata) 386 if uint32(c) != rxdata { 387 // The rxdata has other bits set than just the low 8 bits. This probably 388 // means that the 'empty' flag is set, which indicates there is no data 389 // to be read and the byte is garbage. Ignore this byte. 390 return 391 } 392 uart.Receive(c) 393 } 394 395 func (uart *UART) writeByte(c byte) error { 396 for uart.Bus.TXDATA.Get()&kendryte.UARTHS_TXDATA_FULL != 0 { 397 } 398 399 uart.Bus.TXDATA.Set(uint32(c)) 400 return nil 401 } 402 403 func (uart *UART) flush() {} 404 405 type SPI struct { 406 Bus *kendryte.SPI_Type 407 } 408 409 // SPIConfig is used to store config info for SPI. 410 type SPIConfig struct { 411 Frequency uint32 412 SCK Pin 413 SDO Pin 414 SDI Pin 415 LSBFirst bool 416 Mode uint8 417 } 418 419 // Configure is intended to setup the SPI interface. 420 // Only SPI controller 0 and 1 can be used because SPI2 is a special 421 // peripheral-mode controller and SPI3 is used for flashing. 422 func (spi SPI) Configure(config SPIConfig) error { 423 // Use default pins if not set. 424 if config.SCK == 0 && config.SDO == 0 && config.SDI == 0 { 425 config.SCK = SPI0_SCK_PIN 426 config.SDO = SPI0_SDO_PIN 427 config.SDI = SPI0_SDI_PIN 428 } 429 430 // Enable APB2 clock. 431 kendryte.SYSCTL.CLK_EN_CENT.SetBits(kendryte.SYSCTL_CLK_EN_CENT_APB2_CLK_EN) 432 433 switch spi.Bus { 434 case kendryte.SPI0: 435 // Initialize SPI clock. 436 kendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_SPI0_CLK_EN) 437 kendryte.SYSCTL.CLK_TH1.ClearBits(kendryte.SYSCTL_CLK_TH1_SPI0_CLK_Msk) 438 439 // Initialize pins. 440 config.SCK.SetFPIOAFunction(FUNC_SPI0_SCLK) 441 config.SDO.SetFPIOAFunction(FUNC_SPI0_D0) 442 config.SDI.SetFPIOAFunction(FUNC_SPI0_D1) 443 case kendryte.SPI1: 444 // Initialize SPI clock. 445 kendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_SPI1_CLK_EN) 446 kendryte.SYSCTL.CLK_TH1.ClearBits(kendryte.SYSCTL_CLK_TH1_SPI1_CLK_Msk) 447 448 // Initialize pins. 449 config.SCK.SetFPIOAFunction(FUNC_SPI1_SCLK) 450 config.SDO.SetFPIOAFunction(FUNC_SPI1_D0) 451 config.SDI.SetFPIOAFunction(FUNC_SPI1_D1) 452 default: 453 return errUnsupportedSPIController 454 } 455 456 // Set default frequency. 457 if config.Frequency == 0 { 458 config.Frequency = 4000000 // 4MHz 459 } 460 461 baudr := CPUFrequency() / config.Frequency 462 spi.Bus.BAUDR.Set(baudr) 463 464 // Configure SPI mode 0, standard frame format, 8-bit data, little-endian. 465 spi.Bus.IMR.Set(0) 466 spi.Bus.DMACR.Set(0) 467 spi.Bus.DMATDLR.Set(0x10) 468 spi.Bus.DMARDLR.Set(0) 469 spi.Bus.SER.Set(0) 470 spi.Bus.SSIENR.Set(0) 471 spi.Bus.CTRLR0.Set((7 << 16)) 472 spi.Bus.SPI_CTRLR0.Set(0) 473 spi.Bus.ENDIAN.Set(0) 474 475 return nil 476 } 477 478 // Transfer writes/reads a single byte using the SPI interface. 479 func (spi SPI) Transfer(w byte) (byte, error) { 480 spi.Bus.SSIENR.Set(0) 481 482 // Set transfer-receive mode. 483 spi.Bus.CTRLR0.ClearBits(0x3 << 8) 484 485 // Enable/disable SPI. 486 spi.Bus.SSIENR.Set(1) 487 defer spi.Bus.SSIENR.Set(0) 488 489 // Enable/disable device. 490 spi.Bus.SER.Set(0x1) 491 defer spi.Bus.SER.Set(0) 492 493 spi.Bus.DR0.Set(uint32(w)) 494 495 // Wait for transfer. 496 for spi.Bus.SR.Get()&0x05 != 0x04 { 497 } 498 499 // Wait for data. 500 for spi.Bus.RXFLR.Get() == 0 { 501 } 502 503 return byte(spi.Bus.DR0.Get()), nil 504 } 505 506 // I2C on the K210. 507 type I2C struct { 508 Bus kendryte.I2C_Type 509 } 510 511 var ( 512 I2C0 = (*I2C)(unsafe.Pointer(kendryte.I2C0)) 513 I2C1 = (*I2C)(unsafe.Pointer(kendryte.I2C1)) 514 I2C2 = (*I2C)(unsafe.Pointer(kendryte.I2C2)) 515 ) 516 517 // I2CConfig is used to store config info for I2C. 518 type I2CConfig struct { 519 Frequency uint32 520 SCL Pin 521 SDA Pin 522 } 523 524 // Configure is intended to setup the I2C interface. 525 func (i2c *I2C) Configure(config I2CConfig) error { 526 527 if config.Frequency == 0 { 528 config.Frequency = 100 * KHz 529 } 530 531 if config.SDA == 0 && config.SCL == 0 { 532 config.SDA = I2C0_SDA_PIN 533 config.SCL = I2C0_SCL_PIN 534 } 535 536 // Enable APB0 clock. 537 kendryte.SYSCTL.CLK_EN_CENT.SetBits(kendryte.SYSCTL_CLK_EN_CENT_APB0_CLK_EN) 538 539 switch &i2c.Bus { 540 case kendryte.I2C0: 541 // Initialize I2C0 clock. 542 kendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_I2C0_CLK_EN) 543 kendryte.SYSCTL.CLK_TH5.ReplaceBits(0x03, kendryte.SYSCTL_CLK_TH5_I2C0_CLK_Msk, kendryte.SYSCTL_CLK_TH5_I2C0_CLK_Pos) 544 545 // Initialize pins. 546 config.SDA.SetFPIOAFunction(FUNC_I2C0_SDA) 547 config.SCL.SetFPIOAFunction(FUNC_I2C0_SCLK) 548 case kendryte.I2C1: 549 // Initialize I2C1 clock. 550 kendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_I2C1_CLK_EN) 551 kendryte.SYSCTL.CLK_TH5.ReplaceBits(0x03, kendryte.SYSCTL_CLK_TH5_I2C1_CLK_Msk, kendryte.SYSCTL_CLK_TH5_I2C1_CLK_Pos) 552 553 // Initialize pins. 554 config.SDA.SetFPIOAFunction(FUNC_I2C1_SDA) 555 config.SCL.SetFPIOAFunction(FUNC_I2C1_SCLK) 556 case kendryte.I2C2: 557 // Initialize I2C2 clock. 558 kendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_I2C2_CLK_EN) 559 kendryte.SYSCTL.CLK_TH5.ReplaceBits(0x03, kendryte.SYSCTL_CLK_TH5_I2C2_CLK_Msk, kendryte.SYSCTL_CLK_TH5_I2C2_CLK_Pos) 560 561 // Initialize pins. 562 config.SDA.SetFPIOAFunction(FUNC_I2C2_SDA) 563 config.SCL.SetFPIOAFunction(FUNC_I2C2_SCLK) 564 } 565 566 i2c.SetBaudRate(config.Frequency) 567 568 i2c.Bus.INTR_MASK.Set(0) 569 i2c.Bus.DMA_CR.Set(0x03) 570 i2c.Bus.DMA_RDLR.Set(0) 571 i2c.Bus.DMA_TDLR.Set(0x4) 572 573 return nil 574 } 575 576 // SetBaudRate sets the communication speed for I2C. 577 func (i2c *I2C) SetBaudRate(br uint32) error { 578 div := CPUFrequency() / br / 16 579 580 // Disable controller before setting the prescale register. 581 i2c.Bus.ENABLE.Set(0) 582 583 i2c.Bus.CON.Set(0x63) 584 585 // Set prescaler registers. 586 i2c.Bus.SS_SCL_HCNT.Set(uint32(div)) 587 i2c.Bus.SS_SCL_LCNT.Set(uint32(div)) 588 589 return nil 590 } 591 592 // Tx does a single I2C transaction at the specified address. 593 // It clocks out the given address, writes the bytes in w, reads back len(r) 594 // bytes and stores them in r, and generates a stop condition on the bus. 595 func (i2c *I2C) Tx(addr uint16, w, r []byte) error { 596 // Set peripheral address. 597 i2c.Bus.TAR.Set(uint32(addr)) 598 // Enable controller. 599 i2c.Bus.ENABLE.Set(1) 600 601 if len(w) != 0 { 602 i2c.Bus.CLR_TX_ABRT.Set(i2c.Bus.CLR_TX_ABRT.Get()) 603 dataLen := uint32(len(w)) 604 di := 0 605 606 for dataLen != 0 { 607 fifoLen := 8 - i2c.Bus.TXFLR.Get() 608 if dataLen < fifoLen { 609 fifoLen = dataLen 610 } 611 612 for i := uint32(0); i < fifoLen; i++ { 613 i2c.Bus.DATA_CMD.Set(uint32(w[di])) 614 di += 1 615 } 616 if i2c.Bus.TX_ABRT_SOURCE.Get() != 0 { 617 return errI2CTxAbort 618 } 619 dataLen -= fifoLen 620 } 621 622 // Wait for transmition to complete. 623 for i2c.Bus.STATUS.HasBits(kendryte.I2C_STATUS_ACTIVITY) || !i2c.Bus.STATUS.HasBits(kendryte.I2C_STATUS_TFE) { 624 } 625 626 if i2c.Bus.TX_ABRT_SOURCE.Get() != 0 { 627 return errI2CTxAbort 628 } 629 } 630 if len(r) != 0 { 631 dataLen := uint32(len(r)) 632 cmdLen := uint32(len(r)) 633 di := 0 634 635 for dataLen != 0 || cmdLen != 0 { 636 fifoLen := i2c.Bus.RXFLR.Get() 637 if dataLen < fifoLen { 638 fifoLen = dataLen 639 } 640 for i := uint32(0); i < fifoLen; i++ { 641 r[di] = byte(i2c.Bus.DATA_CMD.Get()) 642 di += 1 643 } 644 dataLen -= fifoLen 645 646 fifoLen = 8 - i2c.Bus.TXFLR.Get() 647 if cmdLen < fifoLen { 648 fifoLen = cmdLen 649 } 650 for i := uint32(0); i < fifoLen; i++ { 651 i2c.Bus.DATA_CMD.Set(0x100) 652 } 653 if i2c.Bus.TX_ABRT_SOURCE.Get() != 0 { 654 return errI2CTxAbort 655 } 656 cmdLen -= fifoLen 657 } 658 } 659 660 return nil 661 }