I am running standard CMSIS as released by ST with libc included and all the jazz. Here is the code that isn't working.
void __attribute__ ((constructor)) uart4_init() {
// Enable the clock for uart4
RCC->APB1ENR |= 1 << 19;
// Enable the clock for GPIO_C, which needs to be configured to pass-through UART4
RCC->AHB1ENR |= 1 << 2;
// Set up the GPIOC 11 and 10 pins for UART use
// Set to alternate function mode
GPIOC->MODER &= ~(0b1111 << 20);
GPIOC->MODER |= 0b1010 << 20;
// Finally set Alternate Function to UART4, to pass through the UART
GPIOC->AFR[1] &= ~(0b11111111 << 8);
GPIOC->AFR[1] |= 0b10001000 << 8;
// Set up the UART port for reasonable sending settings
// Here follows explanations on all bits set to 1:
// Enable the serial port
// Set to nine bits, so we have one to spare for parity
// (Leave default wakeup method, since unused?)
// Enable parity
// Enable odd parity (better at detecting speed mismatch)
// (Do not set parity error interrupt on)
// (Do not set transfer buffer empty interrupt on)
// (Do not set transmission complete, since that is DMA specific)
// (Do not set recieve buffer not empty interrupt on)
// (Do not set idle interrupt since we don't use it)
// (Do not enable transmitter until setup is fully done)
// (Do not enable reciever until setup is fully done)
// (Do not enable mute-mode, we don't use it)
// (Do not send a break character)
UART4->CR1 = 0b11011000000000; // Set everything up
// The confusing part, setting the baud rate, is in separate function
uart4_set_baud(b9600);
// Enable sending and receiving
UART4->CR1 |= 0b1100;
}
I have verified that RCC_APB1ENR bit 19 is set, but the control registers of UART4 don't seem to have any clock and thus don't take the assignments.
(gdb) print/x *0x40023840
$23 = 0x80000
After reading working code (HAL code, so practically obfuscated) and documentation I still cannot figure this out.
Edit: Cleaned up the code following old_timers advice. Should be a usable example now.
Edit2: Removed the interrupts to make more generally usable as base example. Especially since those interrupt bits also net you to enable the UART interrupts through NVIC.
After some guided disassembling (Thanks old_timer!) I have now concluded that I am reading from the wrong addresses in my debugging, so the things I thought weren't working were working all along.
Is essence I read from 0x40024c00 when UART4 is at 0x40004c00...
After checking correcting that I find that CR1 does take the value of 0x37a0 that I have written in binary (and becomes 0x37ac when enabled) and that BRR takes the expected value of 1666 (which should be 9600 baud, if I understood the documentation right...).
After that I can check the status register after sending a test byte to the card and conclude that I have received data and validate that to check that my baud is close enough, so it is working now (enough for continued testing).