STM32 basic UART bare metal setup issue

I am new here, first post, so thanks in advance for being gentle with me 🙂
After spending weeks trying to make this work and searching examples/education/forum, i now reach out and hope someone is willing to help.

Goal:
Write simple program for an STM32G030K8 MCU for basic UART functionality. Transmit one char from PC, receive a hard-coded char from MCU.

The issue:
After sending a char, i do not receive any chars in return. Using hercules terminal tool and serial adapter.

The hardware (wiring, defects etc.) to transmit from MCU is verified, since i wrote a simple HAL-based program to transmit with success through ST Cube IDE. Therefore, i strongly suspect that the code is the issue. Also, i have no experience with debugging (i am a beginner programmer), so that is currently not an option.

PS. Using uKeil IDE and ST-LINK v2 programmer, c99.

#include "stm32g0xx.h"


void initClocks(void){
    //RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;        // ENABLE GPIO PORT A CLOCK (BIT 0)       ???     (I believe the next line replaces this one)
        RCC->IOPENR |= (1<<0);                                          // Enable GPIOA Clock                                   MCO
    RCC->APBENR2 |= RCC_APBENR2_USART1EN;       // ENABLE UART1 CLOCK (BIT 14)              ok
}


void configPinMode(void){
    // RESET PIN MODES
    GPIOA->MODER &= ~((3u << 18)    // CLEAR PA9                ok
                     |(3u << 20));  // CLEAR PA10               ok

    // SET PIN MODES
    GPIOA->MODER |= ((2u << 18)     // SET PA9 TO AF        ok
                    |(2u << 20));   // SET PA10 TO AF       ok
}


void setAF(void){
    // RESET ALTERNATE FUNCTION. AFR[1] IS THE
    // ALTERNATE FUNCTION HIGH REGISTER
    GPIOA->AFR[1] &= ~((15u << 4)       // CLEAR PA9 AF         ok
                      |(15u << 8));     // CLEAR PA10 AF        ok

    // SET ALTERNATE FUNCTION
    GPIOA->AFR[1] |= ((1u << 4)         // SET PA9 AF               not sure if position (high/low) register is ok (maybe AFR[1] is high and AFR[0] is low)
                     |(1u << 8));       // SET PA10 AF          not sure if position (high/low) register is ok (maybe AFR[1] is high and AFR[0] is low)
}


void configUart1Pins(void){
    // SET PIN MODE TO ALTERNATE FUNCTION
    configPinMode();

    // SET ALTERNATE FUNCTION TO BE UART1
    setAF();
}


void configUart1(void){
    // CONFIGURE USART1 CR1 REGISTER
    // CLEAR BITS
    USART1->CR1 &= ~(USART_CR1_M1       // CLEAR M1 FOR 1 START BIT AND 8 DATA BITS (28)                ok
                    |(0x03 << 26)       // INHIBIT INTERRUPTS AT BITS 26 AND 27     (27/26)         ok
                    |USART_CR1_OVER8    // OVERSAMPLING BY 16                       (15)                ok
                    |USART_CR1_CMIE     // INHIBIT CHARACTER MATCH INTERRUPT        (14)                ok
                    |USART_CR1_MME      // DON'T ENABLE MUTE MODE                   (13)                ok
                    |USART_CR1_M0       // CLEAR M0 FOR 1 START BIT AND 8 DATA BITS (12)                ok
                    |USART_CR1_PCE      // NOT IMPLEMENTING PARITY CONTROL          (10)                ok
                    |(0x1F << 3)        // INHIBIT INTERRUPTS AT BITS 4 TO 8        (4-8)               ok
                    |USART_CR1_TE       // DON'T ENABLE TRANSMITTER JUST YET        (3)                 ok
                    |USART_CR1_RE       // DON'T ENABLE RECEIVER JUST YET           (2)                 ok
                    |USART_CR1_UE);     // DON'T ENABLE UART1 JUST YET              (0)                 ok

    // CONFIGURE USART CR2 REGISTER
    // CLEAR BITS
    USART1->CR2 &= ~(USART_CR2_RTOEN    // DISABLE RECEIVER TIMEOUT             (23)                        ok
                    |USART_CR2_ABREN    // NO AUTOMATIC BAUD RATE DETECTION     (20)                        ok
                    |USART_CR2_MSBFIRST // TRANSMIT/RECEIVE LSB FIRST           (19)                        ok
                    |(0x03 << 16)       // IDLE STATE HIGH FOR RX/TX PINS       (17/16)                 ok
                    |USART_CR2_SWAP     // DON'T SWAP FUNCTION OF RX/TX PINS    (15)                        ok
                    |USART_CR2_LINEN    // NO LIN MODE                          (14)                        ok
                    |(0x03 << 12)       // 1 STOP BIT                           (13/12)                 ok
                    |USART_CR2_CLKEN    // DON'T USE CLOCK WITH UART            (11)                        ok
                    |USART_CR2_LBDIE);  // NO LIN BREAK DETECTION INTERRUPT     (6)                         ok

    // CONFIGURE USART CR3 REGISTER
    // CLEAR BITS
    USART1->CR3 &= ~(USART_CR3_TCBGTIE  // NO TRANSMISSION COMPLETE BEFORE GUARD TIME INTERRUPT (24)                ok
                    |USART_CR3_DEM      // NO DRIVER ENABLE MODE                                (14)                ok
                    |(0x7F << 3)        // DISABLE VARIOUS IRRELEVANT MODES                     (9-3)               ok
                    |USART_CR3_IREN     // NO IrDA MODE                                         (1)                 ok
                    |USART_CR3_EIE);    // INHIBIT ERROR INTERRUPT                              (0)                 ok

    // SET BITS
    USART1->CR3 |= (USART_CR3_OVRDIS    // DISABLE OVERRUN FUNCTIONALITY (12)               ok
                   |USART_CR3_ONEBIT);  // USE ONE SAMPLE BIT METHOD     (11)               ok

    // SET BAUD RATE IN BRR REGISTER
    USART1->BRR |= (138<<4);            // Baudrate: Whole Number Part      16MHz/115200=138.8889       (Baudrate 115200)           MCO
        USART1->BRR |= (14<<0);                         // Baudrate: Fractional Part            0.8889*16=14.2224=14        (Oversampling 16)           MCO

    // ENABLE UART
    USART1->CR1 |= (USART_CR1_TE        // ENABLE TRANSMITTER (3)           ok
                   |USART_CR1_RE        // ENABLE RECEIVER    (2)           ok
                   |USART_CR1_UE);      // ENABLE UART1       (0)           ok

}


void initUART(void){
    // INITIALISE REQUIRED CLOCKS. MUST ALWAYS BE DONE FIRST
    // AS WITHOUT ENABLING THE CLOCKS THE PERIPHERALS CANNOT
    // BE CONFIGURED OR USED.
    initClocks();

    // CONFIGURE PINS FOR UART1
    configUart1Pins();

    // CONFIGURE UART1
    configUart1();
}


void transmitUart(uint8_t data){     // BYTE OF DATA TO BE TRANSMITTED
    // WAIT UNTIL TRANSMIT DATA REGISTER IS READY TO TAKE DATA
    // USART_ISR_TXE EXPANDS TO (1 << 7);
    while(!(USART1->ISR & (1<<7)));     // USART_ISR_TXE is not known, therefore bitmask is used instead

    // LOAD DATA TO TRANSMIT REGISTER
    USART1->TDR = data;
}


void transmitStrUart(char* str) // POINTER TO A STRING TO BE TRANSMITTED
{
    // WHILE NOT END OF STRING
    while(*str){
        // TRANSMIT CHARACTER THEN INCREMENT POINTER TO NEXT CHARACTER
        transmitUart(*str++);
    }
}


uint8_t receiveUart(void){
    uint8_t rxData = 0;

    // IF THERE IS DATA IN THE RECEIVE DATA REGISTER
    // USART_ISR_RXNE EXPANDS TO (1 << 5)
    if(USART1->ISR & (1<<5)){                               // USART_ISR_RXNE is not known, therefore bitmask is used instead
        // READ DATA FROM THE REGISTER
        rxData = USART1->RDR;
    }

    return rxData;
}

int main(void){
    
    //SET UP UART
    initUART();

    while(1){
        // IF DATA WAS RECEIVED
        if(receiveUart() > 0){
            //transmitStrUart("Character Receivednr");

            // TRANSMIT AN ARBITRARY 'U' (ASCII 85) OVER UART
            transmitUart(85);
        }
    }
}

Above code is strongly inspired by an example found online (hence the “ok” comments and alike).

Thanks in advance for your advice and help.

4

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật