cancel
Showing results for 
Search instead for 
Did you mean: 

Generate and use an STM32 Hal library, can't override __io_putchar

YohannDrc
Associate III

Hi everyone,

I am currently trying to create a library from STM32 Hal driver (Name of this project is Nucleol073rzHalTest).
The aim for this library is to contain all pin configuration to be used in other projetcs.
For this I simply create a stm32 executable project with the desire board/micro and configure pin.
I then convert this project to library (by changing the type of project from "Executable" to "Static Library' and the output file extension from "elf" to "a"),
and call the function "main_app" in the main in order I call define it in other projects.
(I keep the .IOS file in order to modify at demand the pin configuration, but delete .ld and .s files which will depend on executable project)

I then create another stm32 project (or simple C/C++ project) executable project which will use this library (Name of this project is SandboxHal or SandBoxHalTest for the simple C/C++ project).
I add the path to search the library, and necessary header files from the library.
I delete the ioc file, source and driver files in the stm32 project because they are already compiled in the previous library.
I create my own c++ file and define in it the "main_app" function which simply toggle a led and print messages.

It works well (after some adjustement) and I can control the led on the demo board.
However when it comes to overwrite the function __io_putchar in order to get the uart output redirect to the terminal, I didn't suceed.
It works well in a standard project where all hal drivers are already in it, but not for my projects which are linked to the previous library.

In debug, the code doesn't stop into the function __io_putchar if I add breakpoint.
And __io_putchar is added in the section "Discarded input sections" in the map file after compilation for both the STM32 Executable project and the simple C/C++ Executable project.
I don't know why.

I can't succeed to get this function works in this situation, do you have suggestion about it ?

STM32CubeIDE version : Version: 1.13.2
Board used: Nucleo-L073rz

Here the code, and project view:

capture code test use hal library.png

1 ACCEPTED SOLUTION

Accepted Solutions
YohannDrc
Associate III

I finally found out a solution.
In order the project use the good HAL_UART_MspInit.
I had to generate peripheral initialization as a pair of '.c/.h' files for each peripheral.
It can simply be done by checking a box in the .ioc file of the library.
Prject Manager > Code Generator > Check the box "Generate peripheral initialization as a pair of '.c/.h' files per peripheral"

YohannDrc_0-1706006948724.png

 

View solution in original post

12 REPLIES 12
gbm
Lead III

Remove __attribute__ ((weak)) - it is and should be used only with the default empty definition. If you provide a definition, it must be normal symbol, not weak.

Thanks for your reponse.

I remove __attribute__ ((weak)) but it doesn't change anything.

YohannDrc
Associate III

I had to override the function _write to get into the __io_putchar function.

This function is normally defined in the Nucleol073rzHalTest via the syscalls.c files, but I the file doesn't seem to be taken into account.

extern "C" int _write(int file, char *ptr, int len);
int _write(int file, char *ptr, int len)
{
    int DataIdx;

    for (DataIdx = 0; DataIdx < len; DataIdx++)
    {
        __io_putchar(*ptr++);
    }
    return len;
}


I also notice some errors which appear only during the first compilation:
(_write is no more in compilation error thanks to the previous definition)

Capture erreur.png

So now I enter the __io_putchar function when I call printf. 
But I can't get something appear in the terminal.
Whereas it works whith other other projects, so the terminal and uart used are OK.

KDJEM.1
ST Employee

Hello @YohannDrc and welcome to the Community 🙂,

Concerning the built errors issue, could you please try to downgrade the toolchain version to the GCC10.

For more details, take a look at this post.

I hope this help you.

Thank you.

Kaouthar

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hi KDJEM.1, thank you.

I tried to downgrade and use the gnu toolchain 10 2021.10 in my current projects.

But I now have this message :

arm-none-eabi-g++: error: unrecognized command-line option '-fcyclomatic-complexity'

Problème compilation gnu toolchain 10.png

KDJEM.1
ST Employee

Hi @YohannDrc ,

Thank you for updating the post.

Could you please check the Cyclomatic Complexity functionality.

KDJEM1_0-1700046946592.png

For more, details please refer to UM2609 Section 10. Cyclomatic complexity.

Thank you.

Kaouthar

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

So I uncheck the Cyclomatic Complexity functionality and I can no compile without error message.

But still I didn't get any message print in the console.
I tried just by calling 
HAL_UART_Transmit, but it doesn't print anything either.

extern "C" void main_app();
void main_app()
{
    while (1)
    {
    	uint8_t ch = 'a';
    	HAL_UART_Transmit(&huart2, &ch, 1, HAL_MAX_DELAY);
    	HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);	// Works well
    	HAL_Delay(1000);				// Works well
    }
}




Is huart2 passed from your main code and suitably initialized? Check structure, RCC, GPIO, UART2 registers.

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

Sorry for the delay

yes the huart2 is instanciated and initialized in the main.c file of the Nucleol073rzHalTest library.
I didn't make any change in the generated main.c file except the call of main_app function in the main function.

Main code of the library:

 

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  void main_app(void);
	  main_app();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

 


Instanciation of huart2:

 

/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart2;

 

Initialization for uart2 instance:

 

static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */

}

 

In the map file of the application which include the library,  here are the information about the huart2 instance

 

Archive member included to satisfy reference by file (symbol)

PathOfMyProject/Projects/appSandboxHal/../libNucleol073rzHalTest/Debug\libNucleol073rzHalTest.a(main.o)
                              ./Core/Src/main_sandbox_hal.o (huart2) 

*(.bss*)
 .bss.huart2    0x20000028       0x88 PathOfMyProject/Projects/appSandboxHal/../libNucleol073rzHalTest/Debug\libNucleol073rzHalTest.a(main.o)
                0x20000028                huart2

 

 

I don't know what to check about structure, RCC, GPIO, UART2 registers