STM32/GD32 F103 can't configure PA14 pin
Hello,
I'm using a fake STM32(GD32F103RET6) and having trouble figuring out why I can't change the PA14 pin from being an output pin. As far as the datasheet states it is one of the Serial wire debug pins and before configuring it one must enable AFIO Clock (set RCC APB2ENR AFIOEN bit to 1), likely wait at least a single clock cycle and then disable SWJ (set AFIO MARP SWJ_CFG value to 0b100).
The problem is that there is a single bit in the GPIOA CRH register that seems to not be changeable - MODE14 first bit. This causes the PA14 pin to always be Output. There is no issue when I write the same code in C, so I was wondering if the TinyGo runtime could cause something like this, or maybe I'm just overlooking something.
Here is a simplified code snippet (written to match equivalent C code):
package main
import (
"device/stm32"
"machine"
"strconv"
"time"
)
var (
OUTPUT = machine.PinConfig{Mode: machine.PinOutput}
INPUT_PULLUP = machine.PinConfig{Mode: machine.PinInputPullup}
INPUT_PULLUP_ANALOG = machine.PinConfig{Mode: machine.PinInputModeAnalog}
)
var Serial1 = machine.UART1
func __HAL_RCC_AFIO_CLK_ENABLE() {
stm32.RCC.SetAPB2ENR_AFIOEN(0b1)
time.Sleep(1 * time.Microsecond)
}
func __HAL_AFIO_REMAP_SWJ_DISABLE() {
stm32.AFIO.SetMAPR_SWJ_CFG(0b100)
}
func main() {
// These don't seem to do anything, PA14 can be configured without them?
__HAL_RCC_AFIO_CLK_ENABLE()
__HAL_AFIO_REMAP_SWJ_DISABLE()
machine.PA14.Configure(INPUT_PULLUP_ANALOG) // After configuration the register value is 0b0001, not 0b0000
Serial1.Configure(machine.UARTConfig{})
PrintCheck()
for {
loop()
}
}
func loop() {
time.Sleep(100 * time.Millisecond)
}
func PrintCheck() {
println("=================================")
println("RCC APB2ENR AFIOEN value:", strconv.FormatInt(int64(stm32.RCC.GetAPB2ENR_AFIOEN()), 2))
println("---------------------------------")
println("AFIO MAPR SWJ_CFG value:", strconv.FormatInt(int64(stm32.AFIO.GetMAPR_SWJ_CFG()), 2))
println("---------------------------------")
mode := strconv.FormatInt(int64(stm32.GPIOA.GetCRH_MODE14()), 2)
cnf := strconv.FormatInt(int64(stm32.GPIOA.GetCRH_CNF14()), 2)
println("GPIOA Pin PA14 MODE value:", mode)
println("GPIOA Pin PA14 CNF value:", cnf)
println("Pin PA14 value:", cnf+mode)
println("=================================")
}
I'm using TinyGo v0.37.0, compile for bluepill-clone target and optimizations are set to s (not sure if this is relevant or not).
Disabling JTAG doesn't seem to do anything, the pin seems to be configurable either way, both CRH_CNF14 bits and the second CRH_MODE14 bit seem to be configurable. I tried both just using the Configure(...) function and manually inputing register values like so:
crh := stm32.GPIOA.CRH.Get()
crh &^= 0xF << 24 // Clear bits 27:24 (PA14)
crh |= 0x8 << 24 // MODE14 = 0b00 (input), CNF14 = 0b10 (pull-up/pull-down)
stm32.GPIOA.CRH.Set(crh)
// After set, the received value is 0b1001, not 0b1000
Also if set to Output2MHz, the PA14 pin becomes Output50MHz (instead of having value 0b0010, it becomes 0b0011)