cancel
Showing results for 
Search instead for 
Did you mean: 

Nucleo-L4P5ZG LPUART not receiving nor transmitting

tomcat611
Visitor

Hi all! I am trying to communicate with the Nucleo-L4P5ZG via the LPUART1 peripheral over ST-LINK, however it doesn't seem to be transmitting or receiving anything. Following is my system clock initialization code (non-relevant parts cut out):

 

#pragma once
#include <stm32l4xx.h> 

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#define SYS_FREQUENCY 16000000

uint32_t SystemCoreClock;  // Required by CMSIS

static inline void clock_init(void) {
  SCB->CPACR |= 15 << 20;  // Enable FPU

  RCC->CR |= RCC_CR_HSION; // Set HSI on
  while (!(RCC->CR & RCC_CR_HSIRDY)) {}
  RCC->CFGR &= ~(RCC_CFGR_SW);
  RCC->CFGR |= RCC_CFGR_SW_HSI; // Set HSI as clock source
  while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) {};

  rng_init();  // Initialise random number generator
  RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;    // Enable SYSCFG
  SystemCoreClock = SYS_FREQUENCY;         // Required by CMSIS
}

void LPUART_Init(void) {
  // Enable LPUART clock
  RCC->APB1ENR2 |= RCC_APB1ENR2_LPUART1EN;
  spin(30); // Blocking wait
  // Set sysclock as LPUART clock source
  RCC->CCIPR |= 0x1 << 10;
  // Enable GPIO clock
  RCC->AHB2ENR |= RCC_AHB2ENR_GPIOGEN;
  spin(5); // Blocking wait
  // Configure GPIO pins
  GPIOG->MODER &= ~((0x3 << (8 * 2)) | (0x3 << (7 * 2)));
  GPIOG->MODER |= (0x2 << (8 * 2) | (0x2 << (7 * 2)));
  GPIOG->OTYPER &= ~((0x1 << 😎 | (0x1 << 7));
  // Set GPIOG pins 7 and 8 speed
  GPIOG->OSPEEDR &= ~((0x3 << (8*2)) | (0x3 << (7*2)));
  GPIOG->OSPEEDR |= ((0x2 << (8*2)) | (0x2 << (7*2)));
  // Set GPIOG pins 7 and 8 to alternate function 8
  GPIOG->AFR[0] &= ~((0xF << (7*4)));
  GPIOG->AFR[0] |= ((0b1000 << (7*4)));
  GPIOG->AFR[1] &= ~((0xF << ((8-8) * 4)));
  GPIOG->AFR[1] |= ((0b1000 << ((8-8) *4)));
  // Set baud rate
  LPUART1->BRR = ((SystemCoreClock) / 9600);
  // Enable tx
  LPUART1->CR1 |= 0x1 << 3;
  // Enable rx
  LPUART1->CR1 |= 0x1 << 2;
  // Enable LPUART
  LPUART1->CR1 |= 0x1;
  while ((LPUART1->ISR & USART_ISR_TEACK) == 0);
}

 

The first function above gets called by the CMSIS startup template, "cmsis_l4/Source/Templates/gcc/startup_stm32l4p5xx.s", which then calls my main():

 

int main(void) {
  // These are defined elsewhere and work fine
  gpio_output(LED_PIN);
  gpio_input(BTN_PIN);

  LPUART_Init();

  for (;;) {
    gpio_write(LED_PIN, true); // Defined elsewhere, this is reached and works
    while(!(LPUART1->ISR & USART_ISR_RXNE_RXFNE)) {};
    rxb = LPUART1->RDR;
    gpio_write(LED_PIN, false); // Defined elsewhere, this is never reached

    while(!(LPUART1->ISR & USART_ISR_TXE_TXFNF)) {};
    LPUART1->TDR = rxb;
  }
  return 0;
}

 

The first `gpio_write` on line 9 above is reached and activates the on-board LED. I then run `screen -fn /dev/ttyACM0 9600` on the machine connected to the board (which is able to program the board, ruling out the USB) and press some keys. The LED never goes off, which means line 12 is never reached, and, obviously, the byte is never echoed back to the terminal on the machine. Have I done anything obviously wrong? I can connect GDB via openOCD and I see that the registers are set appropriately, so it seems to either be an issue of me not setting the right parameters on initialization or the machine isn't communicating with the board correctly (however it is during programming?). Thanks very much in advance for any assistance!

1 REPLY 1
TDK
Guru

BRR seems wrong. See formula in the RM. You're setting it as if there are no fractional bits. Should be 256x what you have.

TDK_0-1721601870921.png

 

UE should be set before TE and RE.

 

Consider setting it up with HAL/CubeMX to see what the proper initialization settings and register values are.

If you feel a post has answered your question, please click "Accept as Solution".