forked from espressif/esp-modbus
freemodbus: fix timer port to use esp_timer instead of group timer
* Original commit: espressif/esp-idf@ee104f8de2
This commit is contained in:
@@ -193,44 +193,14 @@ menu "Modbus configuration"
|
|||||||
If this option is set the Modbus stack uses timer for T3.5 time measurement.
|
If this option is set the Modbus stack uses timer for T3.5 time measurement.
|
||||||
Else the internal UART TOUT timeout is used for 3.5T symbol time measurement.
|
Else the internal UART TOUT timeout is used for 3.5T symbol time measurement.
|
||||||
|
|
||||||
config FMB_TIMER_GROUP
|
config FMB_TIMER_USE_ISR_DISPATCH_METHOD
|
||||||
int "Slave Timer group number"
|
bool "Modbus timer uses ISR dispatch method"
|
||||||
range 0 1
|
|
||||||
default 0
|
|
||||||
help
|
|
||||||
Modbus slave Timer group number that is used for timeout measurement.
|
|
||||||
|
|
||||||
config FMB_TIMER_INDEX
|
|
||||||
int "Slave Timer index in the group"
|
|
||||||
range 0 1
|
|
||||||
default 0
|
|
||||||
help
|
|
||||||
Modbus slave Timer Index in the group that is used for timeout measurement.
|
|
||||||
|
|
||||||
config FMB_MASTER_TIMER_GROUP
|
|
||||||
int "Master Timer group number"
|
|
||||||
range 0 1
|
|
||||||
default FMB_TIMER_GROUP
|
|
||||||
help
|
|
||||||
Modbus master Timer group number that is used for timeout measurement.
|
|
||||||
|
|
||||||
config FMB_MASTER_TIMER_INDEX
|
|
||||||
int "Master Timer index"
|
|
||||||
range 0 1
|
|
||||||
default FMB_TIMER_INDEX
|
|
||||||
help
|
|
||||||
Modbus master Timer Index in the group that is used for timeout measurement.
|
|
||||||
Note: Modbus master and slave should have different timer index to be able to work simultaneously.
|
|
||||||
|
|
||||||
config FMB_TIMER_ISR_IN_IRAM
|
|
||||||
bool "Place timer interrupt handler into IRAM"
|
|
||||||
default n
|
default n
|
||||||
|
select ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
||||||
select UART_ISR_IN_IRAM
|
select UART_ISR_IN_IRAM
|
||||||
help
|
help
|
||||||
This option places Modbus timer IRQ handler into IRAM.
|
If this option is set the Modbus stack uses ISR dispatch method
|
||||||
This allows to avoid delays related to processing of non-IRAM-safe interrupts
|
to send timeout events from the callback function called from ISR.
|
||||||
during a flash write operation (NVS updating a value, or some other
|
|
||||||
flash API which has to perform an read/write operation and disable CPU cache).
|
|
||||||
This option has dependency with the UART_ISR_IN_IRAM option which places UART interrupt
|
This option has dependency with the UART_ISR_IN_IRAM option which places UART interrupt
|
||||||
handler into IRAM to prevent delays related to processing of UART events.
|
handler into IRAM to prevent delays related to processing of UART events.
|
||||||
|
|
||||||
|
@@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "esp_log.h" // for ESP_LOGE macro
|
#include "esp_log.h" // for ESP_LOGE macro
|
||||||
|
#include "esp_timer.h"
|
||||||
#include "mbconfig.h"
|
#include "mbconfig.h"
|
||||||
|
|
||||||
#define INLINE inline
|
#define INLINE inline
|
||||||
@@ -87,6 +88,7 @@
|
|||||||
|
|
||||||
// Define number of timer reloads per 1 mS
|
// Define number of timer reloads per 1 mS
|
||||||
#define MB_TIMER_TICS_PER_MS (20UL)
|
#define MB_TIMER_TICS_PER_MS (20UL)
|
||||||
|
#define MB_TIMER_TICK_TIME_US (1000 / MB_TIMER_TICS_PER_MS) // 50uS = one discreet for timer
|
||||||
|
|
||||||
#define MB_TCP_DEBUG (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) // Enable legacy debug output in TCP module.
|
#define MB_TCP_DEBUG (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) // Enable legacy debug output in TCP module.
|
||||||
|
|
||||||
@@ -142,6 +144,12 @@ typedef enum {
|
|||||||
MB_PORT_IPV6 = 1 /*!< TCP IPV6 addressing */
|
MB_PORT_IPV6 = 1 /*!< TCP IPV6 addressing */
|
||||||
} eMBPortIpVer;
|
} eMBPortIpVer;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
esp_timer_handle_t xTimerIntHandle;
|
||||||
|
USHORT usT35Ticks;
|
||||||
|
BOOL xTimerState;
|
||||||
|
} xTimerContext_t;
|
||||||
|
|
||||||
void vMBPortEnterCritical(void);
|
void vMBPortEnterCritical(void);
|
||||||
void vMBPortExitCritical(void);
|
void vMBPortExitCritical(void);
|
||||||
|
|
||||||
|
@@ -85,9 +85,14 @@ static USHORT usMBMasterPortSerialRxPoll(size_t xEventSize)
|
|||||||
// Call the Modbus stack callback function and let it fill the stack buffers.
|
// Call the Modbus stack callback function and let it fill the stack buffers.
|
||||||
xReadStatus = pxMBMasterFrameCBByteReceived(); // callback to receive FSM
|
xReadStatus = pxMBMasterFrameCBByteReceived(); // callback to receive FSM
|
||||||
}
|
}
|
||||||
|
|
||||||
// The buffer is transferred into Modbus stack and is not needed here any more
|
// The buffer is transferred into Modbus stack and is not needed here any more
|
||||||
uart_flush_input(ucUartNumber);
|
uart_flush_input(ucUartNumber);
|
||||||
ESP_LOGD(TAG, "Received data: %d(bytes in buffer)\n", (uint32_t)usCnt);
|
ESP_LOGD(TAG, "Received data: %d(bytes in buffer)\n", (uint32_t)usCnt);
|
||||||
|
#if !CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
|
vMBMasterSetCurTimerMode(MB_TMODE_T35);
|
||||||
|
pxMBMasterPortCBTimerExpired();
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "%s: bRxState disabled but junk data (%d bytes) received. ", __func__, xEventSize);
|
ESP_LOGE(TAG, "%s: bRxState disabled but junk data (%d bytes) received. ", __func__, xEventSize);
|
||||||
}
|
}
|
||||||
|
@@ -38,89 +38,54 @@
|
|||||||
#include "port.h"
|
#include "port.h"
|
||||||
|
|
||||||
/* ----------------------- Modbus includes ----------------------------------*/
|
/* ----------------------- Modbus includes ----------------------------------*/
|
||||||
#include "sdkconfig.h"
|
|
||||||
#include "mb.h"
|
#include "mb.h"
|
||||||
#include "mbport.h"
|
#include "mbport.h"
|
||||||
#include "driver/timer.h"
|
|
||||||
#include "port_serial_slave.h"
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
|
|
||||||
#define MB_US50_FREQ (20000) // 20kHz 1/20000 = 50mks
|
static const char *TAG = "MBS_TIMER";
|
||||||
#define MB_DISCR_TIME_US (50) // 50uS = one discreet for timer
|
|
||||||
|
|
||||||
#define MB_TIMER_PRESCALLER ((TIMER_BASE_CLK / MB_US50_FREQ) - 1)
|
static xTimerContext_t* pxTimerContext = NULL;
|
||||||
#define MB_TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // convert counter value to seconds
|
|
||||||
#define MB_TIMER_DIVIDER ((TIMER_BASE_CLK / 1000000UL) * MB_DISCR_TIME_US - 1) // divider for 50uS
|
|
||||||
#define MB_TIMER_WITH_RELOAD (1)
|
|
||||||
|
|
||||||
static const USHORT usTimerIndex = CONFIG_FMB_TIMER_INDEX; // Modbus Timer index used by stack
|
|
||||||
static const USHORT usTimerGroupIndex = CONFIG_FMB_TIMER_GROUP; // Modbus Timer group index used by stack
|
|
||||||
static timer_isr_handle_t xTimerIntHandle; // Timer interrupt handle
|
|
||||||
|
|
||||||
static timg_dev_t *MB_TG[2] = {&TIMERG0, &TIMERG1};
|
|
||||||
|
|
||||||
/* ----------------------- Start implementation -----------------------------*/
|
/* ----------------------- Start implementation -----------------------------*/
|
||||||
static void IRAM_ATTR vTimerGroupIsr(void *param)
|
static void IRAM_ATTR vTimerAlarmCBHandler(void *param)
|
||||||
{
|
{
|
||||||
// Retrieve the interrupt status and the counter value
|
pxMBPortCBTimerExpired(); // Timer expired callback function
|
||||||
// from the timer that reported the interrupt
|
pxTimerContext->xTimerState = TRUE;
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
ESP_EARLY_LOGD(TAG, "Slave timeout triggered.");
|
||||||
uint32_t intr_status = MB_TG[usTimerGroupIndex]->int_st_timers.val;
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
||||||
uint32_t intr_status = MB_TG[usTimerGroupIndex]->int_st.val;
|
|
||||||
#endif
|
|
||||||
if (intr_status & BIT(usTimerIndex)) {
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
|
||||||
MB_TG[usTimerGroupIndex]->int_clr_timers.val |= BIT(usTimerIndex);
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
||||||
MB_TG[usTimerGroupIndex]->int_clr.val |= BIT(usTimerIndex);
|
|
||||||
#endif
|
|
||||||
(void)pxMBPortCBTimerExpired(); // Timer callback function
|
|
||||||
MB_TG[usTimerGroupIndex]->hw_timer[usTimerIndex].config.alarm_en = TIMER_ALARM_EN;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BOOL xMBPortTimersInit(USHORT usTim1Timerout50us)
|
BOOL xMBPortTimersInit(USHORT usTimeOut50us)
|
||||||
{
|
{
|
||||||
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
MB_PORT_CHECK((usTim1Timerout50us > 0), FALSE,
|
MB_PORT_CHECK((usTimeOut50us > 0), FALSE,
|
||||||
"Modbus timeout discreet is incorrect.");
|
"Modbus timeout discreet is incorrect.");
|
||||||
esp_err_t xErr;
|
MB_PORT_CHECK(!pxTimerContext, FALSE,
|
||||||
timer_config_t config = {
|
"Modbus timer is already created.");
|
||||||
.alarm_en = TIMER_ALARM_EN,
|
pxTimerContext = calloc(1, sizeof(xTimerContext_t));
|
||||||
.auto_reload = MB_TIMER_WITH_RELOAD,
|
if (!pxTimerContext) {
|
||||||
.counter_dir = TIMER_COUNT_UP,
|
return FALSE;
|
||||||
.divider = MB_TIMER_PRESCALLER,
|
}
|
||||||
.intr_type = TIMER_INTR_LEVEL,
|
pxTimerContext->xTimerIntHandle = NULL;
|
||||||
.counter_en = TIMER_PAUSE,
|
// Save timer reload value for Modbus T35 period
|
||||||
|
pxTimerContext->usT35Ticks = usTimeOut50us;
|
||||||
|
esp_timer_create_args_t xTimerConf = {
|
||||||
|
.callback = vTimerAlarmCBHandler,
|
||||||
|
.arg = NULL,
|
||||||
|
#if CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD
|
||||||
|
.dispatch_method = ESP_TIMER_ISR,
|
||||||
|
#else
|
||||||
|
.dispatch_method = ESP_TIMER_TASK,
|
||||||
|
#endif
|
||||||
|
.name = "MBS_T35timer"
|
||||||
};
|
};
|
||||||
// Configure timer
|
// Create Modbus timer
|
||||||
xErr = timer_init(usTimerGroupIndex, usTimerIndex, &config);
|
esp_err_t xErr = esp_timer_create(&xTimerConf, &(pxTimerContext->xTimerIntHandle));
|
||||||
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
|
if (xErr) {
|
||||||
"timer init failure, timer_init() returned (0x%x).", xErr);
|
return FALSE;
|
||||||
// Stop timer counter
|
}
|
||||||
xErr = timer_pause(usTimerGroupIndex, usTimerIndex);
|
|
||||||
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
|
|
||||||
"stop timer failure, timer_pause() returned (0x%x).", xErr);
|
|
||||||
// Reset counter value
|
|
||||||
xErr = timer_set_counter_value(usTimerGroupIndex, usTimerIndex, 0x00000000ULL);
|
|
||||||
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
|
|
||||||
"timer set value failure, timer_set_counter_value() returned (0x%x).", xErr);
|
|
||||||
// wait3T5_us = 35 * 11 * 100000 / baud; // the 3.5T symbol time for baudrate
|
|
||||||
// Set alarm value for usTim1Timerout50us * 50uS
|
|
||||||
xErr = timer_set_alarm_value(usTimerGroupIndex, usTimerIndex, (uint32_t)(usTim1Timerout50us));
|
|
||||||
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
|
|
||||||
"failure to set alarm failure, timer_set_alarm_value() returned (0x%x).",
|
|
||||||
(uint32_t)xErr);
|
|
||||||
// Register ISR for timer
|
|
||||||
xErr = timer_isr_register(usTimerGroupIndex, usTimerIndex, vTimerGroupIsr,
|
|
||||||
(void*)(uint32_t)usTimerIndex, MB_PORT_TIMER_ISR_FLAG, &xTimerIntHandle);
|
|
||||||
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
|
|
||||||
"timer set value failure, timer_isr_register() returned (0x%x).",
|
|
||||||
(uint32_t)xErr);
|
|
||||||
#endif
|
#endif
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -128,10 +93,12 @@ BOOL xMBPortTimersInit(USHORT usTim1Timerout50us)
|
|||||||
void vMBPortTimersEnable(void)
|
void vMBPortTimersEnable(void)
|
||||||
{
|
{
|
||||||
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
ESP_ERROR_CHECK(timer_pause(usTimerGroupIndex, usTimerIndex));
|
MB_PORT_CHECK((pxTimerContext && pxTimerContext->xTimerIntHandle), ; ,
|
||||||
ESP_ERROR_CHECK(timer_set_counter_value(usTimerGroupIndex, usTimerIndex, 0ULL));
|
"timer is not initialized.");
|
||||||
ESP_ERROR_CHECK(timer_enable_intr(usTimerGroupIndex, usTimerIndex));
|
uint64_t xToutUs = (pxTimerContext->usT35Ticks * MB_TIMER_TICK_TIME_US);
|
||||||
ESP_ERROR_CHECK(timer_start(usTimerGroupIndex, usTimerIndex));
|
esp_timer_stop(pxTimerContext->xTimerIntHandle);
|
||||||
|
esp_timer_start_once(pxTimerContext->xTimerIntHandle, xToutUs);
|
||||||
|
pxTimerContext->xTimerState = FALSE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,21 +106,22 @@ void MB_PORT_ISR_ATTR
|
|||||||
vMBPortTimersDisable(void)
|
vMBPortTimersDisable(void)
|
||||||
{
|
{
|
||||||
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
if( (BOOL)xPortInIsrContext() ) {
|
// Disable timer alarm
|
||||||
timer_group_set_counter_enable_in_isr(usTimerGroupIndex, usTimerIndex, TIMER_PAUSE);
|
esp_timer_stop(pxTimerContext->xTimerIntHandle);
|
||||||
} else {
|
|
||||||
ESP_ERROR_CHECK(timer_pause(usTimerGroupIndex, usTimerIndex));
|
|
||||||
ESP_ERROR_CHECK(timer_set_counter_value(usTimerGroupIndex, usTimerIndex, 0ULL));
|
|
||||||
// Disable timer interrupt
|
|
||||||
ESP_ERROR_CHECK(timer_disable_intr(usTimerGroupIndex, usTimerIndex));
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void vMBPortTimerClose(void)
|
void vMBPortTimerClose(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_FMB_TIMER_PORT_ENABLED
|
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
ESP_ERROR_CHECK(timer_deinit(usTimerGroupIndex, usTimerIndex));
|
// Delete active timer
|
||||||
ESP_ERROR_CHECK(esp_intr_free(xTimerIntHandle));
|
if (pxTimerContext) {
|
||||||
|
if (pxTimerContext->xTimerIntHandle) {
|
||||||
|
esp_timer_stop(pxTimerContext->xTimerIntHandle);
|
||||||
|
esp_timer_delete(pxTimerContext->xTimerIntHandle);
|
||||||
|
}
|
||||||
|
free(pxTimerContext);
|
||||||
|
pxTimerContext = NULL;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@@ -32,176 +32,113 @@
|
|||||||
/* ----------------------- Modbus includes ----------------------------------*/
|
/* ----------------------- Modbus includes ----------------------------------*/
|
||||||
#include "mb_m.h"
|
#include "mb_m.h"
|
||||||
#include "mbport.h"
|
#include "mbport.h"
|
||||||
#include "port_serial_master.h"
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#define MB_US50_FREQ (20000) // 20kHz 1/20000 = 50mks
|
static const char *TAG = "MBM_TIMER";
|
||||||
#define MB_TICK_TIME_US (50) // 50uS = one tick for timer
|
|
||||||
|
|
||||||
#define MB_TIMER_PRESCALLER ((TIMER_BASE_CLK / MB_US50_FREQ) - 1)
|
|
||||||
#define MB_TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER)
|
|
||||||
#define MB_TIMER_DIVIDER ((TIMER_BASE_CLK / 1000000UL) * MB_TICK_TIME_US - 1) // divider for 50uS
|
|
||||||
#define MB_TIMER_WITH_RELOAD (1)
|
|
||||||
|
|
||||||
/* ----------------------- Variables ----------------------------------------*/
|
/* ----------------------- Variables ----------------------------------------*/
|
||||||
static USHORT usT35TimeOut50us;
|
static xTimerContext_t* pxTimerContext = NULL;
|
||||||
|
|
||||||
// Initialize Modbus Timer group and index used by stack
|
|
||||||
static const USHORT usTimerIndex = CONFIG_FMB_MASTER_TIMER_INDEX;
|
|
||||||
static const USHORT usTimerGroupIndex = CONFIG_FMB_MASTER_TIMER_GROUP;
|
|
||||||
static timer_isr_handle_t xTimerIntHandle; // Timer interrupt handle
|
|
||||||
|
|
||||||
static timg_dev_t *MB_TG[2] = { &TIMERG0, &TIMERG1 };
|
|
||||||
|
|
||||||
/* ----------------------- static functions ---------------------------------*/
|
|
||||||
static void IRAM_ATTR vTimerGroupIsr(void *param)
|
|
||||||
{
|
|
||||||
// Retrieve the interrupt status and the counter value
|
|
||||||
// from the timer that reported the interrupt
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
|
||||||
uint32_t intr_status = MB_TG[usTimerGroupIndex]->int_st_timers.val;
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
||||||
uint32_t intr_status = MB_TG[usTimerGroupIndex]->int_st.val;
|
|
||||||
#endif
|
|
||||||
if (intr_status & BIT(usTimerIndex)) {
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
|
||||||
MB_TG[usTimerGroupIndex]->int_clr_timers.val |= BIT(usTimerIndex);
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
||||||
MB_TG[usTimerGroupIndex]->int_clr.val |= BIT(usTimerIndex);
|
|
||||||
#endif
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
|
||||||
MB_TG[usTimerGroupIndex]->hw_timer[usTimerIndex].update = 1;
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
||||||
MB_TG[usTimerGroupIndex]->hw_timer[usTimerIndex].update.update = 1;
|
|
||||||
#endif
|
|
||||||
(void)pxMBMasterPortCBTimerExpired(); // Timer expired callback function
|
|
||||||
// Enable alarm
|
|
||||||
MB_TG[usTimerGroupIndex]->hw_timer[usTimerIndex].config.alarm_en = TIMER_ALARM_EN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------- Start implementation -----------------------------*/
|
/* ----------------------- Start implementation -----------------------------*/
|
||||||
|
static void IRAM_ATTR vTimerAlarmCBHandler(void *param)
|
||||||
|
{
|
||||||
|
pxMBMasterPortCBTimerExpired(); // Timer expired callback function
|
||||||
|
pxTimerContext->xTimerState = TRUE;
|
||||||
|
ESP_EARLY_LOGD(TAG, "Timer mode: (%d) triggered", xMBMasterGetCurTimerMode());
|
||||||
|
}
|
||||||
|
|
||||||
BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us)
|
BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us)
|
||||||
{
|
{
|
||||||
MB_PORT_CHECK((usTimeOut50us > 0), FALSE,
|
MB_PORT_CHECK((usTimeOut50us > 0), FALSE,
|
||||||
"Modbus timeout discreet is incorrect.");
|
"Modbus timeout discreet is incorrect.");
|
||||||
|
MB_PORT_CHECK(!pxTimerContext, FALSE,
|
||||||
|
"Modbus timer is already created.");
|
||||||
|
pxTimerContext = calloc(1, sizeof(xTimerContext_t));
|
||||||
|
if (!pxTimerContext) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
pxTimerContext->xTimerIntHandle = NULL;
|
||||||
// Save timer reload value for Modbus T35 period
|
// Save timer reload value for Modbus T35 period
|
||||||
usT35TimeOut50us = usTimeOut50us;
|
pxTimerContext->usT35Ticks = usTimeOut50us;
|
||||||
esp_err_t xErr;
|
esp_timer_create_args_t xTimerConf = {
|
||||||
timer_config_t config = {
|
.callback = vTimerAlarmCBHandler,
|
||||||
.alarm_en = TIMER_ALARM_EN,
|
.arg = NULL,
|
||||||
.auto_reload = MB_TIMER_WITH_RELOAD,
|
#if CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD
|
||||||
.counter_dir = TIMER_COUNT_UP,
|
.dispatch_method = ESP_TIMER_ISR,
|
||||||
.divider = MB_TIMER_PRESCALLER,
|
#else
|
||||||
.intr_type = TIMER_INTR_LEVEL,
|
.dispatch_method = ESP_TIMER_TASK,
|
||||||
.counter_en = TIMER_PAUSE,
|
#endif
|
||||||
|
.name = "MBM_T35timer"
|
||||||
};
|
};
|
||||||
// Configure timer
|
// Create Modbus timer
|
||||||
xErr = timer_init(usTimerGroupIndex, usTimerIndex, &config);
|
esp_err_t xErr = esp_timer_create(&xTimerConf, &(pxTimerContext->xTimerIntHandle));
|
||||||
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
|
if (xErr) {
|
||||||
"timer init failure, timer_init() returned (0x%x).", (uint32_t)xErr);
|
return FALSE;
|
||||||
// Stop timer counter
|
}
|
||||||
xErr = timer_pause(usTimerGroupIndex, usTimerIndex);
|
|
||||||
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
|
|
||||||
"stop timer failure, timer_pause() returned (0x%x).", (uint32_t)xErr);
|
|
||||||
// Reset counter value
|
|
||||||
xErr = timer_set_counter_value(usTimerGroupIndex, usTimerIndex, 0x00000000ULL);
|
|
||||||
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
|
|
||||||
"timer set value failure, timer_set_counter_value() returned (0x%x).",
|
|
||||||
(uint32_t)xErr);
|
|
||||||
// wait3T5_us = 35 * 11 * 100000 / baud; // the 3.5T symbol time for baudrate
|
|
||||||
// Set alarm value for usTimeOut50us * 50uS
|
|
||||||
xErr = timer_set_alarm_value(usTimerGroupIndex, usTimerIndex, (uint32_t)(usTimeOut50us));
|
|
||||||
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
|
|
||||||
"failure to set alarm failure, timer_set_alarm_value() returned (0x%x).",
|
|
||||||
(uint32_t)xErr);
|
|
||||||
// Register ISR for timer
|
|
||||||
xErr = timer_isr_register(usTimerGroupIndex, usTimerIndex,
|
|
||||||
vTimerGroupIsr, (void*)(uint32_t)usTimerIndex, MB_PORT_TIMER_ISR_FLAG, &xTimerIntHandle);
|
|
||||||
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
|
|
||||||
"timer set value failure, timer_isr_register() returned (0x%x).",
|
|
||||||
(uint32_t)xErr);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set alarm value for usTimerTimeOut50us * 50uS
|
// Set timer alarm value
|
||||||
static BOOL xMBMasterPortTimersEnable(USHORT usTimerTics50us)
|
static BOOL xMBMasterPortTimersEnable(uint64_t xToutUs)
|
||||||
{
|
{
|
||||||
MB_PORT_CHECK((usTimerTics50us > 0), FALSE,
|
MB_PORT_CHECK(pxTimerContext && (pxTimerContext->xTimerIntHandle), FALSE,
|
||||||
"incorrect tick value for timer = (0x%x).",
|
"timer is not initialized.");
|
||||||
(uint32_t)usTimerTics50us);
|
MB_PORT_CHECK((xToutUs > 0), FALSE,
|
||||||
esp_err_t xErr;
|
"incorrect tick value for timer = (0x%llu).", xToutUs);
|
||||||
xErr = timer_pause(usTimerGroupIndex, usTimerIndex); // stop timer
|
esp_timer_stop(pxTimerContext->xTimerIntHandle);
|
||||||
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
|
esp_timer_start_once(pxTimerContext->xTimerIntHandle, xToutUs);
|
||||||
"timer pause failure, timer_pause() returned (0x%x).",
|
pxTimerContext->xTimerState = FALSE;
|
||||||
(uint32_t)xErr);
|
|
||||||
xErr = timer_set_counter_value(usTimerGroupIndex, usTimerIndex, 0ULL); // reset timer
|
|
||||||
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
|
|
||||||
"timer set counter failure, timer_set_counter_value() returned (0x%x).",
|
|
||||||
(uint32_t)xErr);
|
|
||||||
// Set alarm value to number of 50uS ticks
|
|
||||||
xErr = timer_set_alarm_value(usTimerGroupIndex, usTimerIndex,
|
|
||||||
(uint32_t)(usTimerTics50us));
|
|
||||||
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
|
|
||||||
"timer set alarm failure, timer_set_alarm_value() returned (0x%x).",
|
|
||||||
(uint32_t)xErr);
|
|
||||||
xErr = timer_enable_intr(usTimerGroupIndex, usTimerIndex);
|
|
||||||
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
|
|
||||||
"timer enable interrupt failure, timer_enable_intr() returned (0x%x).",
|
|
||||||
(uint32_t)xErr);
|
|
||||||
xErr = timer_start(usTimerGroupIndex, usTimerIndex); // start timer
|
|
||||||
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
|
|
||||||
"timer start failure, timer_start() returned (0x%x).",
|
|
||||||
(uint32_t)xErr);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vMBMasterPortTimersT35Enable(void)
|
void vMBMasterPortTimersT35Enable(void)
|
||||||
{
|
{
|
||||||
USHORT usTimerTicks = usT35TimeOut50us;
|
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
|
uint64_t xToutUs = (pxTimerContext->usT35Ticks * MB_TIMER_TICK_TIME_US);
|
||||||
|
|
||||||
// Set current timer mode, don't change it.
|
// Set current timer mode, don't change it.
|
||||||
vMBMasterSetCurTimerMode(MB_TMODE_T35);
|
vMBMasterSetCurTimerMode(MB_TMODE_T35);
|
||||||
// Set timer period
|
// Set timer alarm
|
||||||
(void)xMBMasterPortTimersEnable(usTimerTicks);
|
(void)xMBMasterPortTimersEnable(xToutUs);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void vMBMasterPortTimersConvertDelayEnable(void)
|
void vMBMasterPortTimersConvertDelayEnable(void)
|
||||||
{
|
{
|
||||||
// Covert time in milliseconds into ticks
|
// Covert time in milliseconds into ticks
|
||||||
USHORT usTimerTicks = ((MB_MASTER_DELAY_MS_CONVERT * 1000) / MB_TICK_TIME_US);
|
uint64_t xToutUs = (MB_MASTER_DELAY_MS_CONVERT * 1000);
|
||||||
|
|
||||||
// Set current timer mode
|
// Set current timer mode
|
||||||
vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY);
|
vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY);
|
||||||
ESP_LOGD(MB_PORT_TAG,"%s Convert delay enable.", __func__);
|
ESP_LOGD(MB_PORT_TAG,"%s Convert delay enable.", __func__);
|
||||||
(void)xMBMasterPortTimersEnable(usTimerTicks);
|
(void)xMBMasterPortTimersEnable(xToutUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vMBMasterPortTimersRespondTimeoutEnable(void)
|
void vMBMasterPortTimersRespondTimeoutEnable(void)
|
||||||
{
|
{
|
||||||
USHORT usTimerTicks = (MB_MASTER_TIMEOUT_MS_RESPOND * 1000 / MB_TICK_TIME_US);
|
uint64_t xToutUs = (MB_MASTER_TIMEOUT_MS_RESPOND * 1000);
|
||||||
|
|
||||||
vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT);
|
vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT);
|
||||||
ESP_LOGD(MB_PORT_TAG,"%s Respond enable timeout.", __func__);
|
ESP_LOGD(MB_PORT_TAG,"%s Respond enable timeout.", __func__);
|
||||||
(void)xMBMasterPortTimersEnable(usTimerTicks);
|
(void)xMBMasterPortTimersEnable(xToutUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MB_PORT_ISR_ATTR
|
void MB_PORT_ISR_ATTR
|
||||||
vMBMasterPortTimersDisable()
|
vMBMasterPortTimersDisable()
|
||||||
{
|
{
|
||||||
if( (BOOL)xPortInIsrContext() ) {
|
// Disable timer alarm
|
||||||
timer_group_set_counter_enable_in_isr(usTimerGroupIndex, usTimerIndex, TIMER_PAUSE);
|
esp_timer_stop(pxTimerContext->xTimerIntHandle);
|
||||||
} else {
|
|
||||||
// Stop timer and then reload timer counter value
|
|
||||||
ESP_ERROR_CHECK(timer_pause(usTimerGroupIndex, usTimerIndex));
|
|
||||||
ESP_ERROR_CHECK(timer_set_counter_value(usTimerGroupIndex, usTimerIndex, 0ULL));
|
|
||||||
// Disable timer interrupt
|
|
||||||
ESP_ERROR_CHECK(timer_disable_intr(usTimerGroupIndex, usTimerIndex));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vMBMasterPortTimerClose(void)
|
void vMBMasterPortTimerClose(void)
|
||||||
{
|
{
|
||||||
ESP_ERROR_CHECK(timer_deinit(usTimerGroupIndex, usTimerIndex));
|
// Delete active timer
|
||||||
ESP_ERROR_CHECK(esp_intr_free(xTimerIntHandle));
|
if (pxTimerContext) {
|
||||||
|
if (pxTimerContext->xTimerIntHandle) {
|
||||||
|
esp_timer_stop(pxTimerContext->xTimerIntHandle);
|
||||||
|
esp_timer_delete(pxTimerContext->xTimerIntHandle);
|
||||||
|
}
|
||||||
|
free(pxTimerContext);
|
||||||
|
pxTimerContext = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,3 +9,4 @@ CONFIG_FMB_TIMER_INDEX=0
|
|||||||
CONFIG_FMB_TIMER_ISR_IN_IRAM=y
|
CONFIG_FMB_TIMER_ISR_IN_IRAM=y
|
||||||
CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200
|
CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200
|
||||||
CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150
|
CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150
|
||||||
|
CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD=y
|
||||||
|
@@ -8,3 +8,4 @@ CONFIG_FMB_TIMER_PORT_ENABLED=y
|
|||||||
CONFIG_FMB_TIMER_GROUP=0
|
CONFIG_FMB_TIMER_GROUP=0
|
||||||
CONFIG_FMB_TIMER_INDEX=0
|
CONFIG_FMB_TIMER_INDEX=0
|
||||||
CONFIG_FMB_TIMER_ISR_IN_IRAM=y
|
CONFIG_FMB_TIMER_ISR_IN_IRAM=y
|
||||||
|
CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD=y
|
||||||
|
@@ -17,3 +17,4 @@ CONFIG_FMB_TIMER_ISR_IN_IRAM=y
|
|||||||
CONFIG_MB_MDNS_IP_RESOLVER=n
|
CONFIG_MB_MDNS_IP_RESOLVER=n
|
||||||
CONFIG_MB_SLAVE_IP_FROM_STDIN=y
|
CONFIG_MB_SLAVE_IP_FROM_STDIN=y
|
||||||
CONFIG_EXAMPLE_CONNECT_IPV6=n
|
CONFIG_EXAMPLE_CONNECT_IPV6=n
|
||||||
|
CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD=y
|
||||||
|
@@ -19,3 +19,4 @@ CONFIG_MB_SLAVE_IP_FROM_STDIN=y
|
|||||||
CONFIG_MB_SLAVE_ADDR=1
|
CONFIG_MB_SLAVE_ADDR=1
|
||||||
CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y
|
CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y
|
||||||
CONFIG_EXAMPLE_CONNECT_IPV6=n
|
CONFIG_EXAMPLE_CONNECT_IPV6=n
|
||||||
|
CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD=y
|
||||||
|
Reference in New Issue
Block a user