예제 #1
0
static void retransmit_current_message(modbus* bus)
{
    modbus_message* message;
    list_peek_first(&bus->messageQueue, (void**)&message);

    if(--message->remainingTransmissionAttempts > 0) // retransmit message or drop it?
    {
        uint32_t compensatedReponseTimeout;

        if(message->deferredRetransmissions)
        {
            if(list_count(&bus->messageQueue) > 1) // should a deferred retransmission be attempted and does it make any sense to defer (only makes sense if more than one packet is in the queue)
            {
                if(list_append(&bus->messageQueue, message)) // add to end of queue
                {
                    list_remove(&bus->messageQueue, message); // remove current/first instance of message in transfer queue
                    message->state = MODBUS_MESSAGE_STATE_QUEUED;
                    bus->state = BUS_STATE_IDLE;
                    NABTO_LOG_TRACE(("Deferring retransmission of query (bus=%u, query=%u).", bus->identifier, (int)message));
                    return;
                }
            
                bus->state = BUS_STATE_IDLE;
                NABTO_LOG_TRACE(("Unable to defer query - retransmitting immediately (bus=%u, query=%u)!", bus->identifier, (int)message));
            }
            else
            {
                NABTO_LOG_TRACE(("Query allowed deferrence but transfer queue is empty (bus=%u, query=%u).", bus->identifier, (int)message));
            }
        }

        // retransmit immediately (also used as fallback if deferred retransmission fails)
        compensatedReponseTimeout = (uint32_t)message->maximumResponsetime + calculate_transmission_time(message->frameSize);
        
        uart_flush_receiver(bus->uartChannel);
        uart_write_buffer(bus->uartChannel, message->frame, message->frameSize);

        nabtoSetFutureStamp(&bus->responseTimeout, compensatedReponseTimeout); // time to wait for start of response: transmission time of outgoing frame + maximum response time
        bus->responseSize = 0;
        bus->responseOverrun = false;

        NABTO_LOG_TRACE(("Retransmitting query (bus=%u, remaining attempts=%u).", bus->identifier, (int)message->remainingTransmissionAttempts));
    }
    else
    {
        // mark message as failed
        message->state = MODBUS_MESSAGE_STATE_FAILED;

        // move message from transfer queue to completed list
        list_remove(&bus->messageQueue, message);
        list_append(&completedList, message);

        bus->state = BUS_STATE_IDLE;

        NABTO_LOG_TRACE(("Dropped query due too many retransmissions (bus=%u, message=%u).", bus->identifier, (int)message));
    }
}
예제 #2
0
int fastcall write(int hnd, const void *buf, unsigned count)
{
	static BYTE *b;
	static int c;

    b = buf;
    c = (int)count;

	hnd = hnd;
    if(!screen_initialized)
        return uart_write_buffer(buf, count);
    while(c) {
        char_out(*b);
        b++;
        c--;
    }
    return count;
}
예제 #3
0
void modbus_rtu_master_tick(void)
{
    modbus* bus;

    // tick all busses
    for(bus = busses; bus < (busses + MODBUS_NUMBER_OF_BUSSES); bus++)
    {
        modbus_state oldState;

        oldState = bus->state;

        switch(bus->state)
        {
        case BUS_STATE_IDLE:
            {
                modbus_message* message;
                if(list_peek_first(&bus->messageQueue, (void**)&message)) // is there a message waiting to be sent
                {
                    if(message->state == MODBUS_MESSAGE_STATE_DISCARDED) // has message been discared by the application while waiting in the queue?
                    {
                        list_remove(&bus->messageQueue, message);

                        modbus_rtu_master_release_message(message);

                        NABTO_LOG_TRACE(("Completing discard request (bus=%u, query=%u).", bus->identifier, (int)message));
                    }
                    else // start transferring the message
                    {
                        uint32_t compensatedReponseTime = message->maximumResponsetime + calculate_transmission_time(message->frameSize);

                        NABTO_LOG_TRACE(("Sending query (bus=%u, timeout=%u, compensated timeout=%u).", bus->identifier, (int)message->maximumResponsetime, (int)compensatedReponseTime));

                        uart_flush_receiver(bus->uartChannel);
                        uart_write_buffer(bus->uartChannel, message->frame, message->frameSize);

                        message->state = MODBUS_MESSAGE_STATE_TRANSFERRING;

                        nabtoSetFutureStamp(&bus->responseTimeout, compensatedReponseTime); // time to wait for start of response: transmission time of outgoing frame + maximum response time
                        bus->responseSize = 0;
                        bus->responseOverrun = false;

                        bus->state = BUS_STATE_BUSY;
                        
                        NABTO_LOG_TRACE(("Query sent (bus=%u, timeout=%u, compensated timeout=%u).", bus->identifier, (int)message->maximumResponsetime, (int)compensatedReponseTime));
                        NABTO_LOG_BUFFER(NABTO_LOG_SEVERITY_LEVEL_TRACE, ("Query (length=%u): (shown with CRC)", (int)message->frameSize), message->frame, message->frameSize);
                    }
                }
            }
            break;

        case BUS_STATE_BUSY:
            {
                uint16_t length;
                
                length = uart_can_read(bus->uartChannel);

                if(length > 0) // has data been received?
                {
                    if(bus->responseOverrun == false) // ignore all data after an overrun has occurred
                    {
                        if((bus->responseSize + length) <= MODBUS_MAXIMUM_FRAME_SIZE) // is there room for the data?
                        {
                            // add data to response buffer
                            uart_read_buffer(bus->uartChannel, bus->response + bus->responseSize, length);
                            bus->responseSize += length;
                        }
                        else // response buffer overrun
                        {
                            uart_flush_receiver(bus->uartChannel); // discard data
                            bus->responseOverrun = true; // mark response as over size
                            NABTO_LOG_TRACE(("Receiving oversize response (bus=%u, oversize length=%u)!", bus->identifier, (int)((bus->responseSize + length) - MODBUS_MAXIMUM_FRAME_SIZE)));
                        }
                    }
                    else
                    {
                        uart_flush_receiver(bus->uartChannel); // discard data
                        NABTO_LOG_TRACE(("Dumping overrun data (bus=%u, length=%u)!", bus->identifier, (int)length));
                    }

                    nabtoSetFutureStamp(&bus->frameCommitTimeout, FRAME_SILENT_DURATION); // reset packet commit timer
                }
                else if(bus->responseSize > 0) // has the response begun
                {
                    if(nabtoIsStampPassed(&bus->frameCommitTimeout)) // has the frame ended
                    {
                        modbus_message* message;
                        list_peek_first(&bus->messageQueue, (void**)&message);

                        if(message->state == MODBUS_MESSAGE_STATE_DISCARDED) // has the message been discarded
                        {
                            list_remove(&bus->messageQueue, message);

                            modbus_rtu_master_release_message(message); // perform actual release of discarded message

                            bus->state = BUS_STATE_IDLE;

                            NABTO_LOG_TRACE(("Received response for dumped query (bus=%u, query=%u, response length=%u).", bus->identifier, (int)message, (int)bus->responseSize));
                        }
                        else
                        {
                            if(modbus_rtu_crc_verify_crc_field(bus->response, bus->responseSize)) // does reponse pass CRC check?
                            {
                                NABTO_LOG_BUFFER(NABTO_LOG_SEVERITY_LEVEL_TRACE, ("Received response (bus=%u, length=%u): (shown with CRC)", bus->identifier, (int)bus->responseSize), bus->response, bus->responseSize);

                                // replace the query in the message with the response (removing CRC)
                                memcpy(message->frame, bus->response, bus->responseSize - 2);
                                message->frameSize = bus->responseSize - 2;

                                message->state = MODBUS_MESSAGE_STATE_COMPLETED; // mark message as completed

                                // move message from transfer queue to completed list
                                list_remove(&bus->messageQueue, message);
                                list_append(&completedList, message);

                                bus->state = BUS_STATE_IDLE;

                                NABTO_LOG_TRACE(("Received response for query (bus=%u, query=%u).", bus->identifier, (int)message));
                            }
                            else
                            {
                                NABTO_LOG_TRACE(("Received bad response for query (bus=%u, query=%u)!", bus->identifier, (int)message));
                                retransmit_current_message(bus);
                            }
                        }
                    }
                }
                else if(nabtoIsStampPassed(&bus->responseTimeout)) // the response has not begun within the time limit
                {
                    modbus_message* message;
                    list_peek_first(&bus->messageQueue, (void**)&message);

                    NABTO_LOG_TRACE(("No response received (bus=%u, message=%u)!", bus->identifier, (int)message));

                    if(message->state == MODBUS_MESSAGE_STATE_DISCARDED) // has the application discarded the message?
                    {
                        list_remove(&bus->messageQueue, message);

                        modbus_rtu_master_release_message(message); // perform actual release of discarded message

                        bus->state = BUS_STATE_IDLE;
                        
                        NABTO_LOG_TRACE(("Completing discard request (bus=%u, query=%u).", bus->identifier, (int)message));
                    }
                    else // no - just continue and retransmit the message
                    {
                        retransmit_current_message(bus);
                    }
                }
            }
            break;
        }

        if(oldState != bus->state)
        {
            NABTO_LOG_TRACE(("State change in bus %u: %s -> %s", bus->identifier, modbusStateNames[oldState], modbusStateNames[bus->state]));
        }
    }
}
예제 #4
0
static void flush_cache(void)
{
  uart_write_buffer(0, transmitCache, transmitCachePointer);
  transmitCachePointer = 0;
}
예제 #5
0
파일: uart.c 프로젝트: BridgeHill/unabto
void uart_write(uint8_t channel, uint8_t value)
{
  uart_write_buffer(channel, &value, 1);
}