I am trying to get usart0 to be able to send and receive characters, I have confirmed my hardware is setup correctly but for some reason I cant transmit or receive characters. I have placed all the code here. I am trying to access things from low level registers and I have confirmed that I can control the built in led. I am not sure if I missed anything in terms of what else needs to be setup for the USART, but I went through the atmel documentation and think I did all that it asked, if anyone could provide me some suggestions that would be great.
#include <stdint.h>
#include "core_cm3.h"
/* Base addresses for peripherals */
#define PIOA_BASE (0x400E0E00U)
#define PMC_BASE (0x400E0600U)
/* Peripheral instances */
#define PIOA ((PIO_TypeDef *)PIOA_BASE)
#define PMC ((PMC_TypeDef *)PMC_BASE)
#define ID_PIOA (11U)
#define ID_USART0 (17U)
void USART0_Init(uint32_t baudrate) {
// Step 1: Enable the peripheral clock for USART0
PMC->PMC_WPMR = (0x504D43 << 8);
PMC->PMC_PCER0 = (1 << ID_USART0); // Enable clock for USART0
// Step 2: Configure TX and RX pins (PA10 for TX, PA11 for RX, Peripheral A)
PIOA->PIO_WPMR = (0x50494F << 8); // disable write protect
PIOA->PIO_ABSR &= ~((1 <<10) | (1<<11)); // Select Peripheral A for USART0
PIOA->PIO_PDR |= (1 <<10) | (1<<11); // Disable GPIO control for PA10, PA11
USART0->US_WPMR = (0x555341 << 8); //disable write protect
// Step 3: Disable USART0 before configuration
USART0->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS;
// Step 4: Configure baud rate
uint32_t cd = SYSTEM_CLOCK / (16 * baudrate); // CD = MCK / (16 * baudrate)
USART0->US_BRGR = cd;
// Step 5: Configure USART0 mode
USART0->US_MR = US_MR_CHRL_8_BIT // 8-bit data
| US_MR_PAR_NO // No parity
| US_MR_NBSTOP_1_BIT // 1 stop bit
| US_MR_CHMODE_NORMAL; // Normal mode (not loopback or test)
// Step 6: Enable the receiver and transmitter
USART0->US_CR = US_CR_RXEN | US_CR_TXEN;
}
void USART0_SendChar(char c) {
// Wait for the transmitter to be ready
while (!(USART0->US_CSR & US_CSR_TXRDY));
USART0->US_THR = c; // Write character to Transmit Holding Register
}
char USART0_ReceiveChar() {
// Wait for a character to be received
while (!(USART0->US_CSR & US_CSR_RXRDY));
return USART0->US_RHR; // Read character from Receive Holding Register
}
int main(void)
{
PMC->PMC_WPMR = (0x504D43 << 8);
// Enable the clock for PIOA
PMC->PMC_PCER0 = (1 << ID_PIOA);
// Enable clock for PIOB
PMC->PMC_PCER0 = (1 << ID_PIOB);
/* Set FWS according to SYS_BOARD_MCKR configuration */
EFC0->EEFC_FMR = EEFC_FMR_FWS(4);
EFC1->EEFC_FMR = EEFC_FMR_FWS(4);
/* Initialize main oscillator */
if (!(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)) {
PMC->CKGR_MOR = SYS_CKGR_MOR_KEY_VALUE | SYS_BOARD_OSCOUNT |
CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN;
while (!(PMC->PMC_SR & PMC_SR_MOSCXTS)) {
}
}
/* Switch to 3-20MHz Xtal oscillator */
PMC->CKGR_MOR = SYS_CKGR_MOR_KEY_VALUE | SYS_BOARD_OSCOUNT |
CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL;
while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)) {
}
PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) |
PMC_MCKR_CSS_MAIN_CLK;
while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
}
/* Initialize PLLA */
PMC->CKGR_PLLAR = SYS_BOARD_PLLAR;
while (!(PMC->PMC_SR & PMC_SR_LOCKA)) {
}
/* Switch to main clock */
PMC->PMC_MCKR = (SYS_BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
}
/* Switch to PLLA */
PMC->PMC_MCKR = SYS_BOARD_MCKR;
while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
}
PMC->PMC_PCER0 = (1 << ID_PIOB);
USART0_Init(9600);
const char *message = "USART0 Initialized at 115200 baud.\r\n";
for (const char *p = message; *p; p++) {
USART0_SendChar(*p);
}
while (1)
{
char received = USART0_ReceiveChar(); // Wait for a character
USART0_SendChar(received); // Echo it back
}
return 0;
}