|
Summary of Serial Port Interface
Summary of Application (Chatting and Shared Memory)
Application Implementation DetailsThe application we made implemented a simple node to node chat program with a node to node shared variable system. The main program and SharedMemory_Input() functionThe main program simply calls on SharedMemory_Init() function and then enters an infinite loop that calls SharedMemory_Input(), the heart of our application. The SharedMemory_Init() function initializes the serial I/O interface and the I2C bus controller interface. It prints a welcome menu to the serial I/O device (terminal window in our case) and initializes local and shared variable values. The SharedMemory_Input() prints a prompt for the user to enter commands and waits for a command. The prompt appear like "I2C Chat #:\>" where # would actually be the network address of the processor. While waiting, it checks if the processor needs to respond to tasks that could not be handled in the interrupt handler for incoming messages. There are only two possibilities of our implementation. The first is responding to read requests. Another node has requested to read the value from one of our node's shared memory variables. We need to transmit a RETURNED READ message to this node. The interrupt handler already composed the message, we just have to transmit it (this is explain in our description of the interrupt handler). The second request the node has to handle while waiting for a command is displaying received chat messages. Again, the interrupt handler has already buffered the message we need to display (see description of interrupt handler), we just have to print the message across the serial I/O port. After receiving a command, the command string is processed to determine which service to invoke. Local operations are simple to execute:
Remote operations involve the I2C bus controller:
Each command implementation also performs some rudimentary error checking on the command passed by the user. Receiving MessagesThe I2C bus controller calls SharedMemory_Receive(unsigned char* receiveBuffer, unsigned char size) whenever it received a whole frame from the network. Since the I2C bus controller calls this SharedMemory function from inside the interrupt handler for the I2C interface and because we do not use a priority system for interrupts, we cannot send messages or do serial I/O in SharedMemory_Receive(...) because these operations both require the use of interrupt handling. This is problem for receiving READ messages (another node expects a response) and both the CHAT messages and RETURNED READ messages (the local node is expected to serialize the message contents to the terminal window). When the node receives these messages, it buffers the message locally and signals the message has arrived. The program then expects SharedMemory_Input() to handle the rest of the task, except for RETURNED READ, where the command interpreter is already waiting for the message. Receiving a write request is then simple because the node simply copies the assigned new value specified in the message to the shared variable. The biggest issue with our implementation of receiving messages is that it does not scale. High network traffic could cause one message to overwrite another message. This is not an issue for receiving WRITE messages, since the node services this request immediately and this service cannot be interrupted. Likewise, this is not an issue for RETURNED READ. Since the node is busy waiting for the READ request to be responded by a RETURNED READ message, we know that this node has only sent one read request so we needn't worry about another RETURNED READ message happening before we could handle it. Since we simply buffer the RETURNED READ message and return to the READ command interpreter, we are assured the RETURNED READ will be serviced before the buffer is rewritten. The problem lies in CHAT and READ messages, which do no service their requests immediately. The buffers for CHAT and READ messages can be overwritten by new CHAT and READ messages, respectively. A possible fix for this would be using dynamic memory to queue the message, but we were running out of memory space; dynamic allocation seemed like it would exacerbate the problem. Footnotes: 1There is the precondition that no other node is executing a ping at the same time. When a node is pinging the network, it cannot respond to read requests (responding to a read request is not handled in an interrupt handler). Since the node that pings the network is doing a timed wait for a response, it will not see that the other pinging node as alive. Since the program handles the read request later, this could interfere with the pinging node. Our implementation should have checked the sender of the RETURNED READ matches the node we are probing for. Otherwise, we get odd displays. |