X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=firmware%2Fmodbus.c;h=c895c5f30ec71336e08a4820b059b9cfec22f827;hb=087a60aae1ad8d3f96f94601c68910154f884735;hp=4e8456354e1a5385d630eb7f4cd59cff0f6606a3;hpb=885b506cd11fefff2d2653385c9a2725e8167b79;p=openparking.git diff --git a/firmware/modbus.c b/firmware/modbus.c index 4e84563..c895c5f 100644 --- a/firmware/modbus.c +++ b/firmware/modbus.c @@ -14,7 +14,7 @@ #include "clock.h" #include "modbus.h" -#define BUFSIZE 128 // maximum request size +#define BUFSIZE 180 // maximum request size // configure the control pin #define ctl_pin_setup() do { DDRD |= _BV(PD2); } while (0) @@ -28,7 +28,7 @@ typedef uint8_t bufptr_t; #endif static volatile bufptr_t buf_len, tx_ptr; -static volatile uint8_t buffer[BUFSIZE], transmitting;; +static volatile uint8_t buffer[BUFSIZE], transmitting; static volatile uint16_t last_rx; #ifndef mb_unit_id static uint8_t mb_unit_id; @@ -159,7 +159,7 @@ static mb_exception write_single_reg(uint16_t reg, uint16_t val) return MB_OK; } -void modbus_poll() +uint8_t modbus_poll() { bufptr_t packet_len; uint16_t crc; @@ -167,22 +167,14 @@ void modbus_poll() ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { if (transmitting) - return; - - if (buf_len == 0) // nothing received yet - return; + return 0; if (get_clock() - last_rx < REQ_TIMEOUT) // still receiving - return; - - if (buf_len < 4) { // too short - buf_len = 0; - return; - } + return 0; - if (buffer[0] != mb_unit_id) { // not for myself + if (buf_len < 4) { // too short (or not for us) buf_len = 0; - return; + return 0; } transmitting = 1; // disable further reads @@ -197,7 +189,7 @@ void modbus_poll() transmitting = 0; buf_len = 0; } - return; + return 1; } packet_len -= 2; // strip the CRC @@ -207,14 +199,14 @@ void modbus_poll() switch (buffer[1]) { // function case 3: - if (packet_len == 5) + if (packet_len == 6) rv = read_holding_regs( get_word(buffer, 2), get_word(buffer, 4) ); break; case 6: - if (packet_len == 5) + if (packet_len == 6) rv = write_single_reg( get_word(buffer, 2), get_word(buffer, 4) @@ -234,21 +226,35 @@ void modbus_poll() tx_ptr = 0; ctl_pin_on(); UCSR0B |= _BV(UDRIE0); + + return 1; } ISR(USART_RX_vect) { uint8_t rx_byte = UDR0; + clock_t now = get_clock(); + + if (transmitting) // how did we get here? discard it + goto out; - if (transmitting) // discard it - return; + if (buf_len && buffer[0] != mb_unit_id) // not for us + goto out; - buffer[buf_len] = rx_byte; + if (buf_len == BUFSIZE) { // overrun - discard the packet + buffer[0] = 0xFF; + buf_len = 1; + goto out; + } - if (buf_len + 1 < BUFSIZE) // ignore overruns - buf_len++; + if (now - last_rx >= REQ_TIMEOUT) { // new packet; start over + buf_len = 0; + } - last_rx = get_clock(); + // TODO: we can probably calculate the CRC here as well + buffer[buf_len++] = rx_byte; +out: + last_rx = now; } ISR(USART_TX_vect) @@ -261,7 +267,8 @@ ISR(USART_TX_vect) ISR(USART_UDRE_vect) { - if (tx_ptr+1 >= buf_len) { + if (tx_ptr >= buf_len) { + UCSR0A |= _BV(TXC0); // clear the pending TXC flag UCSR0B |= _BV(TXCIE0); // enable xmit complete irq UCSR0B &= ~_BV(UDRIE0); // disable ourselves } else {