diff --git a/src/machine/board_maixbit.go b/src/machine/board_maixbit.go index e0c1d9ca..2c60fc98 100644 --- a/src/machine/board_maixbit.go +++ b/src/machine/board_maixbit.go @@ -2,52 +2,56 @@ package machine -// GPIO pins. +// Pins on the MAix Bit. const ( - D0 = P08 - D1 = P09 - D2 = P10 - D3 = P11 - D4 = P12 - D5 = P13 - D6 = P14 - D7 = P15 -) - -// High-speed GPIO pins (GPIOHS). -const ( - DHS0 = P16 - DHS1 = P17 - DHS2 = P18 - DHS3 = P19 - DHS4 = P20 - DHS5 = P21 - DHS6 = P22 - DHS7 = P23 - DHS8 = P24 - DHS9 = P25 - DHS10 = P26 - DHS11 = P27 - DHS12 = P28 - DHS13 = P29 - DHS14 = P30 - DHS15 = P31 - DHS16 = P32 - DHS17 = P33 - DHS18 = P34 - DHS19 = P35 - DHS20 = P36 - DHS21 = P37 - DHS22 = P38 - DHS23 = P39 - DHS24 = P40 - DHS25 = P41 - DHS26 = P42 - DHS27 = P43 - DHS28 = P44 - DHS29 = P45 - DHS30 = P46 - DHS31 = P47 + D0 = P00 // JTAG_TCLK + D1 = P01 // JTAG_TDI + D2 = P02 // JTAG_TMS + D3 = P03 // JTAG_TDO + D4 = P04 // UARTHS_RX + D5 = P05 // UARTHS_TX + D6 = P06 // RESV0 + D7 = P07 // RESV0 + D8 = P08 // GPIO1 + D9 = P09 // GPIO2 + D10 = P10 // GPIO3 + D11 = P11 // GPIO4 + D12 = P12 // GPIO5 + D13 = P13 // GPIO6 + D14 = P14 // GPIO7 + D15 = P15 // GPIO8 + D16 = P16 // GPIOHS0 + D17 = P17 // GPIOHS1 + D18 = P18 // GPIOHS2 + D19 = P19 // GPIOHS3 + D20 = P20 // GPIOHS4 + D21 = P21 // GPIOHS5 + D22 = P22 // GPIOHS6 + D23 = P23 // GPIOHS7 + D24 = P24 // GPIOHS8 + D25 = P25 // GPIOHS9 + D26 = P26 // GPIOHS10 / SPI0_MISO + D27 = P27 // GPIOHS11 / SPI0_SCLK + D28 = P28 // GPIOHS12 / SPI0_MOSI + D29 = P29 // GPIOHS13 + D30 = P30 // GPIOHS14 + D31 = P31 // GPIOHS15 + D32 = P32 // GPIOHS16 + D33 = P33 // GPIOHS17 + D34 = P34 // GPIOHS18 + D35 = P35 // GPIOHS19 + D36 = P36 // GPIOHS20 + D37 = P37 // GPIOHS21 + D38 = P38 // GPIOHS22 + D39 = P39 // GPIOHS23 + D40 = P40 // GPIOHS24 + D41 = P41 // GPIOHS25 + D42 = P42 // GPIOHS26 + D43 = P43 // GPIOHS27 + D44 = P44 // GPIOHS28 + D45 = P45 // GPIOHS29 + D46 = P46 // GPIOHS30 + D47 = P47 // GPIOHS31 ) const ( @@ -55,13 +59,20 @@ const ( LED1 = LED_RED LED2 = LED_GREEN LED3 = LED_BLUE - LED_RED = D5 - LED_GREEN = D4 - LED_BLUE = D6 + LED_RED = D13 + LED_GREEN = D12 + LED_BLUE = D14 ) -// Default pins for UARTHS +// Default pins for UARTHS. const ( - UART_TX_PIN = P05 - UART_RX_PIN = P04 + UART_TX_PIN = D5 + UART_RX_PIN = D4 +) + +// SPI pins. +const ( + SPI0_SCK_PIN = D27 + SPI0_MOSI_PIN = D28 + SPI0_MISO_PIN = D26 ) diff --git a/src/machine/board_maixbit_baremetal.go b/src/machine/board_maixbit_baremetal.go new file mode 100644 index 00000000..98733bee --- /dev/null +++ b/src/machine/board_maixbit_baremetal.go @@ -0,0 +1,15 @@ +// +build k210,maixbit + +package machine + +import "device/kendryte" + +// SPI on the MAix Bit. +var ( + SPI0 = SPI{ + Bus: kendryte.SPI0, + } + SPI1 = SPI{ + Bus: kendryte.SPI1, + } +) diff --git a/src/machine/machine_k210.go b/src/machine/machine_k210.go index c14d3c40..247db080 100644 --- a/src/machine/machine_k210.go +++ b/src/machine/machine_k210.go @@ -4,6 +4,7 @@ package machine import ( "device/kendryte" + "errors" "runtime/interrupt" ) @@ -15,6 +16,7 @@ type PinMode uint8 type fpioaPullMode uint8 type PinChange uint8 +// Pin modes. const ( PinInput PinMode = iota PinInputPullUp @@ -22,12 +24,14 @@ const ( PinOutput ) +// FPIOA internal pull resistors. const ( fpioaPullNone fpioaPullMode = iota fpioaPullDown fpioaPullUp ) +// GPIOHS pin interrupt events. const ( PinRising PinChange = iota + 1 PinFalling @@ -36,6 +40,20 @@ const ( PinLow = 8 ) +// FPIOA functions. +const ( + fpioaFuncSpi0Sclk = 17 + fpioaFuncSpi0D0 = 4 + fpioaFuncSpi0D1 = 5 + fpioaFuncSpi1Sclk = 83 + fpioaFuncSpi1D0 = 70 + fpioaFuncSpi1D1 = 71 +) + +var ( + ErrUnsupportedSPIController = errors.New("SPI controller not supported. Use SPI0 or SPI1.") +) + func (p Pin) fpioaSetIOPull(pull fpioaPullMode) { switch pull { case fpioaPullNone: @@ -340,3 +358,120 @@ func (uart UART) WriteByte(c byte) { uart.Bus.TXDATA.Set(uint32(c)) } + +type SPI struct { + Bus *kendryte.SPI_Type +} + +// SPIConfig is used to store config info for SPI. +type SPIConfig struct { + Frequency uint32 + SCK Pin + MOSI Pin + MISO Pin + LSBFirst bool + Mode uint8 +} + +// Configure is intended to setup the SPI interface. +// Only SPI controller 0 and 1 can be used because SPI2 is a special +// slave-mode controller and SPI3 is used for flashing. +func (spi SPI) Configure(config SPIConfig) error { + // Use default pins if not set. + if config.SCK == 0 && config.MOSI == 0 && config.MISO == 0 { + config.SCK = SPI0_SCK_PIN + config.MOSI = SPI0_MOSI_PIN + config.MISO = SPI0_MISO_PIN + } + + // Enable pins for SPI. + sckBits := uint32(kendryte.FPIOA_IO_OE_EN | kendryte.FPIOA_IO_DS_Msk) + dataBits := uint32(kendryte.FPIOA_IO_OE_EN | kendryte.FPIOA_IO_OE_INV | kendryte.FPIOA_IO_IE_EN | + kendryte.FPIOA_IO_IE_INV | kendryte.FPIOA_IO_ST | kendryte.FPIOA_IO_DS_Msk) + + // Enable APB2 clock. + kendryte.SYSCTL.CLK_EN_CENT.SetBits(kendryte.SYSCTL_CLK_EN_CENT_APB2_CLK_EN) + + var fpioaFuncSclk uint32 + var fpioaFuncD0 uint32 + var fpioaFuncD1 uint32 + + switch spi.Bus { + case kendryte.SPI0: + // Initialize FPIOA values. + fpioaFuncSclk = fpioaFuncSpi0Sclk + fpioaFuncD0 = fpioaFuncSpi0D0 + fpioaFuncD1 = fpioaFuncSpi0D1 + + // Initialize SPI clock. + kendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_SPI0_CLK_EN) + kendryte.SYSCTL.CLK_TH1.ClearBits(kendryte.SYSCTL_CLK_TH1_SPI0_CLK_Msk) + case kendryte.SPI1: + // Initialize FPIOA values. + fpioaFuncSclk = fpioaFuncSpi1Sclk + fpioaFuncD0 = fpioaFuncSpi1D0 + fpioaFuncD1 = fpioaFuncSpi1D1 + + // Initialize SPI clock. + kendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_SPI1_CLK_EN) + kendryte.SYSCTL.CLK_TH1.ClearBits(kendryte.SYSCTL_CLK_TH1_SPI1_CLK_Msk) + default: + return ErrUnsupportedSPIController + } + + // Set FPIOA functins for selected pins. + kendryte.FPIOA.IO[uint8(config.SCK)].Set(uint32(sckBits | fpioaFuncSclk)) + kendryte.FPIOA.IO[uint8(config.MOSI)].Set(uint32(dataBits | fpioaFuncD0)) + kendryte.FPIOA.IO[uint8(config.MISO)].Set(uint32(dataBits | fpioaFuncD1)) + + // Set default frequency. + if config.Frequency == 0 { + config.Frequency = 500000 + } + + baudr := CPUFrequency() / config.Frequency + print(baudr) + spi.Bus.BAUDR.Set(baudr) + + // Configure SPI mode 0, standard frame format, 8-bit data, little-endian. + spi.Bus.IMR.Set(0) + spi.Bus.DMACR.Set(0) + spi.Bus.DMATDLR.Set(0x10) + spi.Bus.DMARDLR.Set(0) + spi.Bus.SER.Set(0) + spi.Bus.SSIENR.Set(0) + spi.Bus.CTRLR0.Set((7 << 16)) + spi.Bus.SPI_CTRLR0.Set(0) + spi.Bus.ENDIAN.Set(0) + + return nil +} + +// Transfer writes/reads a single byte using the SPI interface. +func (spi SPI) Transfer(w byte) (byte, error) { + spi.Bus.SSIENR.Set(0) + + // Set transfer-receive mode. + spi.Bus.CTRLR0.ClearBits(0x3 << 8) + + // Enable/disable SPI. + spi.Bus.SSIENR.Set(1) + defer spi.Bus.SSIENR.Set(0) + + // Enable/disable device. + spi.Bus.SER.Set(0x1) + defer spi.Bus.SER.Set(0) + + spi.Bus.DR0.Set(uint32(w)) + + // Wait for transfer. + for spi.Bus.SR.Get()&0x05 != 0x04 { + } + + // Wait for data. + for spi.Bus.RXFLR.Get() == 0 { + } + + return byte(spi.Bus.DR0.Get()), nil + +} diff --git a/src/machine/spi.go b/src/machine/spi.go index 2b022c41..51b18dd5 100644 --- a/src/machine/spi.go +++ b/src/machine/spi.go @@ -1,4 +1,4 @@ -// +build !baremetal sam stm32 fe310 +// +build !baremetal sam stm32 fe310 k210 package machine