stm32: i2c implementation for F7, L5 and L4 MCUs
Этот коммит содержится в:
родитель
9f3dcf3733
коммит
46a7993fb8
12 изменённых файлов: 421 добавлений и 9 удалений
|
@ -54,6 +54,15 @@ const (
|
||||||
|
|
||||||
// I2C pins
|
// I2C pins
|
||||||
const (
|
const (
|
||||||
SCL_PIN = PB6
|
I2C0_SCL_PIN = PB8
|
||||||
SDA_PIN = PB7
|
I2C0_SDA_PIN = PB9
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// I2C1 is documented, alias to I2C0 as well
|
||||||
|
I2C1 = &I2C{
|
||||||
|
Bus: stm32.I2C1,
|
||||||
|
AltFuncSelector: 4,
|
||||||
|
}
|
||||||
|
I2C0 = I2C1
|
||||||
)
|
)
|
||||||
|
|
|
@ -22,8 +22,9 @@ const (
|
||||||
|
|
||||||
// I2C pins
|
// I2C pins
|
||||||
const (
|
const (
|
||||||
// PB6 and PB7 are mapped to CN4 pin 7 and CN4 pin 8 respectively with the
|
// With default solder bridge settings:
|
||||||
// default solder bridge settings
|
// PB6 / Arduino D5 / CN3 Pin 8 is SCL
|
||||||
|
// PB7 / Arduino D4 / CN3 Pin 7 is SDA
|
||||||
I2C0_SCL_PIN = PB6
|
I2C0_SCL_PIN = PB6
|
||||||
I2C0_SDA_PIN = PB7
|
I2C0_SDA_PIN = PB7
|
||||||
)
|
)
|
||||||
|
@ -41,6 +42,15 @@ var (
|
||||||
UART1 = &UART0
|
UART1 = &UART0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// I2C1 is documented, alias to I2C0 as well
|
||||||
|
I2C1 = &I2C{
|
||||||
|
Bus: stm32.I2C1,
|
||||||
|
AltFuncSelector: 4,
|
||||||
|
}
|
||||||
|
I2C0 = I2C1
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
UART0.Interrupt = interrupt.New(stm32.IRQ_USART2, UART0.handleInterrupt)
|
UART0.Interrupt = interrupt.New(stm32.IRQ_USART2, UART0.handleInterrupt)
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,20 @@ var (
|
||||||
UART1 = &UART0
|
UART1 = &UART0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
I2C0_SCL_PIN = PB8
|
||||||
|
I2C0_SDA_PIN = PB9
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// I2C1 is documented, alias to I2C0 as well
|
||||||
|
I2C1 = &I2C{
|
||||||
|
Bus: stm32.I2C1,
|
||||||
|
AltFuncSelector: 4,
|
||||||
|
}
|
||||||
|
I2C0 = I2C1
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
UART0.Interrupt = interrupt.New(stm32.IRQ_LPUART1, UART0.handleInterrupt)
|
UART0.Interrupt = interrupt.New(stm32.IRQ_LPUART1, UART0.handleInterrupt)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// +build avr nrf sam stm32,!stm32f7x2,!stm32l5x2,!stm32l0,!stm32l4x2 fe310 k210
|
// +build avr nrf sam stm32,!stm32l0 fe310 k210
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
// +build stm32,!stm32f7x2,!stm32l5x2,!stm32l0,!stm32l4x2
|
// +build stm32f4 stm32f1
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
// Peripheral abstraction layer for I2C on the stm32 family
|
// I2C implementation for 'older' STM32 MCUs, including the F1 and F4 series
|
||||||
|
// of MCUs.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"device/stm32"
|
"device/stm32"
|
347
src/machine/machine_stm32_i2c_revb.go
Обычный файл
347
src/machine/machine_stm32_i2c_revb.go
Обычный файл
|
@ -0,0 +1,347 @@
|
||||||
|
// +build stm32l5 stm32f7 stm32l4
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/stm32"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname ticks runtime.ticks
|
||||||
|
func ticks() int64
|
||||||
|
|
||||||
|
// I2C implementation for 'newer' STM32 MCUs, including the F7, L5 and L4
|
||||||
|
// series of MCUs.
|
||||||
|
//
|
||||||
|
// Currently, only 100KHz mode is supported
|
||||||
|
|
||||||
|
const (
|
||||||
|
flagBUSY = stm32.I2C_ISR_BUSY
|
||||||
|
flagTCR = stm32.I2C_ISR_TCR
|
||||||
|
flagRXNE = stm32.I2C_ISR_RXNE
|
||||||
|
flagSTOPF = stm32.I2C_ISR_STOPF
|
||||||
|
flagAF = stm32.I2C_ISR_NACKF
|
||||||
|
flagTXIS = stm32.I2C_ISR_TXIS
|
||||||
|
flagTXE = stm32.I2C_ISR_TXE
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MAX_NBYTE_SIZE = 255
|
||||||
|
TIMEOUT_TICKS = 100 // 100ms
|
||||||
|
|
||||||
|
I2C_NO_STARTSTOP = 0x0
|
||||||
|
I2C_GENERATE_START_WRITE = 0x80000000 | stm32.I2C_CR2_START
|
||||||
|
I2C_GENERATE_START_READ = 0x80000000 | stm32.I2C_CR2_START | stm32.I2C_CR2_RD_WRN
|
||||||
|
I2C_GENERATE_STOP = 0x80000000 | stm32.I2C_CR2_STOP
|
||||||
|
)
|
||||||
|
|
||||||
|
type I2C struct {
|
||||||
|
Bus *stm32.I2C_Type
|
||||||
|
AltFuncSelector uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// I2CConfig is used to store config info for I2C.
|
||||||
|
type I2CConfig struct {
|
||||||
|
SCL Pin
|
||||||
|
SDA Pin
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i2c I2C) Configure(config I2CConfig) error {
|
||||||
|
// disable I2C interface before any configuration changes
|
||||||
|
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_PE)
|
||||||
|
|
||||||
|
// enable clock for I2C
|
||||||
|
enableAltFuncClock(unsafe.Pointer(i2c.Bus))
|
||||||
|
|
||||||
|
// init pins
|
||||||
|
if config.SCL == 0 && config.SDA == 0 {
|
||||||
|
config.SCL = I2C0_SCL_PIN
|
||||||
|
config.SDA = I2C0_SDA_PIN
|
||||||
|
}
|
||||||
|
i2c.configurePins(config)
|
||||||
|
|
||||||
|
// Frequency range
|
||||||
|
i2c.Bus.TIMINGR.Set(i2c.getFreqRange())
|
||||||
|
|
||||||
|
// Disable Own Address1 before set the Own Address1 configuration
|
||||||
|
i2c.Bus.OAR1.ClearBits(stm32.I2C_OAR1_OA1EN)
|
||||||
|
|
||||||
|
// 7 bit addressing, no self address
|
||||||
|
i2c.Bus.OAR1.Set(stm32.I2C_OAR1_OA1EN)
|
||||||
|
|
||||||
|
// Enable the AUTOEND by default, and enable NACK (should be disable only during Slave process
|
||||||
|
i2c.Bus.CR2.Set(stm32.I2C_CR2_AUTOEND | stm32.I2C_CR2_NACK)
|
||||||
|
|
||||||
|
// Disable Own Address2 / Dual Addressing
|
||||||
|
i2c.Bus.OAR2.Set(0)
|
||||||
|
|
||||||
|
// Disable Generalcall and NoStretch, Enable peripheral
|
||||||
|
i2c.Bus.CR1.Set(stm32.I2C_CR1_PE)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i2c I2C) Tx(addr uint16, w, r []byte) error {
|
||||||
|
if len(w) > 0 {
|
||||||
|
if err := i2c.controllerTransmit(addr, w); nil != err {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(r) > 0 {
|
||||||
|
if err := i2c.controllerReceive(addr, r); nil != err {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i2c I2C) configurePins(config I2CConfig) {
|
||||||
|
config.SCL.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSCL}, i2c.AltFuncSelector)
|
||||||
|
config.SDA.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSDA}, i2c.AltFuncSelector)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i2c I2C) controllerTransmit(addr uint16, w []byte) error {
|
||||||
|
start := ticks()
|
||||||
|
|
||||||
|
if !i2c.waitOnFlagUntilTimeout(flagBUSY, false, start) {
|
||||||
|
return errI2CBusReadyTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
pos := 0
|
||||||
|
xferCount := len(w)
|
||||||
|
xferSize := uint8(xferCount)
|
||||||
|
if xferCount > MAX_NBYTE_SIZE {
|
||||||
|
// Large write, indicate reload
|
||||||
|
xferSize = MAX_NBYTE_SIZE
|
||||||
|
i2c.transferConfig(addr, xferSize, stm32.I2C_CR2_RELOAD, I2C_GENERATE_START_WRITE)
|
||||||
|
} else {
|
||||||
|
// Small write, auto-end
|
||||||
|
i2c.transferConfig(addr, xferSize, stm32.I2C_CR2_AUTOEND, I2C_GENERATE_START_WRITE)
|
||||||
|
}
|
||||||
|
|
||||||
|
for xferCount > 0 {
|
||||||
|
if !i2c.waitOnTXISFlagUntilTimeout(start) {
|
||||||
|
return errI2CWriteTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c.Bus.TXDR.Set(uint32(w[pos]))
|
||||||
|
pos++
|
||||||
|
xferCount--
|
||||||
|
xferSize--
|
||||||
|
|
||||||
|
// If we've written the last byte of this chunk
|
||||||
|
if xferCount != 0 && xferSize == 0 {
|
||||||
|
// Wait for Transfer Complete Reload to be flagged
|
||||||
|
if !i2c.waitOnFlagUntilTimeout(flagTCR, true, start) {
|
||||||
|
return errI2CWriteTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
if xferCount > MAX_NBYTE_SIZE {
|
||||||
|
// Large write remaining, indicate reload
|
||||||
|
xferSize = MAX_NBYTE_SIZE
|
||||||
|
i2c.transferConfig(addr, xferSize, stm32.I2C_CR2_RELOAD, I2C_NO_STARTSTOP)
|
||||||
|
} else {
|
||||||
|
// Small write, auto-end
|
||||||
|
xferSize = uint8(xferCount)
|
||||||
|
i2c.transferConfig(addr, xferSize, stm32.I2C_CR2_AUTOEND, I2C_NO_STARTSTOP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !i2c.waitOnStopFlagUntilTimeout(start) {
|
||||||
|
return errI2CWriteTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c.clearFlag(stm32.I2C_ISR_STOPF)
|
||||||
|
|
||||||
|
i2c.resetCR2()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i2c I2C) controllerReceive(addr uint16, r []byte) error {
|
||||||
|
start := ticks()
|
||||||
|
|
||||||
|
if !i2c.waitOnFlagUntilTimeout(flagBUSY, false, start) {
|
||||||
|
return errI2CBusReadyTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
pos := 0
|
||||||
|
xferCount := len(r)
|
||||||
|
xferSize := uint8(xferCount)
|
||||||
|
if xferCount > MAX_NBYTE_SIZE {
|
||||||
|
// Large read, indicate reload
|
||||||
|
xferSize = MAX_NBYTE_SIZE
|
||||||
|
i2c.transferConfig(addr, xferSize, stm32.I2C_CR2_RELOAD, I2C_GENERATE_START_READ)
|
||||||
|
} else {
|
||||||
|
// Small read, auto-end
|
||||||
|
i2c.transferConfig(addr, xferSize, stm32.I2C_CR2_AUTOEND, I2C_GENERATE_START_READ)
|
||||||
|
}
|
||||||
|
|
||||||
|
for xferCount > 0 {
|
||||||
|
if !i2c.waitOnRXNEFlagUntilTimeout(start) {
|
||||||
|
return errI2CWriteTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
r[pos] = uint8(i2c.Bus.RXDR.Get())
|
||||||
|
pos++
|
||||||
|
xferCount--
|
||||||
|
xferSize--
|
||||||
|
|
||||||
|
// If we've read the last byte of this chunk
|
||||||
|
if xferCount != 0 && xferSize == 0 {
|
||||||
|
// Wait for Transfer Complete Reload to be flagged
|
||||||
|
if !i2c.waitOnFlagUntilTimeout(flagTCR, true, start) {
|
||||||
|
return errI2CWriteTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
if xferCount > MAX_NBYTE_SIZE {
|
||||||
|
// Large read remaining, indicate reload
|
||||||
|
xferSize = MAX_NBYTE_SIZE
|
||||||
|
i2c.transferConfig(addr, xferSize, stm32.I2C_CR2_RELOAD, I2C_NO_STARTSTOP)
|
||||||
|
} else {
|
||||||
|
// Small read, auto-end
|
||||||
|
xferSize = uint8(xferCount)
|
||||||
|
i2c.transferConfig(addr, xferSize, stm32.I2C_CR2_AUTOEND, I2C_NO_STARTSTOP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !i2c.waitOnStopFlagUntilTimeout(start) {
|
||||||
|
return errI2CWriteTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c.clearFlag(stm32.I2C_ISR_STOPF)
|
||||||
|
|
||||||
|
i2c.resetCR2()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i2c I2C) waitOnFlagUntilTimeout(flag uint32, set bool, startTicks int64) bool {
|
||||||
|
for i2c.hasFlag(flag) != set {
|
||||||
|
if (ticks() - startTicks) > TIMEOUT_TICKS {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i2c I2C) waitOnRXNEFlagUntilTimeout(startTicks int64) bool {
|
||||||
|
for !i2c.hasFlag(flagRXNE) {
|
||||||
|
if i2c.isAcknowledgeFailed(startTicks) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if i2c.hasFlag(flagSTOPF) {
|
||||||
|
i2c.clearFlag(flagSTOPF)
|
||||||
|
i2c.resetCR2()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ticks() - startTicks) > TIMEOUT_TICKS {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i2c I2C) waitOnTXISFlagUntilTimeout(startTicks int64) bool {
|
||||||
|
for !i2c.hasFlag(flagTXIS) {
|
||||||
|
if i2c.isAcknowledgeFailed(startTicks) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ticks() - startTicks) > TIMEOUT_TICKS {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i2c I2C) waitOnStopFlagUntilTimeout(startTicks int64) bool {
|
||||||
|
for !i2c.hasFlag(flagSTOPF) {
|
||||||
|
if i2c.isAcknowledgeFailed(startTicks) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ticks() - startTicks) > TIMEOUT_TICKS {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i2c I2C) isAcknowledgeFailed(startTicks int64) bool {
|
||||||
|
if i2c.hasFlag(flagAF) {
|
||||||
|
// Wait until STOP Flag is reset
|
||||||
|
// AutoEnd should be initiate after AF
|
||||||
|
for !i2c.hasFlag(flagSTOPF) {
|
||||||
|
if (ticks() - startTicks) > TIMEOUT_TICKS {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c.clearFlag(flagAF)
|
||||||
|
i2c.clearFlag(flagSTOPF)
|
||||||
|
i2c.flushTXDR()
|
||||||
|
i2c.resetCR2()
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i2c I2C) flushTXDR() {
|
||||||
|
// If a pending TXIS flag is set, write a dummy data in TXDR to clear it
|
||||||
|
if i2c.hasFlag(flagTXIS) {
|
||||||
|
i2c.Bus.TXDR.Set(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush TX register if not empty
|
||||||
|
if !i2c.hasFlag(flagTXE) {
|
||||||
|
i2c.clearFlag(flagTXE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i2c I2C) resetCR2() {
|
||||||
|
i2c.Bus.CR2.ClearBits(stm32.I2C_CR2_SADD_Msk |
|
||||||
|
stm32.I2C_CR2_HEAD10R_Msk |
|
||||||
|
stm32.I2C_CR2_NBYTES_Msk |
|
||||||
|
stm32.I2C_CR2_RELOAD_Msk |
|
||||||
|
stm32.I2C_CR2_RD_WRN_Msk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i2c I2C) transferConfig(addr uint16, size uint8, mode uint32, request uint32) {
|
||||||
|
mask := uint32(stm32.I2C_CR2_SADD_Msk |
|
||||||
|
stm32.I2C_CR2_NBYTES_Msk |
|
||||||
|
stm32.I2C_CR2_RELOAD_Msk |
|
||||||
|
stm32.I2C_CR2_AUTOEND_Msk |
|
||||||
|
(stm32.I2C_CR2_RD_WRN & uint32(request>>(31-stm32.I2C_CR2_RD_WRN_Pos))) |
|
||||||
|
stm32.I2C_CR2_START_Msk |
|
||||||
|
stm32.I2C_CR2_STOP_Msk)
|
||||||
|
|
||||||
|
value := (uint32(addr<<1) & stm32.I2C_CR2_SADD_Msk) |
|
||||||
|
((uint32(size) << stm32.I2C_CR2_NBYTES_Pos) & stm32.I2C_CR2_NBYTES_Msk) |
|
||||||
|
mode | request
|
||||||
|
|
||||||
|
i2c.Bus.CR2.ReplaceBits(value, mask, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i2c I2C) hasFlag(flag uint32) bool {
|
||||||
|
return i2c.Bus.ISR.HasBits(flag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i2c I2C) clearFlag(flag uint32) {
|
||||||
|
if flag == stm32.I2C_ISR_TXE {
|
||||||
|
i2c.Bus.ISR.SetBits(flag)
|
||||||
|
} else {
|
||||||
|
i2c.Bus.ICR.SetBits(flag)
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,3 +41,13 @@ func (uart *UART) setRegisters() {
|
||||||
uart.statusReg = &uart.Bus.ISR
|
uart.statusReg = &uart.Bus.ISR
|
||||||
uart.txEmptyFlag = stm32.USART_ISR_TXE
|
uart.txEmptyFlag = stm32.USART_ISR_TXE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------- I2C related code
|
||||||
|
|
||||||
|
// Gets the value for TIMINGR register
|
||||||
|
func (i2c I2C) getFreqRange() uint32 {
|
||||||
|
// This is a 'magic' value calculated by STM32CubeMX
|
||||||
|
// for 27MHz PCLK1 (216MHz CPU Freq / 8).
|
||||||
|
// TODO: Do calculations based on PCLK1
|
||||||
|
return 0x00606A9B
|
||||||
|
}
|
||||||
|
|
|
@ -34,3 +34,13 @@ func (uart *UART) setRegisters() {
|
||||||
uart.statusReg = &uart.Bus.ISR
|
uart.statusReg = &uart.Bus.ISR
|
||||||
uart.txEmptyFlag = stm32.USART_ISR_TXE
|
uart.txEmptyFlag = stm32.USART_ISR_TXE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------- I2C related code
|
||||||
|
|
||||||
|
// Gets the value for TIMINGR register
|
||||||
|
func (i2c I2C) getFreqRange() uint32 {
|
||||||
|
// This is a 'magic' value calculated by STM32CubeMX
|
||||||
|
// for 80MHz PCLK1.
|
||||||
|
// TODO: Do calculations based on PCLK1
|
||||||
|
return 0x10909CEC
|
||||||
|
}
|
||||||
|
|
|
@ -39,3 +39,13 @@ func (uart *UART) setRegisters() {
|
||||||
uart.statusReg = &uart.Bus.ISR
|
uart.statusReg = &uart.Bus.ISR
|
||||||
uart.txEmptyFlag = stm32.USART_ISR_TXE
|
uart.txEmptyFlag = stm32.USART_ISR_TXE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------- I2C related code
|
||||||
|
|
||||||
|
// Gets the value for TIMINGR register
|
||||||
|
func (i2c I2C) getFreqRange() uint32 {
|
||||||
|
// This is a 'magic' value calculated by STM32CubeMX
|
||||||
|
// for 110MHz PCLK1.
|
||||||
|
// TODO: Do calculations based on PCLK1
|
||||||
|
return 0x40505681
|
||||||
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ func nanosecondsToTicks(ns int64) timeUnit {
|
||||||
}
|
}
|
||||||
|
|
||||||
// number of ticks (microseconds) since start.
|
// number of ticks (microseconds) since start.
|
||||||
|
//go:linkname ticks runtime.ticks
|
||||||
func ticks() timeUnit {
|
func ticks() timeUnit {
|
||||||
return timeUnit(tickCount.Get())
|
return timeUnit(tickCount.Get())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"inherits": ["cortex-m"],
|
"inherits": ["cortex-m"],
|
||||||
"llvm-target": "armv7m-none-eabi",
|
"llvm-target": "armv7m-none-eabi",
|
||||||
"build-tags": ["bluepill", "stm32f103", "stm32"],
|
"build-tags": ["bluepill", "stm32f103", "stm32f1", "stm32"],
|
||||||
"cflags": [
|
"cflags": [
|
||||||
"--target=armv7m-none-eabi",
|
"--target=armv7m-none-eabi",
|
||||||
"-Qunused-arguments"
|
"-Qunused-arguments"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"inherits": ["cortex-m"],
|
"inherits": ["cortex-m"],
|
||||||
"llvm-target": "armv7m-none-eabi",
|
"llvm-target": "armv7m-none-eabi",
|
||||||
"build-tags": ["nucleof103rb", "stm32f103", "stm32"],
|
"build-tags": ["nucleof103rb", "stm32f103", "stm32f1","stm32"],
|
||||||
"cflags": [
|
"cflags": [
|
||||||
"--target=armv7m-none-eabi",
|
"--target=armv7m-none-eabi",
|
||||||
"-Qunused-arguments"
|
"-Qunused-arguments"
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче