Loading...
 

SW4STM32 and SW4Linux fully supports the STM32MP1 asymmetric multicore Cortex/A7+M4 MPUs

   With System Workbench for Linux, Embedded Linux on the STM32MP1 family of MPUs from ST was never as simple to build and maintain, even for newcomers in the Linux world.
And, if you install System Workbench for Linux in System Workbench for STM32 you can seamlessly develop and debug asymmetric applications running partly on Linux, partly on the Cortex-M4.
You can get more information from the ac6-tools website and download two short videos (registration required) highlighting:

System Workbench for STM32


Redirecting printf with a custom, non-global, callback

On an AVR microcontroller, I do this:

int printCHAR(char character, FILE *stream)
{
BOARD_TypeDef_t* udata = (BOARD_TypeDef_t*) fdev_get_udata(stream);
display_write(&udata->display[displayA], character);
return 0;
}

void main()
{
/* Declare BOARD typedef. */
BOARD_TypeDef_t board;

/* Initialize BOARD typedef. */
board_init(&board);

/* Initialize display */
display_init(&board.display[displayA]);

FILE uart_str = FDEV_SETUP_STREAM(printCHAR, NULL, _FDEV_SETUP_RW);
fdev_setup_stream(&uart_str, printCHAR, NULL, _FDEV_SETUP_RW);
fdev_set_udata(&uart_str, &board);
stdout = &uart_str;

printf(“%s”, “ABC”);
}

This prints the letters “ABC” on the memory lcd via the display_write function in printCHAR, with the non-global parameter &udata->display[displayA].

I’d like to achieve something similar on an STM32 microcontroller (on the G071RB Nucleo board) to which an spi display is attached. The FDEV set of functions appear to be customized, lightweight workarounds for the avr-libc library and are hence unavailable for STM32 processors.

For now, my main on the STM32 looks something like this:

void main(void)
{
/* Declare BOARD typedef. */
BOARD_TypeDef_t board;

/* Initialize BOARD typedef. */
board_init(&board);

/* Initialize display */
display_init(&board.display[displayA]);

/* Writes a “B” to the display */
display_write(&board.display[displayA], 0x42);
}

What I would like to do is to use my display_write function and the display destination in a retargetted printf.

The options I have seen are:

1. Using __io_putchar function: This is available to be externed from the syscalls.c file. However, the only parameter it takes is the character to be printed, so I’m not sure and don’t think I can get my BOARD_TypeDef_t in there.

2. Using write function: This is available in the syscalls.c file. However, I would rather use this the canonical way via __io_putchar and not by directly editing the write function.

3. Using fopencookie: I think this is the way I would like to do this but I’m having some difficulty, with my cookie_write_function_t function defined inside of the cookie_io_functions_t array of functions not getting called at all but rather getting fwrite being called instead. That quickly degenerates into nothing getting printed to the spi display. However, subsequent calls via the display_write primitive do continue to print to the spi display.

Also, it would be good to know if this could be achieved perhaps with fputc or some other way.

Any ideas of what I might be doing wrong, or guidance on how I might do this right, are appreciated.

Regards,
J

France

Hi,

The simplest way to go is through __io_putchar that you can define, e.g. in the file in which you place the display initialization code, as it is declared as weak in syscalls.c. To print on your display you can write it as
int __io_putchar(char c) {
    return display_write(&board.display[displayA], c); 
}

For this to work, of course, you must declare the board variable as a global static variable (not in the display initialization function) and move the display_init (and perhaps board_init) call in the display initialization function.

Then any printf/write with go to your display

HTH

Bernard (Ac6)

Hi,

Thanks for the suggestion.

A key requirement is that there are no global variables and this proposal suggests one. Thanks.

Regards,
J