UG96 cellular module Interfacing with STM32H743ZI + FreeRTOS

Hello,

I have to implement AWS IOT application i am using UG96 cellular module with stm32h743 controller. there uart communication used for transmitting and receiveing data.
My problem is transmitting interrupt is working fine but receiving interrupt only came at a first.
how to i solve issue? if any one have any solution please share.

Is this question about how to use the UART on the STM32H7? If so, are there examples that come with the board? I think the ST tools will generate examples for you. Not clear if this is a FreeRTOS question or not.

No it’s not regarding to UART without FreeRTOS UART is working properly.
When i am used FreeRTOS in my application Transmit interrupt working properly but at a time of receiving in xSemaphoreTake given osErrorOS or Timeout ERROR.

You should show some code.

static at_status_t process_AT_transaction(at_handle_t athandle, at_msg_t msg_in_id, at_buf_t *p_rsp_buf)
{
#if (RTOS_USED == 1)
  UNUSED(p_rsp_buf);
#endif /* RTOS_USED == 1 */

  /* static variables (do not use stack) */
  static AT_CHAR_t build_atcmd[ATCMD_MAX_CMD_SIZE] = {0};
  /* local varaibles */
  at_status_t retval;
  uint32_t tickstart;
  uint32_t at_cmd_timeout = 0U;
  at_action_send_t action_send;
  at_action_rsp_t action_rsp;
  uint16_t build_atcmd_size;
  uint8_t another_cmd_to_send;

  /* reset at cmd buffer */
  (void) memset((void *) build_atcmd, 0, ATCMD_MAX_CMD_SIZE);

  do
  {
    (void) memset((void *)&build_atcmd[0], 0, sizeof(AT_CHAR_t) * ATCMD_MAX_CMD_SIZE);
    build_atcmd_size = 0U;

    /* Get command to send */
    action_send = ATParser_get_ATcmd(&at_context[athandle],
                                     (uint8_t *)&build_atcmd[0],
                                     (uint16_t)(sizeof(AT_CHAR_t) * ATCMD_MAX_CMD_SIZE),
                                     &build_atcmd_size, &at_cmd_timeout);
    if ((action_send & ATACTION_SEND_ERROR) != 0U)
    {
      PrintDBG("AT_sendcmd error: get at command")
      LogError(7, ERROR_WARNING);
      return (ATSTATUS_ERROR);
    }

    /* Send AT command through IPC if a valid command is available */
    if (build_atcmd_size > 0U)
    {
      /* Before to send a command, check if current mode is DATA mode
      *  (exception if request is to suspend data mode)
      */
      if ((at_context[athandle].in_data_mode == AT_TRUE) && (msg_in_id != (at_msg_t) SID_CS_DATA_SUSPEND))
      {
        /* impossible to send a CMD during data mode */
        PrintErr("DATA ongoing, can not send a command")
        LogError(8, ERROR_WARNING);
        return (ATSTATUS_ERROR);
      }

      retval = sendToIPC(athandle, (uint8_t *)&build_atcmd[0], build_atcmd_size);
      if (retval != ATSTATUS_OK)
      {
        PrintErr("AT_sendcmd error: send to ipc")
        LogError(9, ERROR_WARNING);
        return (ATSTATUS_ERROR);
      }
    }

    /* Wait for a response or a temporation (which could be = 0)*/
    if (((action_send & ATACTION_SEND_WAIT_MANDATORY_RSP) != 0U) ||
        ((action_send & ATACTION_SEND_TEMPO) != 0U))
    {
      /* init tickstart for a full AT transaction */
      tickstart = HAL_GetTick();

      do
      {
        /* Wait for response from IPC */
        retval = waitFromIPC(athandle, tickstart, at_cmd_timeout, &msgFromIPC[athandle]);
        if (retval != ATSTATUS_OK)
        {
          if ((action_send & ATACTION_SEND_WAIT_MANDATORY_RSP) != 0U)
          {
            /* Waiting for a response (mandatory) */
            if (retval == ATSTATUS_TIMEOUT)
            {
              /* in case of advanced debug
               IPC_dump_RX_queue(&ipcHandleTab[athandle], 1);
              */
            }
            PrintErr("AT_sendcmd error: wait from ipc")
#if (DBG_REQUEST_DURATION == 1)
            PrintErr("Interrupts count: disable=%d enable=%d",
                     count_disable,
                     count_enable)
#endif /* DBG_REQUEST_DURATION */
            LogError(10, ERROR_WARNING);
            return (ATSTATUS_ERROR);
          }
          else /* ATACTION_SEND_TEMPO */
          {
            /* Temporisation (was waiting for a non-mandatory event)
            *  now that timer has expired, proceed to next action if needed
            */
            if ((action_send & ATACTION_SEND_FLAG_LAST_CMD) != 0U)
            {
              action_rsp = ATACTION_RSP_FRC_END;
            }
            else
            {
              action_rsp = ATACTION_RSP_FRC_CONTINUE;
            }
            goto continue_execution;
          }
        }

#if (RTOS_USED == 1)
        /* Retrieve the action which has been set on IPC msg reception in ATCoreTaskBody
        *  More than one action could has been set
        */
        if ((at_context[athandle].action_flags & ATACTION_RSP_FRC_END) != 0U)
        {
          action_rsp = ATACTION_RSP_FRC_END;
          /* clean flag */
          at_context[athandle].action_flags &= ~((at_action_rsp_t) ATACTION_RSP_FRC_END);
        }
        else if ((at_context[athandle].action_flags & ATACTION_RSP_FRC_CONTINUE) != 0U)
        {
          action_rsp = ATACTION_RSP_FRC_CONTINUE;
          /* clean flag */
          at_context[athandle].action_flags &= ~((at_action_rsp_t) ATACTION_RSP_FRC_CONTINUE);
        }
        else if ((at_context[athandle].action_flags & ATACTION_RSP_ERROR) != 0U)
        {
          /* clean flag */
          at_context[athandle].action_flags &= ~((at_action_rsp_t) ATACTION_RSP_ERROR);
          PrintErr("AT_sendcmd error: parse from rsp")
          LogError(11, ERROR_WARNING);
          return (ATSTATUS_ERROR);
        }
        else
        {
          /* all other actions are ignored */
          action_rsp = ATACTION_RSP_IGNORED;
        }
#else
        /* Parse the response */
        action_rsp = ATParser_parse_rsp(&at_context[athandle], &msgFromIPC[athandle]);

        /* analyze the response (check data mode flag) */
        action_rsp = analyze_action_result(athandle, action_rsp);
        PrintDBG("RAW ACTION (AT_sendcmd) = 0x%x", action_rsp)
        if (action_rsp == ATACTION_RSP_ERROR)
        {
          PrintErr("AT_sendcmd error: parse from rsp")
          LogError(12, ERROR_WARNING);
          return (ATSTATUS_ERROR);
        }
#endif /* RTOS_USED == 1 */

        /* continue if this is an intermediate response */
continue_execution:

        PrintDBG("") /* to avoid a warning */

#if (RTOS_USED == 0)
        /* URC received during AT transaction */
        if (action_rsp == ATACTION_RSP_URC_FORWARDED)
        {
          /* notify user with callback */
          if (register_URC_callback[athandle] != NULL)
          {
            at_status_t retUrc;

            do
            {
              /* get URC response buffer */
              retUrc = ATParser_get_urc(&at_context[athandle], p_rsp_buf);
              if ((retUrc == ATSTATUS_OK) || (retUrc == ATSTATUS_OK_PENDING_URC))
              {
                /* call the URC callback */
                (* register_URC_callback[athandle])(p_rsp_buf);
              }
            } while (retUrc == ATSTATUS_OK_PENDING_URC);
          }
          else
          {
            PrintErr("No valid callback to forward URC")
          }
        }
#endif /* RTOS_USED == 0 */

      } while ((action_rsp == ATACTION_RSP_INTERMEDIATE) ||
               (action_rsp == ATACTION_RSP_IGNORED) ||
               (action_rsp == ATACTION_RSP_URC_FORWARDED) ||
               (action_rsp == ATACTION_RSP_URC_IGNORED));

      if (action_rsp == ATACTION_RSP_FRC_CONTINUE)
      {
        another_cmd_to_send = 1U;
      }
      else
      {
        /* FRC_END, ERRORS,... */
        another_cmd_to_send = 0U;
      }
    }
    else
    {
      PrintErr("Invalid action code")
      LogError(13, ERROR_WARNING);
      return (ATSTATUS_ERROR);
    }

  } while (another_cmd_to_send == 1U);

#if (RTOS_USED == 1)
  /* clear all flags*/
  at_context[athandle].action_flags = ATACTION_RSP_NO_ACTION;
#endif /* RTOS_USED == 1 */

  PrintDBG("action_rsp value = %d", action_rsp)
  if (action_rsp == ATACTION_RSP_ERROR)
  {
    LogError(14, ERROR_WARNING);
    return (ATSTATUS_ERROR);
  }

  return (ATSTATUS_OK);
}


/*Call Back Functions*/
static void msgReceivedCallback(IPC_Handle_t *ipcHandle)
{
  /* Warning ! this function is called under IT */
  uint8_t index = find_index(ipcHandle);

#if (RTOS_USED == 1)
  /* disable irq not required, we are under IT */
  MsgReceived[index]++;

  if (osMessagePut(q_msg_IPC_received_Id, SIG_IPC_MSG, 0U) != osOK)
  {
    PrintErr("q_msg_IPC_received_Id error for SIG_IPC_MSG")
  }

#else
  MsgReceived[index]++;
  /* received during in IDLE state ? this is an URC */
  if (at_context[index].processing_cmd == 0)
  {
    if (register_event_callback[index] != NULL)
    {
      (* register_event_callback[index])();
    }
  }
#endif /* RTOS_USED == 1 */
}

static void msgSentCallback(IPC_Handle_t *ipcHandle)
{
  /* Warning ! this function is called under IT */
  uint8_t index = find_index(ipcHandle);
  at_context[index].dataSent = AT_TRUE;

#if (RTOS_USED == 1)
  (void) osSemaphoreRelease(at_context[index].s_SendConfirm_SemaphoreId);
#endif /* RTOS_USED == 1 */

}

Here msgSentCallback working fine every time interrupt occurred but at time of responding msgReceivedCallback there is waitFromIPC getting ATSTATUS_TIMEOUT.

/*  IPC Code*/

IPC_Status_t IPC_open_uart(IPC_Handle_t *hipc,
                           IPC_Device_t  device,
                           IPC_Mode_t    mode,
                           IPC_RxCallbackTypeDef pRxClientCallback,
                           IPC_TxCallbackTypeDef pTxClientCallback,
                           IPC_CheckEndOfMsgCallbackTypeDef pCheckEndOfMsg)
{
  HAL_StatusTypeDef uart_status;
  /* check the handles */
  if (hipc == NULL)
  {
    return (IPC_ERROR);
  }
  if (pRxClientCallback == NULL)
  {
    return (IPC_ERROR);
  }
  if (pTxClientCallback == NULL)
  {
    return (IPC_ERROR);
  }
  if ((mode != IPC_MODE_UART_CHARACTER) && (mode != IPC_MODE_UART_STREAM))
  {
    return (IPC_ERROR);
  }
  if ((mode == IPC_MODE_UART_CHARACTER) && (pCheckEndOfMsg == NULL))
  {
    return (IPC_ERROR);
  }

  /* Register this channel into the IPC devices list */
  if (g_IPC_Devices_List[device].h_current_channel == NULL)
  {
    /* register this channel as default channel (first call) */
    g_IPC_Devices_List[device].h_current_channel = hipc;
  }
  else if (g_IPC_Devices_List[device].h_inactive_channel == NULL)
  {
    /* another channel already registered and active, register this channel as inactive */
    g_IPC_Devices_List[device].h_inactive_channel = hipc;
  }
  else
  {
    /* supports only 2 channels for same IPC device */
    return (IPC_ERROR);
  }

  /* initialize common RX buffer */
  g_IPC_Devices_List[device].RxChar[0] = (IPC_CHAR_t)('\0');

  PrintDBG("IPC channel %p registered", g_IPC_Devices_List[device].h_current_channel)
  PrintDBG("state 0x%x", g_IPC_Devices_List[device].state)
  PrintDBG("active channel handle: %p", g_IPC_Devices_List[device].h_current_channel)
  PrintDBG("inactive channel handle: %p", g_IPC_Devices_List[device].h_inactive_channel)

  /* select default queue (character or stream) */
  if (ATSTATUS_TIMEOUTmode == IPC_MODE_UART_CHARACTER)
  {
    hipc->RxFifoWrite = RXFIFO_writeCharacter;
  }
#if (IPC_USE_STREAM_MODE == 1U)
  else
  {
    hipc->RxFifoWrite = RXFIFO_writeStream;
  }
#endif /* IPC_USE_STREAM_MODE */

  /* initialize IPC channel parameters */
  hipc->Device_ID = device;
  hipc->Interface.interface_type = g_IPC_Devices_List[device].phy_int.interface_type;
  hipc->Interface.h_uart = g_IPC_Devices_List[device].phy_int.h_uart;
  hipc->State = IPC_STATE_INITIALIZED;

  /* register client callback */
  hipc->RxClientCallback = pRxClientCallback;
  hipc->TxClientCallback = pTxClientCallback;
  hipc->CheckEndOfMsgCallback = pCheckEndOfMsg;
  hipc->Mode = mode;
  hipc->UartBusyFlag = 0U;

  /* init RXFIFO */
  RXFIFO_init(hipc);
#if (IPC_USE_STREAM_MODE == 1U)
  RXFIFO_stream_init(hipc);
#endif /* IPC_USE_STREAM_MODE */

  /* start RX IT */
  uart_status = HAL_UART_Receive_IT(hipc->Interface.h_uart, (uint8_t *)g_IPC_Devices_List[device].RxChar, 1U);
  if (HAL_OK != uart_status)
  {
    return (IPC_ERROR);
  }

  hipc->State = IPC_STATE_ACTIVE;

  return (IPC_OK);
}


IPC_Status_t IPC_send_uart(IPC_Handle_t *hipc, uint8_t *p_TxBuffer, uint16_t bufsize)
{
  /* PrintDBG(">IPC_send: buf@=%p size=%d", aTxBuffer, bufsize) */

  /* check the handles */
  if (hipc == NULL)
  {
    return (IPC_ERROR);
  }

#if (RTOS_USED == 1)
  /* Test if current hipc */
  if (hipc != g_IPC_Devices_List[hipc->Device_ID].h_current_channel)
  {
    return (IPC_ERROR);
  }
#endif /* RTOS_USED */

  /* send string in one block */
  while (true)
  {
    HAL_StatusTypeDef err;
    err = HAL_UART_Transmit_IT(hipc->Interface.h_uart, (uint8_t *)p_TxBuffer, bufsize);
    if (err !=  HAL_BUSY)
    {

      if ((hipc->UartBusyFlag == 1U) && (hipc->Interface.interface_type == IPC_INTERFACE_UART))
      {
        hipc->UartBusyFlag = 0U;
        while (HAL_UART_Receive_IT(hipc->Interface.h_uart, (uint8_t *)g_IPC_Devices_List[hipc->Device_ID].RxChar, 1U) != HAL_OK)
        {

        }
        PrintINFO("Receive rearmed...")
      }
      break;
    }


#if (RTOS_USED == 1)
    (void) osDelay(10U);
#endif /* RTOS_USED */
  }

  return (IPC_OK);
}


IPC_Status_t IPC_receive_uart(IPC_Handle_t *hipc, IPC_RxMessage_t *p_msg)
{
  int16_t unread_msg;

#if (DBG_IPC_RX_FIFO != 0U)
  int16_t free_bytes;
#endif /* DBG_IPC_RX_FIFO */

  if (hipc->Mode == IPC_MODE_UART_CHARACTER)
  {
    /* check the handles */
    if (hipc == NULL)
    {
      PrintErr("IPC_receive err - hipc NULL")
      return (IPC_ERROR);
    }
    if (p_msg == NULL)
    {
      PrintErr("IPC_receive err - p_msg NULL")
      return (IPC_ERROR);
    }

#if (DBG_IPC_RX_FIFO != 0U)
    free_bytes = RXFIFO_getFreeBytes(hipc);
    PrintDBG("free_bytes before msg read=%d", free_bytes)
#endif /* DBG_IPC_RX_FIFO */

    /* read the first unread message */
    unread_msg = RXFIFO_read(hipc, p_msg);
    if (unread_msg == -1)
    {
      PrintErr("IPC_receive err - no unread msg")
      return (IPC_ERROR);
    }

#if (DBG_IPC_RX_FIFO != 0U)
    free_bytes = RXFIFO_getFreeBytes(hipc);
    PrintDBG("free bytes after msg read=%d", free_bytes)
#endif /* DBG_IPC_RX_FIFO */

    if (hipc->State == IPC_STATE_PAUSED)
    {
#if (DBG_IPC_RX_FIFO != 0U)
      /* dump_RX_dbg_infos(hipc, 1, 1); */
      PrintINFO("Resume IPC (paused %d times) %d unread msg", hipc->dbgRxQueue.cpt_RXPause, unread_msg)
#endif /* DBG_IPC_RX_FIFO */

      hipc->State = IPC_STATE_ACTIVE;
      (void) HAL_UART_Receive_IT(hipc->Interface.h_uart, (uint8_t *)g_IPC_Devices_List[hipc->Device_ID].RxChar, 1U);
    }

    if (unread_msg == 0)
    {
      return (IPC_RXQUEUE_EMPTY);
    }
    else
    {
      return (IPC_RXQUEUE_MSG_AVAIL);
    }
  }
  else
  {
    PrintErr("IPC_receive err - IPC mode not matching")
    return (IPC_ERROR);
  }
}

Actually I have Taken a reference from X-CUBE-AWS which is available for STM32L496 micro controller and i am converting them as per STM32H743ZI controller. in STM32L496 code was working fine and in my case at a time of reception occuring a problem.

Next time please enclose code blocks in 3 tildas (~~~) or 3 backticks (```) and try to align/format the code for better readability :slight_smile:

Please be clearer. Are you saying that the test code for the 496 worked EVEN WITH FREERTOS, but using the same code for another MCU (a 743) did not? If so, why would this be a FreeRTOS issue and not an MCU compat issue?

Without FreeRTOS my UART Transmission and reception getting a proper response. that’s why i was thinking may be response not occurred due to FreeRTOS. i am not sure but it’s assumption.

Again, you should be clear. Earlier on you wrote that the proper response comes from the 496. No you write that this depends on the presence of the OS. SO:

  • Which combination(s) work(s)? Target MCU, Hardware board, OS (or none), sample SW suite
  • Which combo(s) do(es) not work? Target MCU, Hardware board, OS (or none), sample SW suite

I mean in STM32H743ZI without FreeRTOS Uart is working fine.