Подтягивание всех изменений с релиза в ветку

This commit is contained in:
2025-11-04 22:02:28 +03:00
parent 7e21fc7f28
commit fbc424e507
25 changed files with 4410 additions and 896 deletions

View File

@@ -23,6 +23,7 @@
- RS_TIM_Handler() в TIMx_IRQHandler вместо HAL_TIM_IRQHandler()
******************************************************************************/
#include "rs_message.h"
#include "modbus_diag.h"
uint8_t RS_Buffer[MSG_SIZE_MAX]; // uart buffer
@@ -34,7 +35,7 @@ extern void RS_TIM_DeInit(TIM_HandleTypeDef *htim);
//-------------------------------------------------------------------
//-------------------------GENERAL FUNCTIONS-------------------------
/**
* @brief Start receive IT.
* @brief Начать прием по прерываниям.
* @param hRS Указатель на хендлер RS.
* @param RS_msg Указатель на структуру сообщения.
* @return RS_RES Статус о состоянии RS после инициализации приема.
@@ -60,7 +61,7 @@ RS_StatusTypeDef RS_Receive_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
// start receiving
__HAL_UART_ENABLE_IT(hRS->huart, UART_IT_IDLE);
uart_res = HAL_UART_Receive_IT(hRS->huart, &hRS->pBufferPtr[hRS->RS_Message_Size], MSG_SIZE_MAX); // receive until ByteCnt+1 byte,
uart_res = HAL_UART_Receive_IT(hRS->huart, &hRS->pBufferPtr[hRS->RS_Message_Size], MSG_SIZE_MAX); // receive until ByteCnt+1 byte,
// then in Callback restart receive for rest bytes
// if receive isnt started - abort RS
@@ -82,7 +83,7 @@ RS_StatusTypeDef RS_Receive_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
}
/**
* @brief Start transmit IT.
* @brief Начать передачу по прерываниям.
* @param hRS Указатель на хендлер RS.
* @param RS_msg Указатель на структуру сообщения.
* @return RS_RES Статус о состоянии RS после инициализации передачи.
@@ -111,7 +112,6 @@ RS_StatusTypeDef RS_Transmit_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
//----------INITIALIZE TRANSMIT-------------
RS_EnableTransmit();
// for(int i = 0; i < hRS->sRS_Timeout; i++);
RS_Set_Busy(hRS); // set RS busy
RS_Set_TX_Flags(hRS); // initialize flags for transmit IT
@@ -145,13 +145,13 @@ RS_StatusTypeDef RS_Transmit_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
}
/**
* @brief Initialize UART and handle RS stucture.
* @brief Инициалазация структуры @ref RS_HandleTypeDef.
* @param hRS Указатель на хендлер RS.
* @param suart Указатель на структуру с настройками UART.
* @param stim Указатель на структуру с настройками таймера.
* @param pRS_BufferPtr Указатель на буффер для приема-передачи по UART. Если он NULL, то поставиться библиотечный буфер.
* @return RS_RES Статус о состоянии RS после инициализации.
* @note Инициализация перефирии и структуры для приема-передачи по RS.
* @details Инициализация перефирии и структуры для приема-передачи по RS.
*/
RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim, uint8_t *pRS_BufferPtr)
{
@@ -166,9 +166,6 @@ RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart, TIM_H
hRS->htim = htim;
if (hRS->sRS_RX_Size_Mode == NULL)
return RS_ERR;
// check that buffer is defined
if (hRS->pBufferPtr == NULL)
{
@@ -182,7 +179,7 @@ RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart, TIM_H
/**
* @brief Abort RS/UART.
* @brief Отменить прием/передачу RS/UART.
* @param hRS Указатель на хендлер RS.
* @param AbortMode Выбор, что надо отменить.
- ABORT_TX: Отмена передачи по ЮАРТ, с очищением флагов TX,
@@ -190,20 +187,14 @@ RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart, TIM_H
- ABORT_RX_TX: Отмена приема и передачи по ЮАРТ,
- ABORT_RS: Отмена приема-передачи RS, с очищением всей структуры.
* @return RS_RES Статус о состоянии RS после аборта.
* @note Отмена работы UART в целом или отмена приема/передачи RS.
Также очищается хендл hRS.
* @details Отмена работы UART в целом или отмена приема/передачи RS.
Также очищается хендл hRS.
*/
RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode)
{
HAL_StatusTypeDef uart_res = 0;
if(hRS->htim)
{
if(hRS->sRS_Timeout) // if timeout setted
HAL_TIM_Base_Stop_IT(hRS->htim); // stop timeout
hRS->htim->Instance->CNT = 0;
__HAL_TIM_CLEAR_IT(hRS->htim, TIM_IT_UPDATE);
}
RS_Timeout_Stop(hRS);
if((AbortMode&ABORT_RS) == 0x00)
{
@@ -237,11 +228,11 @@ RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode)
//-------------------------------------------------------------------
//--------------------CALLBACK/HANDLER FUNCTIONS---------------------
/**
* @brief Handle for starting receive.
* @brief Обработчик для начала приема.
* @param hRS Указатель на хендлер RS.
* @param RS_msg Указатель на структуру сообщения.
* @return RS_RES Статус о состоянии RS после инициализации приема или окончания общения.
* @note Определяет начинать прием команды/ответа или нет.
* @details Определяет начинать прием команды/ответа или нет.
*/
RS_StatusTypeDef RS_Handle_Receive_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
{
@@ -249,9 +240,15 @@ RS_StatusTypeDef RS_Handle_Receive_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *R
switch(hRS->sRS_Mode)
{
case RS_SLAVE_ALWAYS_WAIT: // in slave mode with permanent waiting
RS_RES = RS_Receive_IT(hRS, RS_msg); break; // start receiving again
case RS_SLAVE_TIMEOUT_WAIT: // in slave mode with timeout waiting (start receiving cmd by request)
// В режиме мастер
case RS_MASTER_REQUEST:
RS_Timeout_Start(hRS); // сразу запускаем таймаут и начинаем прием
// В режиме слейв
case RS_SLAVE_ALWAYS_WAIT:
RS_RES = RS_Receive_IT(hRS, RS_msg); // Просто запускаем фоновый прием
break;
case RS_RESERVED:
RS_Set_Free(hRS); RS_RES = RS_OK; break; // end RS communication (set RS unbusy)
}
@@ -263,11 +260,11 @@ RS_StatusTypeDef RS_Handle_Receive_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *R
return RS_RES;
}
/**
* @brief Handle for starting transmit.
* @brief Обработчик для начала передачи.
* @param hRS Указатель на хендлер RS.
* @param RS_msg Указатель на структуру сообщения.
* @return RS_RES Статус о состоянии RS после инициализации передачи.
* @note Определяет отвечать ли на команду или нет.
* @details Определяет отвечать ли на команду или нет.
*/
RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
{
@@ -276,13 +273,14 @@ RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *
switch(hRS->sRS_Mode)
{
case RS_SLAVE_ALWAYS_WAIT: // in slave mode always response
case RS_SLAVE_TIMEOUT_WAIT: // transmit response
case RS_RESERVED: // transmit response
case RS_MASTER_REQUEST: // transmit response
RS_RES = RS_Transmit_IT(hRS, RS_msg); break;
}
if(RS_RES != RS_OK)
{
if(hRS->sRS_Mode < RS_MASTER_START)
if(hRS->sRS_Mode < RS_MASTER_MODE_START)
{
RS_Handle_Receive_Start(hRS, RS_msg);
}
@@ -294,10 +292,10 @@ RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *
}
/**
* @brief UART TX Callback: define behaviour after transmiting message.
* @brief UART TX Callback: коллбек после окончания передачи.
* @param hRS Указатель на хендлер RS.
* @return RS_RES Статус о состоянии RS после обработки приема.
* @note Определяет поведение RS после передачи сообщения.
* @details Определяет поведение RS после передачи сообщения.
*/
RS_StatusTypeDef RS_UART_TxCpltCallback(RS_HandleTypeDef *hRS)
{
@@ -306,24 +304,18 @@ RS_StatusTypeDef RS_UART_TxCpltCallback(RS_HandleTypeDef *hRS)
//--------------ENDING TRANSMITTING-------------
RS_Set_TX_End(hRS);
RS_EnableReceive();
// for(int i = 0; i < hRS->sRS_Timeout; i++);
//-----------START RECEIVING or END RS----------
RS_RES = RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
// if(RS_RES != RS_OK)
// {
// __NOP();
// }
return RS_RES;
}
/**
* @brief Handler for UART.
* @brief Обработчик прерывания UART.
* @param hRS Указатель на хендлер RS.
* @note Обрабатывает ошибки если есть и вызывает RS Коллбеки.
* Добавить вызов этой функции в UARTx_IRQHandler() после HAL_UART_IRQHandler().
* @details Обрабатывает ошибки если есть и вызывает RS Коллбеки.
* Добавить вызов этой функции в UARTx_IRQHandler() ВМЕСТО HAL_UART_IRQHandler().
*/
void RS_UART_Handler(RS_HandleTypeDef *hRS)
{
@@ -331,13 +323,14 @@ void RS_UART_Handler(RS_HandleTypeDef *hRS)
{
return;
}
//-------------CHECK IDLE FLAG FIRST-------------
//-------------CHECK IDLE FLAG FIRST-------------
/* Проверяем флаг IDLE в первую очередь - это гарантирует обработку только после idle */
if(__HAL_UART_GET_FLAG(hRS->huart, UART_FLAG_IDLE) && __HAL_UART_GET_IT_SOURCE(hRS->huart, UART_IT_IDLE))
{
__HAL_UART_CLEAR_IDLEFLAG(hRS->huart); // Важно: очистить флаг IDLE
//-------------STANDARD UART HANDLING-------------
HAL_UART_IRQHandler(hRS->huart);
hRS->f.RX_Continue = 0;
// Если прием активен и мы получили IDLE - это конец фрейма
if(RS_Is_RX_Busy(hRS) && hRS->f.RX_Ongoing)
@@ -356,29 +349,23 @@ void RS_UART_Handler(RS_HandleTypeDef *hRS)
// Парсим наше сообщение
RS_StatusTypeDef parse_res = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr);
// Проверяем адрес Modbus перед обработкой
if(hRS->pMessagePtr->MbAddr != hRS->ID)
// Если сообещине принято корректно
if(parse_res == RS_OK)
{
// Чужое сообщение - игнорируем и начинаем новый прием
RS_Abort(hRS, ABORT_RX);
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
return;
}
// Если сообещине принято корректно - отвечаем на него
if(parse_res != RS_SKIP)
{
if(hRS->htim)
{
// Останавливаем таймаут
if(hRS->sRS_Timeout)
HAL_TIM_Base_Stop_IT(hRS->htim);
}
RS_Timeout_Stop(hRS);
hRS->lastPacketTick = uwTick;
RS_Response(hRS, hRS->pMessagePtr);
if(hRS->sRS_Mode < RS_MASTER_MODE_START)
RS_Response(hRS, hRS->pMessagePtr); // отвечаем на запрос
else
{
if(hRS->pCallback)
{
hRS->pCallback(hRS, hRS->pMessagePtr); // обрабатываем ответ
RS_Set_Free(hRS); // освобожднаем RS
}
}
}
else
{
@@ -399,19 +386,13 @@ void RS_UART_Handler(RS_HandleTypeDef *hRS)
/* IF NO ERROR OCCURS */
if(hRS->huart->ErrorCode == 0)
{
if(hRS->htim)
// if first byte is received and receive is active
if((hRS->huart->RxXferCount+1 == hRS->huart->RxXferSize) && RS_Is_RX_Busy(hRS))
{
hRS->htim->Instance->CNT = 0; // reset cnt;
/* Start timeout при получении первого байта */
if(hRS->sRS_Timeout) // if timeout setted
if((hRS->huart->RxXferCount+1 == hRS->huart->RxXferSize) && RS_Is_RX_Busy(hRS)) // if first byte is received and receive is active
{
hRS->htim->Instance->ARR = hRS->sRS_Timeout;
HAL_TIM_Base_Start_IT(hRS->htim);
RS_Set_RX_Active_Flags(hRS);
}
RS_Timeout_Start(hRS);
}
RS_Timeout_Update(hRS);
/* RX Callback - теперь НЕ вызываем здесь, ждем IDLE */
@@ -425,6 +406,10 @@ void RS_UART_Handler(RS_HandleTypeDef *hRS)
//----------------ERRORS HANDLER----------------
else
{
if (hRS->huart->ErrorCode & HAL_UART_ERROR_ORE)
{
MB_Diagnostics_CharacterOverrunCnt(); // <-- Обнаружено переполнение
}
//TrackerCnt_Err(hRS->rs_err);
/* de-init uart transfer */
RS_Abort(hRS, ABORT_RS);
@@ -436,10 +421,10 @@ void RS_UART_Handler(RS_HandleTypeDef *hRS)
/**
* @brief Handler for TIM.
* @brief Обработчик прерывания TIM.
* @param hRS Указатель на хендлер RS.
* @note Попадание сюда = таймаут и перезапуск RS приема
* Добавить вызов этой функции в TIMx_IRQHandler() после HAL_TIM_IRQHandler().
* @details Попадание сюда = таймаут и перезапуск RS приема
* Добавить вызов этой функции в TIMx_IRQHandler() ВМЕСТО HAL_TIM_IRQHandler().
*/
void RS_TIM_Handler(RS_HandleTypeDef *hRS)
{
@@ -449,13 +434,73 @@ void RS_TIM_Handler(RS_HandleTypeDef *hRS)
}
HAL_TIM_IRQHandler(hRS->htim);
RS_Abort(hRS, ABORT_RS);
RS_Abort(hRS, ABORT_RS);
if(hRS->pMessagePtr->MbAddr == hRS->ID) // ошибка если таймаут по нашему сообщению
TrackerCnt_Err(hRS->rs_err);
if(hRS->pMessagePtr->MbAddr == hRS->ID) // ошибка если таймаут по нашему сообщению
TrackerCnt_Err(hRS->rs_err);
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
if(hRS->sRS_Mode == RS_MASTER_REQUEST) {
// Мастер: таймаут ответа -> освобождаем для нового запроса
RS_Set_Free(hRS);
} else {
// Слейв: перезапускаем прием
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
}
}
/**
* @brief Запуск таймаута приема.
* @param hRS Указатель на хендлер RS.
* @return RS_RES Статус операции.
* @details Запускает таймер для отсчета времени ожидания следующего байта.
*/
RS_StatusTypeDef RS_Timeout_Start(RS_HandleTypeDef *hRS)
{
if(hRS->htim)
{
hRS->htim->Instance->CNT = 0; // reset cnt;
if(hRS->sRS_Timeout) // if timeout setted
{
hRS->htim->Instance->ARR = hRS->sRS_Timeout;
HAL_TIM_Base_Start_IT(hRS->htim);
RS_Set_RX_Active_Flags(hRS);
}
}
return RS_OK;
}
/**
* @brief Остановка таймаута приема.
* @param hRS Указатель на хендлер RS.
* @return RS_RES Статус операции.
* @details Останавливает таймер ожидания.
*/
RS_StatusTypeDef RS_Timeout_Stop(RS_HandleTypeDef *hRS)
{
if(hRS->htim)
{
// Останавливаем таймаут
if(hRS->sRS_Timeout)
HAL_TIM_Base_Stop_IT(hRS->htim);
hRS->htim->Instance->CNT = 0;
__HAL_TIM_CLEAR_IT(hRS->htim, TIM_IT_UPDATE);
}
return RS_OK;
}
/**
* @brief Обновление (сброс) таймаута приема.
* @param hRS Указатель на хендлер RS.
* @return RS_RES Статус операции.
* @details Сбрасывает счетчик таймера в 0.
*/
RS_StatusTypeDef RS_Timeout_Update(RS_HandleTypeDef *hRS)
{
if(hRS->htim)
{
hRS->htim->Instance->CNT = 0; // reset cnt;
}
return RS_OK;
}
//--------------------CALLBACK/HANDLER FUNCTIONS---------------------
//-------------------------------------------------------------------
@@ -468,7 +513,6 @@ void RS_TIM_Handler(RS_HandleTypeDef *hRS)
* @param hRS Указатель на хендлер RS.
* @param RS_msg Указатель на структуру сообщения.
* @return RS_RES Статус о результате ответа на комманду.
* @note Обработка принятой комманды и ответ на неё.
*/
__weak RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
{
@@ -477,12 +521,11 @@ __weak RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg
}
/**
* @brief Собрать сообщение в буфер UART.
* @brief Пользовательская функция для сбора сообщения в буфер UART.
* @param hRS Указатель на хендлер RS.
* @param RS_msg Указатель на структуру сообщения.
* @param msg_uart_buff Указатель на буффер UART.
* @return RS_RES Статус о результате заполнения буфера.
* @note Заполнение буффера UART из структуры сообщения.
*/
__weak RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff)
{
@@ -491,12 +534,11 @@ __weak RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef
}
/**
* @brief Разпарсить сообщение из буфера UART.
* @brief Пользовательская функция для парса сообщения из буфера UART.
* @param hRS Указатель на хендлер RS.
* @param RS_msg Указатель на структуру сообщения.
* @param msg_uart_buff Указатель на буффер UART.
* @return RS_RES Статус о результате заполнения структуры.
* @note Заполнение структуры сообщения из буффера UART.
*/
__weak RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff)
{