STM32F103RB USART TX problem

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderator: RoccoMarco

Post Reply
mirtio
Posts: 4
Joined: Sun Nov 09, 2014 12:56 pm

STM32F103RB USART TX problem

Post by mirtio »

Hi

I'm using a STM32F103RB on an Olimexino STM32 board from Olimex and try to get USART TX working with no success so far. Some more details about my setup:

  • I use the Maple bootloader, so I changed the linkerscripts and VTOR accordingly and use the dfu-util to flash my software
  • I use the USB CDC example in my test program which works like a charm
  • I attached another USB <-> USART (FTDI FT232RL based) to the processors USART2 RX/TX pins.
  • On my computer I have two terminals open: One to communicate with the FTDI chip (which forwards to the STM32's USART2) and one to access the STM32's own USB CDC serial device.

In my program I forward characters received from USART2 to the SerialOverUSB connection. This works like a charm. However if I try to transmit something on USART2 nothing is happening at the TX pin PA2 (verified using an oscilloscope).
For the USART usage I copied the demo program and modified it accordingly to my board. Every time something is received or transmitted, the yellow LED on the board is flashed. This works correctly even though I don't see anything on the TX pin, so the callback functions are called correctly.

What could be the problem here? Could it be related to some initialization the Maple bootloader does? Unfortunately I don't have any debugger hardware.
I also tried using USART1 - it is the same there.

My code with respect to the USART2 is as follows:

Code: Select all

/*
 * UART Callback functions
 */
static VirtualTimer vt1, vt2;

static void restart(void *p) {

  (void)p;

  chSysLockFromIsr();
  uartStartSendI(&UARTD2, 14, "Hello World!\r\n");
  chSysUnlockFromIsr();
}

static void ledoff(void *p) {

  (void)p;
  palClearPad(GPIOA, GPIOA_YELLOW_LED);
}

/*
 * This callback is invoked when a transmission buffer has been completely
 * read by the driver.
 */
static void txend1(UARTDriver *uartp) {

  (void)uartp;
  palSetPad(GPIOA, GPIOA_YELLOW_LED);
}

/*
 * This callback is invoked when a transmission has physically completed.
 */
static void txend2(UARTDriver *uartp) {

  (void)uartp;
  palClearPad(GPIOA, GPIOA_YELLOW_LED);
  chSysLockFromIsr();
  if (chVTIsArmedI(&vt1))
    chVTResetI(&vt1);
   
  // Call restart() after given time
  chVTSetI(&vt1, MS2ST(50), restart, NULL);
  chSysUnlockFromIsr();
}

/*
 * This callback is invoked when a character is received but the application
 * was not ready to receive it, the character is passed as parameter.
 */
static void rxchar(UARTDriver *uartp, uint16_t c) {

  (void)uartp;
 
  // Forward character on to SDU1
  chprintf((BaseSequentialStream *)(&SDU1), "RECVD: %c\r\n", c);
 
  /* Flashing the LED each time a character is received.*/
  palSetPad(GPIOA, GPIOA_YELLOW_LED);
  chSysLockFromIsr();
  if (chVTIsArmedI(&vt2))
    chVTResetI(&vt2);
  chVTSetI(&vt2, MS2ST(200), ledoff, NULL);
  chSysUnlockFromIsr();
}

 
/*
 * UART driver configuration structure.
 */
static UARTConfig uart_cfg_2 = {
  txend1,
  txend2,
  NULL,
  rxchar,
  NULL,
  9600,
  0,
  0, //USART_CR2_LINEN,
  0
};

/*
 * Application entry point.
 */
int main(void) {
   
   /*
    * Early pad initialization
    */
   palSetPadMode(GPIOA, 2, PAL_MODE_STM32_ALTERNATE_PUSHPULL);      // USART2-TX
   palSetPadMode(GPIOA, 3, PAL_MODE_INPUT);                                 // USART2-RX
   
  /*
   * System initializations.
   * - HAL initialization, this also initializes the configured device drivers
   *   and performs the board-specific initializations.
   * - Kernel initialization, the main() function becomes a thread and the
   *   RTOS is active.
   */
  halInit();
  chSysInit();

  /*
   * Activates the uart driver 2 using the given configuration.
   */
  uartStart( &UARTD2, &uart_cfg_2 ); 

   /*
    * Start transmission on UART2
    */
   uartStartSend(&UARTD2, 13, "Starting...\r\n");

   /*
   * Normal main() thread activity, in this demo it does nothing except
   * sleeping in a loop.
   */
  while (TRUE) {
    chThdSleepMilliseconds(1000);
  }
}


P.S.: ChibiOS is a really great software. The examples and demos really helped me to get started quickly!
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: STM32F103RB USART TX problem

Post by Giovanni »

Hi,

The Serial driver is easier to use than the UART driver for simple applications (you don't need to deal with callbacks).

The problem that I can see in that code is that you are trying to access SDU1 from a callback, you can't do that, only I-class functions can be called from callbacks.

I recommend you read "kernel concepts" in the documentation and enable the "state check" debug option in chconf.h, it is able to detect such calling violations.

Giovanni
mirtio
Posts: 4
Joined: Sun Nov 09, 2014 12:56 pm

Re: STM32F103RB USART TX problem

Post by mirtio »

Hi Giovanni

thanks for the hint. The usage of SDU1 was just a quick hack to check if serial RX is working on USART2. It is however not the source of the problem.
I just removed the Maple bootloader and flashed the "bare" program via the STM32's hard-wired bootloader through USART1 (so the hardware must be functional) to check if the problem lies with using the Maple bootloader. The behaviour now, however, is exactly the same. Everything works apart from USART TX.

I will try to use the Serial driver as you suggested and report back.
mirtio
Posts: 4
Joined: Sun Nov 09, 2014 12:56 pm

Re: STM32F103RB USART TX problem

Post by mirtio »

Using the serial driver also does not work. What I tried was the bare minimum program

Code: Select all

#include "ch.h"
#include "hal.h"

/*
 * Green LED blinker thread, times are in milliseconds.
 */
static WORKING_AREA(waThread1, 128);
static msg_t Thread1(void *arg) {

  (void)arg;
  chRegSetThreadName("blinker");
  while (TRUE) {
    palClearPad(GPIOA, GPIOA_GREEN_LED);
    chThdSleepMilliseconds(500);
    palSetPad(GPIOA, GPIOA_GREEN_LED);
    chThdSleepMilliseconds(500);
  }
}

/*
 * Serial driver configuration structure.
 */
static SerialConfig ser_cfg = {
    9600,
    0,
    0,
    0
};

/*
 * Application entry point.
 */
int main(void) {
   
   /*
    * Early pad initialization
    */
   palSetPadMode(GPIOA, 9, PAL_MODE_STM32_ALTERNATE_PUSHPULL);      // USART1-TX
   palSetPadMode(GPIOA,10, PAL_MODE_INPUT);                                 // USART1-RX
   
  /*
   * System initializations.
   * - HAL initialization, this also initializes the configured device drivers
   *   and performs the board-specific initializations.
   * - Kernel initialization, the main() function becomes a thread and the
   *   RTOS is active.
   */
  halInit();
  chSysInit();

  /*
   * Activates the serial driver 2 using the driver default configuration.
   */
  sdStart(&SD1, &ser_cfg );
 
  /*
   * Creates the blinker thread.
   */
  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
   /*
   * Normal main() thread activity, in this demo it does nothing except
   * sleeping in a loop and sending a character over USART1.
   */
  while (TRUE) {
    sdPut(&SD1, 'A');
    chThdSleepMilliseconds(50);
  }

}


Nothing is sent over USART1. There is no change in voltage on Pin PA9. I must be missing something!
mirtio
Posts: 4
Joined: Sun Nov 09, 2014 12:56 pm

Re: STM32F103RB USART TX problem

Post by mirtio »

:oops:

It seems like halInit() or chSysInit() resets all ports to the default settings in board.h. So my pad configuration got overwritten. After changing the order of the function calls it works correctly...

I can't believe it took me almost 2 days to find this - I should get a debugger hardware...
kdsouza
Posts: 14
Joined: Thu Jul 02, 2015 3:26 pm
Has thanked: 1 time

Re: STM32F103RB USART TX problem

Post by kdsouza »

Hi!,

I am facing a similar problem with the STM32F072 Nucleo Board.

the UART example works well with UART1 but when i try to load UART1 and UART2 it doesn't do anything.

So i tried keeping only UART2 up and comment out UART1 but well, the UART2 output is coming on UART1,

Code: Select all

/*
    ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

#include "ch.h"
#include "hal.h"

/*
 * UART driver configuration structure.
 */
static UARTConfig uart_cfg_1 = {
  NULL, //txend1,
  NULL, //txend2,
  NULL, //rxend,
  NULL, //rxchar,
  NULL, //rxerr,
  800000,
  0,
  0, //USART_CR2_LINEN,
  0
};

static UARTConfig uart_cfg_2 = {
  NULL, //txend1,
  NULL, //txend2,
  NULL, //rxend,
  NULL, //rxchar,
  NULL, //rxerr,
  800000,
  0,
  0,
  0
};

/*
 * Application entry point.
 */
int main(void) {

  /*
   * System initializations.
   * - HAL initialization, this also initializes the configured device drivers
   *   and performs the board-specific initializations.
   * - Kernel initialization, the main() function becomes a thread and the
   *   RTOS is active.
   */
  halInit();
  chSysInit();

  /*
   * Activates the serial driver 1, PA9 and PA10 are routed to USART1.
   */


  palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(1));      /* USART1 TX.       */
  palSetPadMode(GPIOA, 10, PAL_MODE_ALTERNATE(1));    /* USART1 RX.       */
  palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(1));      /* USART2 TX.       */
  palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(1));      /* USART2 RX.       */

  //uartStart(&UARTD1, &uart_cfg_1);
    uartStart(&UARTD2, &uart_cfg_2);

  /*
   * Starts the transmission, it will be handled entirely in background.
   */
  //uartStartSend(&UARTD1, 13, "Starting...\r\n");
  uartStartSend(&UARTD2, 13, "Starting...\r\n");

  /*
   * Normal main() thread activity, in this demo it does nothing.
   */
  while (true) {
    chThdSleepMilliseconds(500);
    uartStartSend(&UARTD2, 7, "Soom!\r\n");
    //uartStartSend(&UARTD1, 7, "Boom!\r\n");
  }
}


Am I doing anything wron?

mcuconfig.h reads the following

Code: Select all

#define STM32_UART_USE_USART1               TRUE
#define STM32_UART_USE_USART2               TRUE
#define STM32_UART_USART1_IRQ_PRIORITY      3
#define STM32_UART_USART2_IRQ_PRIORITY      3
#define STM32_UART_USART1_DMA_PRIORITY      0
#define STM32_UART_USART2_DMA_PRIORITY      0
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: STM32F103RB USART TX problem

Post by Giovanni »

Hi,

Hard to believe that it comes out of another UART, the code looks correct. Are you sure that you are executing the right code? (compiled, flashed)

Giovanni
Post Reply