cancel
Showing results for 
Search instead for 
Did you mean: 

Where are the program sources stored in CubeMXIDE for FreeRTOS?

I want to change heap4.c to add a feature.  I want the heap program to tell me, when I ask for memory and I get a Malloc Failure, I want to know the shortfall.  I have a method for this, which works, but involves changing heap4.c.  When I do that, any time I go back to the configuration program to change the IOC file, the program regenerates all files.  Since heap4.c does not have a user section, and certainly not there, the changes are overwritten.

I have a similar problem in main.c, but if I can do one source change, I can do others.

 

4 REPLIES 4
Pavel A.
Super User

The situation here is like with all the ST-provided libraries. You either get a copy of everything in the generated project (or example) or reference to source files in the shared "repository". In the former case your change can be discarded by re-generation. In the latter case you can edit the file in the "repository", with obvious drawbacks.

You probably want to make a clone of heap4.c into your project, rename it to (say) heap4m.c. 

Then exclude the original heap4.c from build (whenever it is located). Don't forget to save the changes in your version control.  After re-generation, revise changes and revert unwanted ones.

 

Sorry, I decided to take a slight break and work on the pick and place machine.  

I think I know where to find the link (in the program) to call up heap4.c.  However, that's not in a user section, so I end up with the same "need to replace a program/section".  The repository will likely be edited when I find it, that's the neatest solution.  What I'm looking for is a solution that I don't have to keep tweaking time after time.  I find that I need to regenerate the program from the IOC file a few times when getting the program up and running (or even during the development to adjust features).  

The code I need to generate is rather highly customized, adding support for QSPI memory, then customizing FreeRTOS to adjust memory allocations.  I do find adjusting FreeRTOS parameters annoying, as the program doesn't have very good interactive setup (and even error reporting) capabilities. That's another matter.  

For me, the optimal solution will be to modify the source files.  

Thanks

As to "this solve the problem", I'll have to report on that after a bit.

 

OK, got some progress to report:

Apparently, (and I'm guessing), the libraries are both processor and situation specific, and also stored in a zip file.  The trick is to find the unzipped versions which are apparently created as the pack is installed.

I did the following:

1) find where the unzipped versions hide.  I'm currently experimenting with an L5 processor and dealing with version 1.19 of CubeMX.  I had problems with the latest version.  The files are located at:

 

/*******************************************************************************************************************
 *
 * File location is:
 *
 * C:\Users\YourNameHere\STM32Cube\Repository\STM32Cube_FW_L5_V1.5.1\Middlewares\Third_Party\FreeRTOS\Source\portable\MemMang
 *
 *	where this is for the L5 processor, and 1.5.1 is the current firmware pack
 *
 *	This file (heap4.c) has been modified to return the amount of memory not used.
 *
 ******************************************************************************************************************/

Make a copy of this to avoid unpleasant surprises.

I then commented out the existing code and added the following code in heap4.c

	#if( configUSE_MALLOC_FAILED_HOOK == 1 )
	{
		if( pvReturn == NULL )
		{
			extern void vApplicationMallocFailedHook( size_t );
			vApplicationMallocFailedHook(xFreeBytesRemaining - xWantedSize);
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}
	}
	#endif

 

You do want to substitute the configUSE_MALLOC_FAILED_HOOK section.

Now, in the main.c code you add a section that implements the MALLOC_FAILED section.  

void vApplicationMallocFailedHook( size_t shortfall )
{
	HeapStats_t					heap_status;
	uint32_t					needed;
	char						text[30] = {0};
	char						numstr[10];

	// record heap size.
	vPortGetHeapStats(&heap_status);
	needed = abs(shortfall);
	strcpy(text,(char*)"MALLOC FAILED HOOK ");
	itoa(needed & 0xFFFF, numstr,10);
	strcat(text,numstr);
	#ifdef _ERROR
		ERROR1(__FILE__, __LINE__, text);
	#endif
}

 

recording the heap stats just gives access to more information if needed.  Most of the variables will be optimized out, so the useful data is in numstr, or text.

My hardware designs include 4 LEDS, red, blue, green and amber.  Red is used for errors, blue is used for a link indicator, amber is used for warning, and green is used for a task run indicator (it's a heartbeat).

Therefore, the ERROR1 macro provides LED drive and a record of where the error returned.

void ERROR1(const void* filename, unsigned int linenumber, char* comment)
{
	int j;
	char* filename1 = (char*) filename;
	  __disable_irq();
	  while (1)
	  {
			#if (defined _LED) && (defined _DIRECT_LED) && (defined RED_LED_Pin)
				 if (RED_ON_HIGH)
				 {
						HAL_GPIO_WritePin(RED_LED_GPIO_Port, RED_LED_Pin, GPIO_PIN_SET);
				 }
				 else
				 {
						HAL_GPIO_WritePin(RED_LED_GPIO_Port, RED_LED_Pin, GPIO_PIN_RESET);
				 }
			#endif
			#if (defined _LED) && (defined _DIRECT_LED) && (defined RED_LED_Pin)
				 if (RED_ON_HIGH)
				 {
						HAL_GPIO_WritePin(RED_LED_GPIO_Port, RED_LED_Pin, GPIO_PIN_SET);
				 }
				 else
				 {
						HAL_GPIO_WritePin(RED_LED_GPIO_Port, RED_LED_Pin, GPIO_PIN_RESET);
				 }

			#endif
			for (int i = 0; i < 500000; i++)
			{
				j = i;
			}
			#if (defined _LED) && (defined _DIRECT_LED) && (defined RED_LED_Pin)
				 if (RED_ON_HIGH)
				 {
						HAL_GPIO_WritePin(RED_LED_GPIO_Port, RED_LED_Pin, GPIO_PIN_RESET);
				 }
				 else
				 {
						HAL_GPIO_WritePin(RED_LED_GPIO_Port, RED_LED_Pin, GPIO_PIN_SET);
				 }
			#endif
			#if (defined _LED) && (defined _DIRECT_LED) && (defined RED_LED_Pin)
				 if (RED_ON_HIGH)
				 {
						HAL_GPIO_WritePin(RED_LED_GPIO_Port, RED_LED_Pin, GPIO_PIN_RESET);
				 }
				 else
				 {
						HAL_GPIO_WritePin(RED_LED_GPIO_Port, RED_LED_Pin, GPIO_PIN_SET);
				 }

			#endif
			for (int i = 0; i < 500000; i++)
			{
				j = i;
			}
	  }
}

 

This depends on the pin definitions in the IOC file.  The pin name is "RED_LED".  This also requires the definitions of _LED (enables all LEDS), _DIRECT_LED (indicates pin LEDs), and RED_LED_Pin (defined pin in IOC file).  RED_ON_HIGH is defined if using an inverting driver from the pin to the LED.  I prefer LED drivers to unload the processor pins.  It also allows remote indicators without worrying about overloading the processor pin drive, especially on low drive capability pins.  

The whole system is built on a definition file that allows graceful enabling and disabling of hardware/software systems across projects.

When I change versions of the software I'll have to regenerate the changes.

 

 

 

Just noticed that I had a section (two of them) repeated in the ERROR code.  Feel free to delete.