Large Arrays causing hardfaults/errors

Hello,

I am having a hard time getting 2 arrays of size 840 bytes to work in my code, one each in two functions. First I tried just declaring it in the function where I wanted to use it. Crashed from hardfault and then I checked the stack usage for that task and it was maxed out after doing an operation to that array. I tried adding more memory to the task stack and it maxes out at 896 bytes.

I think tried to use both pvPortMalloc and Malloc and both of them return an array of size 1 back (4 bytes as im using uint32_t). I tried putting in various numbers and was unable to get it to return anything besides that.

Then I tried to put it in the global scope. It worked until I hit a line that memset a second array sized 840 where it hardfaults. Also during this it would not let me read the heap allocation to see how full it was.

Without the arrays in the program at all I have 5.2kb left of heap.

Other Info:
I am using a KW41Z 512kb flash 128kb ram.

If your arrays are declared as local variables in the task then you need to ensure that the stack space allocated at task creation is sufficient for the all the variables and any nested calls.

For pvPortMalloc if the return value is not NULL you have a pointer to the space requested.
So for your array:

uint8_t * pArray = NULL;
pArray = pvPortMalloc(840*sizeof(uint8_t));
if(pArray != NULL)
{
   // Do something useful with the array
   // Once done don't forget vFree(pArray); to return the memory to the heap.
}
else
{
   // The array could not be allocated
}

Thank you for your help. I am going to try that out and see what happens. I tried just allocating more stack space to the task to handle it and I noticed once it uses those arrays the stack usage goes up as expected. But after the function returns it doesn’t release that memory so its stuck jamming up 1.7kb of memory… So I am going to try the dynamic allocation to get it to free up after, as I plan on using this function in a few tasks and don’t want to waste a ton of memory on a function that saves or reads 840b to flash.

Making the variables on the stack will return the space when the function returns, but of course stack space is only usable by that task, so you could call that function again, or a different function that needed similar space. To return it so other tasks can use it, that is what the heap is for.

So currently I have it declared within the function like this,

uint32_t paramBuf[220];

and when I step through while monitoring the tasks stack usage it going from about 600b to 1.4kb when i call the saveflash() function to save that array to flash, then to around 2.2kb when it calls the loadflash() function. After both functions return it seems the stack usage is still at 2.2kb which is odd because I imagined it should go back down to 600b since the functions returned.

I was thinking to try to expand my heap/stack size and use the dynamic allocation and then free it after to get around that. Although I am confused as to why its not just returning after the function returns.

How are you measuring stack usage? The ‘High Water Mark’ calls, by definition don’t give the current usage, but the historical (for this run) maximum. If you measure with the stack pointer itself, you will see the extra space.

I am using the FreeRTOS plugin for mcuxpresso. I actually don’t know if that gets current or high watermark off the top of my head.

Most plugins get the high water mark, as that is most often what you want to know.

So here is what the FreeRTOS mcuxpresso debug plugin says when I expand the task to look at more details (I am using heap4.c for the heap):

Before running either function:
Stack Base: 0x200049c0
Stack Top: 0x20005638
Stack Highwater Mark: 0x200051d0
Stack Usage: 1.1kb/3.12kb

After running and returning from 1 flash function that uses that array as a local variable:
Stack Base: 0x200049c0
Stack Top: 0x20005638
Stack Highwater Mark: 0x20004e50
Stack Usage: 1.98kb/3.12kb

After running the second flash function:
Stack Base: 0x200049c0
Stack Top: 0x20005638
Stack Highwater Mark: 0x20004b98
Stack Usage: 2.66kb/3.12kb

Also here is a copy of the function I am calling to see if it sheds any light onto this behavior. I would imagine the stack top is supposed to go down after the function returns.

“CALLBOX_PARMS” is an 840byte struct I am converting to a 220 sized 32bit array for the 32bit flash memory. Then reading and converting it back into that struct.

CALLBOX_PARMS readFlashParam()
{

uint32_t flashReadBuf[CALLBOX_PARMS_SIZE/4];
uint32_t pflashBlockBase = 0;
uint32_t pflashTotalSize = 0;
uint32_t pflashSectorSize = 0;
flash_security_state_t securityStatus = kFLASH_SecurityStateNotSecure; /* Return protection status */
uint32_t destAdrss; /* Address of the target location */
uint32_t failAddr, failDat;
/* Get flash properties*/
FLASH_GetProperty(&s_flashDriver, kFLASH_PropertyPflashBlockBaseAddr, &pflashBlockBase);
FLASH_GetProperty(&s_flashDriver, kFLASH_PropertyPflashTotalSize, &pflashTotalSize);
FLASH_GetProperty(&s_flashDriver, kFLASH_PropertyPflashSectorSize, &pflashSectorSize);

//Get Flash Base Address
destAdrss = pflashBlockBase + (pflashTotalSize - pflashSectorSize);


memset(flashReadBuf,0,sizeof(flashReadBuf));
uint32_t i = 0;

//Lock Mutex for flash access
OSA_MutexLock(xflashMutex, 20000);


 /* Verify programming by reading back from flash directly*/
 for (i = 0; i < (CALLBOX_PARMS_SIZE/4); i++)
 {
	 flashReadBuf[i] = *(volatile uint32_t *)(destAdrss + i * 4);

 }

 OSA_MutexUnlock(xflashMutex);

 CALLBOX_PARMS returnStruct;
 memcpy(&returnStruct, flashReadBuf, sizeof(returnStruct));


 return returnStruct;

}

void saveFlashParam()
{
uint32_t s_buffer[CALLBOX_PARMS_SIZE/4];

//Flash inits
status_t result=0;
uint32_t pflashBlockBase = 0;
uint32_t pflashTotalSize = 0;
uint32_t pflashSectorSize = 0;
flash_security_state_t securityStatus = kFLASH_SecurityStateNotSecure; /* Return protection status */
uint32_t destAdrss; /* Address of the target location */
uint32_t i, failAddr, failDat;
/* Get flash properties*/
FLASH_GetProperty(&s_flashDriver, kFLASH_PropertyPflashBlockBaseAddr, &pflashBlockBase);
FLASH_GetProperty(&s_flashDriver, kFLASH_PropertyPflashTotalSize, &pflashTotalSize);
FLASH_GetProperty(&s_flashDriver, kFLASH_PropertyPflashSectorSize, &pflashSectorSize);

//Convert Param Struct to Byte Struct


int sizeofBuf = sizeof(s_buffer);



memset(s_buffer,0,sizeof(s_buffer));
memcpy(s_buffer, pFParms, sizeof(s_buffer));

/* Check security status. */
result = FLASH_GetSecurityState(&s_flashDriver, &securityStatus);
if (kStatus_FLASH_Success != result)
{
	while(1);
}
/* Print security status. */
switch (securityStatus)
{
	case kFLASH_SecurityStateNotSecure:
		break;
	case kFLASH_SecurityStateBackdoorEnabled:
		break;
	case kFLASH_SecurityStateBackdoorDisabled:
		break;
	default:
		break;
}

//Small flash test to verify its working
if (kFLASH_SecurityStateNotSecure == securityStatus)
{

	destAdrss = pflashBlockBase + (pflashTotalSize - pflashSectorSize);

	result = FLASH_Erase(&s_flashDriver, destAdrss, pflashSectorSize, kFLASH_ApiEraseKey);
	if (kStatus_FLASH_Success != result)
	{
		while(1);
	}

	/* Verify sector if it's been erased. */
	result = FLASH_VerifyErase(&s_flashDriver, destAdrss, pflashSectorSize, kFLASH_MarginValueUser);
	if (kStatus_FLASH_Success != result)
	{
		while(1);
	}

	/* Program user buffer into flash*/
	 result = FLASH_Program(&s_flashDriver, destAdrss, s_buffer, sizeof(s_buffer));
	 if (kStatus_FLASH_Success != result)
	 {
		 while(1);
	 }

	 /* Verify programming by Program Check command with user margin levels */
	 result = FLASH_VerifyProgram(&s_flashDriver, destAdrss, sizeof(s_buffer), s_buffer, kFLASH_MarginValueUser,
								  &failAddr, &failDat);
	 if (kStatus_FLASH_Success != result)
	 {
		 while(1);
	 }
}

}

After looking at the difference between these numbers I notice that these values don’t really tell you what the current space being used is at all because the base-top just equals the allocated space. And the highwatermark is just the max amount of memory used at one time? I guess I am still confused as to how its using 2.66kb at once given that before the function its only using 1.1kb and that would indicate that one of those functions is using 2kb of stack which I don’t see how that would happen?

None of those values is the current stack pointer. Stack Base is the bottom end of the allocated stack, Stack Top is the top end of the allocated stack, and the High-water Mark is how much has been written to at some time

Remember that for the second call, you need to include the stack usage of the functions that it calls