cancel
Showing results for 
Search instead for 
Did you mean: 

SBSFU with FreeRTOS causing FIREWALL RESET FAULT

SL61
Associate II

Hi everyone,

I am using STM32L4A6 with FreeRTOS running on it. I integrate SBSFU according to UM2262 and AN5056. After jumping to application, the firmware triggered Firewall reset when calling osKernelStart() .

I already turned SysTick off before jumping to my application. I used one LED to indicate the current code running and firmware was good before calling osKernelStart().

I also tried to use non-os application integrated SBSFU and it ran without problem.

Any suggestion is welcome. Thanks.

Sean

1 ACCEPTED SOLUTION

Accepted Solutions
Jocelyn RICARD
ST Employee

Hello Sean,

The MX_USB_DEVICE_Init() just prepares the USB stack to be connected but nothing is initialized yet.

The initialization occurs when the USB host is requesting the enumeration.

In your case, you have already connected the USB cable, so enumeration starts immediately after the init but is takes time.

This is the reason why your delay solves the issue.

Now, if you disconnect the USB cable, you will fall in the same reset issue as resources for CDC class will be de-allocated.

As workaround, I would suggest to add something like:

if (pdev->dev_state == USBD_STATE_CONFIGURED)

{

CDC_Transmit_FS ...

}

But this is not robust solution as disconnect interrupt could occur between the test and the call.

The best solution would be to disable USB interrupts the time to call CDC_Transmit but I don't know the impact on the USB stack.

Need to be checked.

Best regards

Jocelyn

View solution in original post

8 REPLIES 8
Jocelyn RICARD
ST Employee

Hello Sean,

as you deactivated the systick you are already aware of that issue.

I'm not aware of another issue related to the usage of FreeRTOS.

Did you change any mapping compared to the 32L496GDISCOVERY example?

Best regards

Jocelyn

Sorry for the late reply, Jocelyn. I actually use the same linker file as the 32L496GDISCOVERY example​ and the system_stm32l4xx.c file to avoid mapping issue.

The thing that makes me confused is that Firewall Reset should be triggered by invalid access to protected memory region (both Flash and SRAM), right? Since I used the same configuration as 32L496GDISCOVERY example, the code and the heap used by RTOS should be allocated to right location.

Hi Jocelyn,

Here is an update. I used the led to locate the code violating firewall and found FW got FIREWALL RESET FAULT when sending data via USB.

Here is the code to transmit data and it reset when hitting USBD_CDC_HandleTypeDef *hcdc =

(USBD_CDC_HandleTypeDef*) hUsbDeviceFS.pClassData;

uint8_t CDC_Transmit_FS (uint8_t* Buf, uint16_t Len)
{
	uint8_t result = USBD_OK;
	/* USER CODE BEGIN 7 */
	USBD_CDC_HandleTypeDef *hcdc =
			(USBD_CDC_HandleTypeDef*) hUsbDeviceFS.pClassData;
 
	while (hcdc->TxState != 0);
 
	USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
	result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
	/* USER CODE END 7 */
	return result;
}

Jocelyn RICARD
ST Employee

Hello Sean,

This is strange indeed!

So, I understand you used the STM32L496 example that you adapted to use USB for firmware update instead of Ymodem.

If you send a zip of your project I could have a look and understand what happens.

The only way to progress is to use the debugger to go as close as possible from the reset and understand the reason.

Best regards

Jocelyn

Hello Jocelyn,

I found a workaround to over come this problem. Actually it is very tricky. By adding a delay after MX_USB_DEVICE_Init(), the program runs normally.

After digging in a little, I found the reason should be invalid access to memory used by USB when USB not fully initialized. When there is no delay after MX_USB_DEVICE_Init(), program goes into CDC_Transmit_FS() directly and tries to access hUsbDeviceFS.pClassData, which is a pointer required to be initialized by USB stack. At this time, hUsbDeviceFS.pClassData is not initialized yet and this caused the problem. How about hUsbDeviceFS.pClassData? It is initialized in USBD_CDC_Init() and this function is called somewhere during callback.

/**
  * @brief  USBD_CDC_Init
  *         Initialize the CDC interface
  * @param  pdev: device instance
  * @param  cfgidx: Configuration index
  * @retval status
  */
static uint8_t  USBD_CDC_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
  uint8_t ret = 0U;
  USBD_CDC_HandleTypeDef   *hcdc;
 
  if(pdev->dev_speed == USBD_SPEED_HIGH)
  {
    /* Open EP IN */
    USBD_LL_OpenEP(pdev, CDC_IN_EP, USBD_EP_TYPE_BULK,
                   CDC_DATA_HS_IN_PACKET_SIZE);
 
    pdev->ep_in[CDC_IN_EP & 0xFU].is_used = 1U;
 
    /* Open EP OUT */
    USBD_LL_OpenEP(pdev, CDC_OUT_EP, USBD_EP_TYPE_BULK,
                   CDC_DATA_HS_OUT_PACKET_SIZE);
 
    pdev->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U;
 
  }
  else
  {
    /* Open EP IN */
    USBD_LL_OpenEP(pdev, CDC_IN_EP, USBD_EP_TYPE_BULK,
                   CDC_DATA_FS_IN_PACKET_SIZE);
 
    pdev->ep_in[CDC_IN_EP & 0xFU].is_used = 1U;
 
    /* Open EP OUT */
    USBD_LL_OpenEP(pdev, CDC_OUT_EP, USBD_EP_TYPE_BULK,
                   CDC_DATA_FS_OUT_PACKET_SIZE);
 
    pdev->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U;
  }
  /* Open Command IN EP */
  USBD_LL_OpenEP(pdev, CDC_CMD_EP, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);
  pdev->ep_in[CDC_CMD_EP & 0xFU].is_used = 1U;
 
  pdev->pClassData = USBD_malloc(sizeof (USBD_CDC_HandleTypeDef));
 
  if(pdev->pClassData == NULL)
  {
    ret = 1U;
  }
  else
  {
    hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
 
    /* Init  physical Interface components */
    ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Init();
 
    /* Init Xfer states */
    hcdc->TxState = 0U;
    hcdc->RxState = 0U;
 
    if(pdev->dev_speed == USBD_SPEED_HIGH)
    {
      /* Prepare Out endpoint to receive next packet */
      USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer,
                             CDC_DATA_HS_OUT_PACKET_SIZE);
    }
    else
    {
      /* Prepare Out endpoint to receive next packet */
      USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer,
                             CDC_DATA_FS_OUT_PACKET_SIZE);
    }
  }
  return ret;
}

Now I can wait for USB fully initialized and use it without problems.​

Thanks

Sean

Jocelyn RICARD
ST Employee

Hello Sean,

thank you for the feedback.

The firewall is located at the beginning of the flash after the interrupt vector table.

The flash is mirrored at address 0.

So, if accessing to uninitialised structures, you may fall in this reset issue

Now this is a bit strange that CDC_Transmit_FS()  is called so early.

The USB enumeration should occur before, so everything should be already initialized.

Best regards

Jocelyn

Hello Jocelyn,

It makes me confused too as long as there is status checking in MX_USB_DEVICE_Init() and it should be initialized​. Actually my test code is simple, just modified a little from the one generated from CubeMX. Without Hal_Delay(500), I have the firewall reset problem.

void StartDefaultTask(void const * argument)
{
    
                 
  /* init code for USB_DEVICE */
	MX_USB_DEVICE_Init();
	HAL_Delay(500);
 
	/* USER CODE BEGIN StartDefaultTask */
	/* Infinite loop */
	for (;;)
	{
		const char* test = "APP\r\n";
		CDC_Transmit_FS((uint8_t*) test, strlen(test));
		HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_2);
		HAL_IWDG_Refresh(&hiwdg);
		osDelay(1000);
	}
	/* USER CODE END StartDefaultTask */
}

Thanks,

Sean

Jocelyn RICARD
ST Employee

Hello Sean,

The MX_USB_DEVICE_Init() just prepares the USB stack to be connected but nothing is initialized yet.

The initialization occurs when the USB host is requesting the enumeration.

In your case, you have already connected the USB cable, so enumeration starts immediately after the init but is takes time.

This is the reason why your delay solves the issue.

Now, if you disconnect the USB cable, you will fall in the same reset issue as resources for CDC class will be de-allocated.

As workaround, I would suggest to add something like:

if (pdev->dev_state == USBD_STATE_CONFIGURED)

{

CDC_Transmit_FS ...

}

But this is not robust solution as disconnect interrupt could occur between the test and the call.

The best solution would be to disable USB interrupts the time to call CDC_Transmit but I don't know the impact on the USB stack.

Need to be checked.

Best regards

Jocelyn