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);
}
}