timeouts added to modbus rtu serial i/o handling

pull/2/head
Mateusz Lubecki 2020-09-26 22:33:43 +02:00
rodzic 3a55ebadcb
commit bad16f5a44
3 zmienionych plików z 40 dodań i 4 usunięć

Wyświetl plik

@ -123,7 +123,7 @@ void srl_keep_timeout(srl_context_t *ctx) {
;
}
if (ctx->srl_rx_state != SRL_RX_NOT_CONFIG && ctx->srl_rx_timeout_waiting_enable == 1) {
if ((ctx->srl_rx_state == SRL_WAITING_TO_RX || ctx->srl_rx_state == SRL_RXING ) && ctx->srl_rx_timeout_waiting_enable == 1) {
if (master_time - ctx->srl_rx_waiting_start_time > ctx->srl_rx_timeout_trigger_value_in_msec) {
ctx->port->CR1 &= (0xFFFFFFFF ^ USART_CR1_RE);
ctx->port->CR1 &= (0xFFFFFFFF ^ USART_CR1_RXNEIE);
@ -336,6 +336,9 @@ uint8_t srl_receive_data(srl_context_t *ctx, int num, char start, char stop, cha
return SRL_OK;
}
/**
* This function start the transfer with
*/
uint8_t srl_receive_data_with_instant_timeout(srl_context_t *ctx, int num, char start, char stop, char echo, char len_addr, char len_modifier) {
if (ctx->srl_rx_state == SRL_RXING)
return SRL_BUSY;
@ -480,6 +483,9 @@ void srl_irq_handler(srl_context_t *ctx) {
// raise a flag to signalize that timeout shall be calulated from now.
ctx->srl_rx_timeout_calc_started = 1;
// disable the waiting timeout
ctx->srl_rx_timeout_waiting_enable = 0;
// if there is any data remaining to receive
if (ctx->srl_rx_bytes_counter < ctx->srl_rx_bytes_req) {
@ -680,6 +686,11 @@ void srl_switch_tx_delay(srl_context_t *ctx, uint8_t disable_enable) {
}
}
/**
* This function controls the timeout which is calculated for data reception (when the
* state is set to SRL_RXING). The calculation starts after the first byte appears in
* data register and protect against stalling in the middle of data transfer
*/
void srl_switch_timeout(srl_context_t *ctx, uint8_t disable_enable, uint32_t value) {
if (disable_enable == 1)
ctx->srl_rx_timeout_enable = 1;
@ -697,6 +708,13 @@ void srl_switch_timeout(srl_context_t *ctx, uint8_t disable_enable, uint32_t val
}
}
/**
* This function enables the timeout which is calculated for the waiting state for
* the data reception to begin (the first byte on serial port). It must be called for
* each RX transaction it is required as this timeout is cleared/disabled after the first
* byte received by the serial port (when the state changes from SRL_WAITING_TO_RX to
* SRL_RXING)
*/
void srl_switch_timeout_for_waiting(srl_context_t *ctx, uint8_t disable_enable) {
if (disable_enable == 1)
ctx->srl_rx_timeout_waiting_enable = 1;

Wyświetl plik

@ -16,7 +16,14 @@ int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_regist
uint16_t data = 0;
// iterator through input table and registers table
int i = 0, j = 4;
int i = 0, j = 3;
// rewind the input buffer if the first byte is not valid modbus rtu slave address
if (*input < 1 || *input > 0xF7) {
// don't loop here and assume that the modbus response is shifted only
// by one byte
input++;
}
// 7 bytes is the shortest meaningful Modbus RTU frame
// with a value of single register
@ -31,12 +38,12 @@ int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_regist
output->slave_address = data;
// fetch function code
data = *(input + 2);
data = *(input + 1);
// check if the function code is correct or not
if (data == 0x03 || data == 0x04) {
// fetch the function result lenght in bytes
data = *(input + 3);
data = *(input + 2);
// store amount of registers in this response
output->number_of_registers = data / 2;

Wyświetl plik

@ -165,6 +165,13 @@ int32_t rtu_serial_pool(rtu_pool_queue_t* queue, srl_context_t* serial_context)
switch (rtu_pool) {
case RTU_POOL_IDLE: {
// Enabling the timeout for Modbus-RTU.
// This timeout starts after first received byte and triggers if
// the slave will hang up and stop the transmission before the end of the frame
// It doesn't need to be called each time but this is the only function which takes
// the pointer to serial context
srl_switch_timeout(serial_context, 1, 0);
// check the function it at current queue position
if (queue->function_id[queue->it] == 0x03) {
// read holding registers
@ -240,6 +247,10 @@ int32_t rtu_serial_pool(rtu_pool_queue_t* queue, srl_context_t* serial_context)
srl_receive_data_with_callback(serial_context, rtu_serial_callback);
//srl_receive_data(serial_context, 8, 0, 0, 0, 0, 0);
// enable the timeout in case the RTU slave won't respond
// at all or there is no slaves connected to RS485 bus
srl_switch_timeout_for_waiting(serial_context, 1);
// switch the state
rtu_pool = RTU_POOL_RECEIVING;