Preferred version of STM32Cube (not CubeMX) for use with FreeRTOS-Plus-TCP on STM32F427?

galens wrote on Friday, October 11, 2019:

Hi,

Up to this point, I have been using FreeRTOS on an STM32F427 with no issues. I’ve been using the register definitions from STM32Cube (V1.21.0), but none of the HAL or low level code. Now I have the need for ethernet communications, so I will need to start using some of the HAL code. Given the following versions, can someone tell me what is the minimum and/or preferred version of STM32Cube I should be using? It looks like the latest STM32Cube version for the F4 parts is V1.24.1, which was released in April of 2019. The last change to the TCP code appears to be changeset 2681 on 2019-07-14. Should I be using STM32Cube V1.24.1?

FreeRTOS 10.2.1
FreeRTOS-Plus svn version 2735, 2019-10-10
GNU Arm Embedded Toolchain 8-2019-q3-update

thanks,
galen

rtel wrote on Friday, October 11, 2019:

I would recommend starting with what is in the FreeRTOS download so you have a configuration that is known to work, assuming the MAC IP is the same in your chip. You can then opt to update the Cube software afterwards if desired, but easier to do that once you have code running.

galens wrote on Saturday, October 12, 2019:

I’m happy to avoid the use of HAL as much as possible. Perhaps I’ve missed some important piece of information, but it appears to me that there are some pieces of HAL that can’t be avoided. There are several HAL-related include files that must be present.

When trying to compile portable/NetworkInterface/STM32Fxx/NetworkInterface.c, I encountered the following issues:

  1. The project must have some version of stm32f4xx_hal_conf.h.
  2. A non-ethernet module must be defined in stm32f4xx_hal_conf.h. Without this define, stm32f4xx_hal_def.h will not get included, causing lots of breakage (no macro definition for __IO, no typedef for HAL_StatusTypeDef).
  3. ipconfigZERO_COPY_TX_DRIVER must be defined to 1, otherwise compile will fail due to DMATxDescToClear being undefined.
  4. Defines in stm32fxx_hal_eth.h redefine macros defined in Legacy/stm32_hal_legacy.h, which is included from stm32f4xx_hal_def.h.
  5. Using gcc -Wall, there are lots of ‘unused parameter’ and ‘comparison of integer expressions of different signedness’ warnings.

It would be very helpful to have a known good stm32f4xx_hal_conf.h, or at least some notes in portable/NetworkInterface/STM32Fxx/readme.txt that indicate what HAL pieces are required. Thanks.

heinbali01 wrote on Sunday, October 13, 2019:

  1. The project must have some version of stm32f4xx_hal_conf.h.

That’s the way HAL projects work.

2 A non-ethernet module must be defined in stm32f4xx_hal_conf.h.

I will attach my version of stm32f4xx_hal_conf.h. It will include more modules than you actually need.
It is important to have a good implementation of ipconfigRAND32() that uses the RNG module.

3 ipconfigZERO_COPY_TX_DRIVER must be defined to 1, otherwise
compile will fail due to DMATxDescToClear being undefined.

I will check that. For now it is recommended to defined ipconfigZERO_COPY_TX_DRIVER as 1.

4 Defines in stm32fxx_hal_eth.h redefine macros defined in
Legacy/stm32_hal_legacy.h, which is included from stm32f4xx_hal_def.h.

That also drives me crazy, the big overlap between these two files.
I avoided it by defining __STM32_HAL_LEGACY before including it.

6 Using gcc -Wall, there are lots of ‘unused parameter’ and ‘comparison
of integer expressions of different signedness’ warnings.

Could you copy/paste a few of those warnings please? When I compile it with gcc I hardly get any warnings.

It would be very helpful to have a known good stm32f4xx_hal_conf.h,
or at least some notes in portable/NetworkInterface/STM32Fxx/readme.txt
that indicate what HAL pieces are required. Thanks.

The difficulty is of course, that the Network Interface sits between FreeRTOS+TCP and hardware. AWS/FreeRTOS does not develop or publish the HAL. It would be nice if the manufacturers of the CPU’s can publish the network interfaces.

There are a few differences between the port layers in AWS/FreeRTOS and SVN/FreeRTOS.

Here in SVN you will find the latest Network Interface for STM32Fx ( both STM32F4x and STM32F7x ).

heinbali01 wrote on Sunday, October 13, 2019:

Here below you find a stm32f4xx_hal_conf.h that I use for my STM32F4xx projects.

galens wrote on Wednesday, October 16, 2019:

Thanks for the feedback. That helped. I now have ethernet working here, or at least my board successfully gets an address via DHCP and I can ping it.

I have several patches for you that I think will improve the code. Most of them are stm32-related, but one or two fix warnings in the TCP code. Is it okay to create a new bug and attach all of them there? Here is a brief list of the changes you may be interested in.

  • Add note regarding ethernet zero copy
  • Include HAL common macros
  • Prevent inclusion of HAL legacy macros
  • Clean up unused parameter warnings
  • Clean up comparison warnings
  • Only warn if media interface macro is undefined
  • Remove prvMACAddressConfig() if LLMNR not enabled

FYI, my code is still HAL free. I created my own version of the following functions in order to get it working.

  • HAL_GetTick
  • HAL_Delay
  • __HAL_RCC_SYSCFG_CLK_ENABLE
  • HAL_RCC_GetHCLKFreq
  • HAL_ETH_MspInit

Regarding the HAL delay functions, I noticed that HAL delay is being used to workaround the “Successive write operations to the same register might not be fully taken into account” errata. The workaround requires a delay of four TX_CLK/RX_CLK clock cycles. For a 10 Mbit connection, these clocks are running at 2.5 MHz, so this delay would be 1.6 microseconds. The granularity of HAL_Delay is 1 millisecond, so using it causes far more delay than necessary. It would seem there is room for improvement here.

Regarding the ipconfigRAND32 function, I am using rand() from newlib for this, but I don’t see a good place to call srand() to set the seed. Since the IP task will have its own newlib context, and hence its own srand() seed, srand() needs to be called within the IP task. I don’t see a mechanism for doing this. I can, and probably will, throw this into my HAL ethernet initialization code for now, but this is not related to the stm32, so it really doesn’t belong there. Is there a better place to do this?

Thanks again.

heinbali01 wrote on Thursday, October 17, 2019:

Hello Galen, thanks for this detailed feedback. I have reserved time to have a look at it and change the driver where useful.

I have several patches for you that I think will improve the code.
Most of them are stm32-related, but one or two fix warnings in the TCP code.
Is it okay to create a new bug and attach all of them there? Here is a
brief list of the changes you may be interested in.

You can just attach them in this post, so we keep it al together.

FYI, my code is still HAL free. I created my own version of the
following functions in order to get it working.

HAL_GetTick
HAL_Delay

Actually, it would be nicer to use xTaskGetTickCount() and vTaskDelay().

__HAL_RCC_SYSCFG_CLK_ENABLE
HAL_RCC_GetHCLKFreq

Both usefull

HAL_ETH_MspInit

Which is a HAL call-back function, and should be provided by the application developer ( often found in main.c ).

Regarding the HAL delay functions, I noticed that HAL delay is being used to
workaround the “Successive write operations to the same register might not be
fully taken into account” errata.

You totally right about this. I left it because ( as far as I know ) the delay is only needed during initialisation.
In other drivers, usually, a peripheral register is set and than read back.

Regarding the ipconfigRAND32 function, I am using rand() from newlib for
this, but I don’t see a good place to call srand() to set the seed.

It is indeed very important to call srand() with a random value. And if you ST part has a RNG module, that would even be better.

I used the following code in my ST-projects:

void HAL_RNG_MspInit(RNG_HandleTypeDef *hrng)
{
	__HAL_RCC_RNG_CLK_ENABLE();

	/* Enable RNG clock source */
	RCC->AHB2ENR |= RCC_AHB2ENR_RNGEN;
	
	/* RNG Peripheral enable */
	RNG->CR |= RNG_CR_RNGEN;
}

uint32_t ulRandom32( )
{
HAL_StatusTypeDef xResult;
uint32_t ulReturn;

	xResult = HAL_RNG_GenerateRandomNumber( &hrng, &ulReturn );
	if( xResult != HAL_OK )
	{
		ulReturn = 0uL;
	}
	return ulReturn;
}

heinbali01 wrote on Thursday, October 17, 2019:

Sorry, the aobve sample code needs to be called like this:

    hrng.Instance = RNG;
    HAL_RNG_Init( &hrng );

galens wrote on Thursday, October 17, 2019:

You can just attach them in this post, so we keep it al together.

As I mentioned when creating this thread, the code I’m using is FreeRTOS-Plus svn version 2735, 2019-10-10. However, I checked this into my own local git repository, so the patches will be generated from my git repo. Before I attach seven patch files, can you tell me whether you have a preferred patch format?

galens wrote on Thursday, October 17, 2019:

Here are my patches. I went ahead and generated them using git format-patch. Please note the directory path before applying. My directory structure may not have the same depth as yours.

galens wrote on Thursday, October 17, 2019:

FYI, my code is still HAL free. I created my own version of the following functions in order to get it working.

HAL_GetTick
HAL_Delay

Actually, it would be nicer to use xTaskGetTickCount() and vTaskDelay().

That’s actually what I did. My functions are just wrappers for the FreeRTOS functions.

Regarding the HAL delay functions, I noticed that HAL delay is being used to workaround the “Successive write operations to the same register might not be fully taken into account” errata.

You totally right about this. I left it because ( as far as I know ) the delay is only needed during initialisation. In other drivers, usually, a peripheral register is set and than read back.

I thought that might be the case, but I didn’t take time to investigate. It would be easy enough to create short delays by reading and spinning on SysTick, but it’s good to know it’s not needed.

Regarding the ipconfigRAND32 function, I am using rand() from newlib for this, but I don’t see a good place to call srand() to set the seed.

It is indeed very important to call srand() with a random value. And if you ST part has a RNG module, that would even be better.

Yes, I plan to use the RNG in the stm32f427, but for those who don’t have that option and are using newlib, it might be nice to have a callback somewhere early in the IP task. This would allow for a call to srand() within the IP task context.