cancel
Showing results for 
Search instead for 
Did you mean: 

Has anyone got ITCM working with GCC under STM32CubeIDE

Garnett.Robert
Senior III

Hi,

I have spent three days trying to put some real-time FIR filters into ITCM to speed things up.

I have been able to allocate the functions, copy the code from flash to ITCM in the start-up file, but when I run the system the ITCM memory gets changed for no apparent reason. If I single step through the parts where the ITCM memory changes, it doesn't change.

The functions work the first time through, but as the code is corrupted processor registers aren't initialized properly so I get hard faults.

The only working example I can find is one ported to Keil uVision which uses scatter files, much easier than that abominable gcc linker script.

I would post the results of my efforts, but that will take another day and I'm fed up with it.

I would just love to see a working example developed under STM32CubeIDE.

My functions are simple, self contained no input parameters. It shouldn't be hard. It isn't with uVision.

Can anyone help?

Best regards

Rob

1 ACCEPTED SOLUTION

Accepted Solutions

Rob,

Which STM32?

If hospi->Instance is zero, it means it hasn't been properly initialized previously. So walk back in your code (and Cube now forms part of your code), find out how hopsi is defined and how is it initialized and find out why is hospi->Instance zero.

I don't know about RTOS, I don't use it.

JW

View solution in original post

6 REPLIES 6

Which STM32?

You can try to place a data breakpoint (watchpoint) to some of the areas you are suspecting to change, that would reveal the culprit which overwrites it.

JW

TDK
Guru

If it works once, sounds like you got it working, you just need to figure out where and why the rogue memory write is happening and fix it.

Some other leads here:

https://community.st.com/s/question/0D50X00009hmWRjSAM/how-to-move-code-into-itcm-ram-with-stm32f72xx3xx

If you feel a post has answered your question, please click "Accept as Solution".

0693W00000GXSBWQA5.jpg0693W00000GXSBPQA5.jpg0693W00000GXSBRQA5.jpg0693W00000GXSBHQA5.jpg0693W00000GXSBCQA5.jpgHi Jan

Thanks for your prompt response.

I took your advice and set up a couple of trace points at memory addresses 0x8 and 0x4.

Instead of running the functions in ITCM I left them in flash and put a pattern of 0x40 words in the ITCM starting at zero. (0xFAFAFBFB)

I then ran without break points and found that there were writes being made to the ITCM ram.

The first write was made by the ospi deinit:

The second by freeRTOS vTaskSwitchContext function:

Looking at the disassembly first of these the, ospi de init we get:

You can see that the next instruction:

0801749a:  str    r2, [r3, #8]

will set the ITCM ram addr. to 0xFAFAFBF9

Which it does:

This looks a lot like a naughty stack problem. What do you think?

Th problem with this line of thinking is that the operating system scheduler isn't running when the ospi initialisation is running as this is executed at startup. So stack usage shouldn't be very high.

I will have a look at what the stack is doing.

Any f0693W00000GXSB7QAP.jpguther thoughts?

Best regards

Rob

Rob,

Which STM32?

If hospi->Instance is zero, it means it hasn't been properly initialized previously. So walk back in your code (and Cube now forms part of your code), find out how hopsi is defined and how is it initialized and find out why is hospi->Instance zero.

I don't know about RTOS, I don't use it.

JW

Garnett.Robert
Senior III

Hi

I found the answer to the overwriting problem. The two areas which were overwriting the ITCM ram were the Octo Spi Initialization function for the discovery board STM32H7B3I-DK and the uxListRemove of FreeRTOS.

The first of these was:

static void MX_OCTOSPI1_Init(void)
{
  /* USER CODE END OCTOSPI1_Init 1 */
  /* OCTOSPI1 parameter configuration*/
  hospi1.Instance = OCTOSPI1;
  hospi1.Init.FifoThreshold = 1;
  hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
...
  hospi1.Init.MaxTran = 0;
  hospi1.Init.Refresh = 0;
  if (HAL_OSPI_Init(&hospi1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN OCTOSPI1_Init 2 */
  BSP_OSPI_NOR_Init_t Flash;
  Flash.InterfaceMode = BSP_OSPI_NOR_OPI_MODE;
  Flash.TransferRate  = BSP_OSPI_NOR_DTR_TRANSFER;
  hospi_nor->Instance = hospi1.Instance;  /* rjg mod */
  BSP_OSPI_NOR_DeInit(0);
  int32_t RetVal = BSP_OSPI_NOR_Init(0, &Flash);
  if(RetVal != BSP_ERROR_NONE)
  {
    Error_Handler();
  }
  RetVal = BSP_OSPI_NOR_EnableMemoryMappedMode(0);
  if(RetVal != BSP_ERROR_NONE)
  {
    Error_Handler();
  }
  /* USER CODE END OCTOSPI1_Init 2 */
 
}

The programmer creates a new handle for the ospi driver called hospi_nor, but doesn't initialize it to the hardware instance of the actual peripherals memory locations. The sequence is:

BSP_OSPI_NOR_DeInit(uint32_t Instance) below calls

if (HAL_OSPI_DeInit(&hospi_nor[Instance]) != HAL_OK). Line 34.

/**
  * @brief  De-Initializes the OSPI interface.
  * @param  Instance   OSPI Instance
  * @retval BSP status
  */
int32_t BSP_OSPI_NOR_DeInit(uint32_t Instance)
{
  int32_t ret = BSP_ERROR_NONE;
 
  /* Check if the instance is supported */
  if(Instance >= OSPI_NOR_INSTANCES_NUMBER)
  {
    ret = BSP_ERROR_WRONG_PARAM;
  }
  else
  {
    /* Disable Memory mapped mode */
    if(Ospi_Nor_Ctx[Instance].IsInitialized == OSPI_ACCESS_MMP)
    {
      if(BSP_OSPI_NOR_DisableMemoryMappedMode(Instance) != BSP_ERROR_NONE)
      {
        ret = BSP_ERROR_COMPONENT_FAILURE;
      }
    }
 
    if(ret == BSP_ERROR_NONE)
    {
      /* Set default Ospi_Nor_Ctx values */
      Ospi_Nor_Ctx[Instance].IsInitialized = OSPI_ACCESS_NONE;
      Ospi_Nor_Ctx[Instance].InterfaceMode = BSP_OSPI_NOR_SPI_MODE;
      Ospi_Nor_Ctx[Instance].TransferRate  = BSP_OSPI_NOR_STR_TRANSFER;
 
#if (USE_HAL_OSPI_REGISTER_CALLBACKS == 0)
      OSPI_NOR_MspDeInit(&hospi_nor[Instance]);
#endif /* (USE_HAL_OSPI_REGISTER_CALLBACKS == 0) */
 
      /* Call the DeInit function to reset the driver */
      if (HAL_OSPI_DeInit(&hospi_nor[Instance]) != HAL_OK)
      {
        ret = BSP_ERROR_PERIPH_FAILURE;
      }
    }
  }
 
  /* Return BSP status */
  return ret;
}

if (HAL_OSPI_DeInit(&hospi_nor[Instance]) != HAL_OK) this calls macro

CLEAR_BIT(hospi->Instance->DCR1, OCTOSPI_DCR1_FRCK); Line 17 below.

HAL_StatusTypeDef HAL_OSPI_DeInit(OSPI_HandleTypeDef *hospi)
{
  HAL_StatusTypeDef status = HAL_OK;
 
  /* Check the OSPI handle allocation */
  if (hospi == NULL)
  {
    status = HAL_ERROR;
    /* No error code can be set set as the handler is null */
  }
  else
  {
     /* Disable OctoSPI */
     __HAL_OSPI_DISABLE(hospi);
 
     /* Disable free running clock if needed : must be done after OSPI disable */
     CLEAR_BIT(hospi->Instance->DCR1, OCTOSPI_DCR1_FRCK);

as hospi_nor isn't initialized the clear bit macro accesses the ITCM address at offset #4.

I don't know what the programmer was trying to achieve and I didn't want to break working? code so I added the line:

  hospi_nor->Instance = hospi1.Instance;  /* rjg mod */

This sets the hospi_nor.Instance to the correct peripheral address.

The second area overwriting was the uxListRemove function of the FreeRTOS lists module.

UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
/* The list item knows which list it is in.  Obtain the list from the list
item. */
List_t * const pxList = pxItemToRemove->pxContainer;
 
	pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
	pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
 
	...
}

Lines 7 and 8 were the lead in the saddlebags here. The cause was twofold first I had executed a task suspend before starting the scheduler and secondly i used taskSuspend on a sw timer rather than timerStop. This causes the uxTaskRemove function to behave badly and corrupt the ITCM.

Fixing my two errors stopped the problem, but I could see the same thing happening again. To prevent writing to the ITCM ram program area I invoked the MPU after copying the code from flash to ram. I set the MPU for this ram to read only so if I inadvertently try to write to it I will get a memory fault which is a lot safer than if the program soldiers on with bad code in the ITCM.

It was all worth it as my critical functions with compiler optimization on only take 190 us compared to 500 us before.

Just to help others my startup code and linker script are attached.

and my function calls are:

__attribute__((section(".Tim2itcm"))) void PositionFilter_step(void)
{
...
}
 
__attribute__((section(".Tim2itcm"))) void impulseCurveFit_step(void)
{
...
}
 
etc.

Anyway guys thanks for your help.

Best regards

Rob

Hi Jan,

Trouble is it's not my code, its a driver written by ST for the Tiny Shark Octi SPI and like a lot of this code it hasn't been tested all that well. I will have to rewrite it and simplify it at some stage, but I don't have the time right now, so I've set the handles instance to the hw instance.