int fastcall read(int hnd, void *buf, unsigned count) { static WORD map; int ret; hnd = hnd; if(!screen_initialized) return uart_read_buffer(buf, count); map = MAPPER_MAP1; MAPPER_MAP1 = MAP_RAMDMA; IRQ_TMR_CTRL = TMR_ENABLE; if(string_input((char *)cursor_pos, buf, count)) ret = strlen(buf); else ret = 0; IRQ_TMR_CTRL = TMR_DISABLE; MAPPER_MAP1 = map; return ret; }
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])); } } }