cancel
Showing results for 
Search instead for 
Did you mean: 

Nucleo-L4P5ZG LPUART not receiving nor transmitting

tomcat611
Associate

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!

3 REPLIES 3
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".

For GPIOG you must enable VDDIO via PWR

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
tomcat611
Associate

Thank you both @Tesla DeLorean and @TDK, following both of your advice let me to getting some kind of input! My updated LPUART initialization code:

 

void LPUART_Init(void) {
  RCC->APB1ENR1 |= RCC_APB1ENR1_PWREN;
  spin(30);
  PWR->CR2 |= 0x1 << 9;
  spin(30);
  // Enable LPUART clock
  RCC->APB1ENR2 |= RCC_APB1ENR2_LPUART1EN;
  spin(30);
  RCC->CCIPR |= 0x1 << 10;
  // Initialize GPIO pin
  gpio_init(PIN('G', 7), GPIO_MODE_AF, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH, GPIO_PULL_UP, 0b1000);
  gpio_init(PIN('G', 8), GPIO_MODE_AF, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH, GPIO_PULL_UP, 0b1000);
  // Enable GPIO clock
  RCC->AHB2ENR |= RCC_AHB2ENR_GPIOGEN;
  spin(30);
  // Configure LPUART controller
  LPUART1->CR1 &= ~USART_CR1_UE; // Disable LPUART
  // Set the baud rate
  //uint16_t uartdiv = SystemCoreClock / 9600;
  //LPUART1->BRR = uartdiv;
  LPUART1->BRR = ((256 * SystemCoreClock) / 9600);
  // Leave all interrupts disabled

  // Enable LPUART
  LPUART1->CR1 |= 0x1;
  spin(20);

  // Enable tx
  LPUART1->CR1 |= 0x1 << 3;

  // Enable rx
  LPUART1->CR1 |= 0x1 << 2;

  while ((LPUART1->ISR & USART_ISR_TEACK) == 0);
}

And the updated code that sends a character (note that I've changed this to send a constant char on button press):

if(gpio_read(BTN_PIN) != 0) {
    gpio_write(LED_PIN, true);
    LPUART1->TDR = 'h';
    while(!(LPUART1->ISR & USART_ISR_TXE_TXFNF)) {};
} else {
    gpio_write(LED_PIN, false);
}

Upon starting screen on my computer the same way as before, I get a stream of ">" characters whenever I press the button on the board. I tried changing the char sent by the board to 'r', which changed the character appearing in the terminal to a stream of "�" preceeded by a single "0". I thought this was due to a mismatch between the frames that the tty was expecting and what the board was sending, so I fiddled with stty options by "stty -F /dev/ttyACM0 -cstopb -parenb -clocal cs8". This sets the tty to expect the same as the default LPUART registers - 1 stop bit, 8 data bits, no parity bits. This didn't change anything, however 🙂 I'm left thinking that my baud rate must still not be set correctly, but I cannot see what would be wrong (after correcting the error that @TDK pointed out).