#include "inc/freeEMS.h"
#include "inc/interrupts.h"
#include "inc/utils.h"
#include "inc/commsCore.h"
#include "inc/commsISRs.h"
Go to the source code of this file.
Defines | |
#define | COMMSISRS_C |
Functions | |
void | sendAndIncrement (unsigned char rawValue) |
Send And Increment. | |
void | receiveAndIncrement (const unsigned char value) |
Receive And Increment. | |
void | resetReceiveState (unsigned char sourceIDState) |
Reset Receive State. | |
void | SCI0ISR () |
Serial Communication Interface 0 ISR. |
This file contains the code for both send and receive of serial bytes through the UART SCI0 device. It is purely interrupt driven and controlled by a set of register and non-register flags that are toggled both inside and outside this file. Some additional helper functions are also kept here.
Definition in file commsISRs.c.
#define COMMSISRS_C |
Definition at line 41 of file commsISRs.c.
void receiveAndIncrement | ( | const unsigned char | value | ) | [inline] |
Receive And Increment.
Store the value and add it to the checksum, then increment the pointer and length.
value | is the byte of data to store in the buffer and add to the checksum. |
Definition at line 81 of file commsISRs.c.
References RXBufferCurrentPosition, RXCalculatedChecksum, and RXPacketLengthReceived.
Referenced by SCI0ISR().
00081 { 00082 *RXBufferCurrentPosition = value; 00083 RXCalculatedChecksum += value; 00084 RXBufferCurrentPosition++; 00085 RXPacketLengthReceived++; 00086 }
void resetReceiveState | ( | unsigned char | sourceIDState | ) |
Reset Receive State.
Reset communications reception to the state provided.
TODO CAN0CTL1 &= CANCTL1_RX_ISR_DISABLE;
TODO CAN0CTL1 |= CANCTL1_RX_ISR_ENABLE;
sourceIDState | is the state to apply to the RX buffer state variable. |
Definition at line 99 of file commsISRs.c.
References COM_SET_CAN0_INTERFACE_ID, COM_SET_SCI0_INTERFACE_ID, RXBufferContentSourceID, RXBufferCurrentPosition, RXCalculatedChecksum, RXPacketLengthReceived, RXStateFlags, SCI0CR2, SCICR2_RX_DISABLE, SCICR2_RX_ENABLE, SCICR2_RX_ISR_DISABLE, and SCICR2_RX_ISR_ENABLE.
Referenced by decodePacketAndRespond(), and SCI0ISR().
00099 { 00100 /* Set the receive buffer pointer to the beginning */ 00101 RXBufferCurrentPosition = (unsigned char*)&RXBuffer; 00102 00103 /* Zero the flags, buffer length and checksum */ 00104 RXPacketLengthReceived = 0; 00105 RXCalculatedChecksum = 0; 00106 RXStateFlags = 0; 00107 00108 /* Set the source ID state (clear all or all but one flag(s)) */ 00109 RXBufferContentSourceID = sourceIDState; 00110 00111 /* Which ever interface we are setting is the one we came from. By definition */ 00112 /* it must be on and we want it to stay on, so just turn off all the others. */ 00113 if(sourceIDState & COM_SET_SCI0_INTERFACE_ID){ 00114 /* Turn off all others here */ 00117 /* SPI ? I2C ? SCI1 ? */ 00118 }else if(sourceIDState & COM_SET_CAN0_INTERFACE_ID){ 00119 /* Turn off all others here */ 00120 /* Only SCI for now */ 00121 SCI0CR2 &= SCICR2_RX_DISABLE; 00122 SCI0CR2 &= SCICR2_RX_ISR_DISABLE; 00123 /* SPI ? I2C ? SCI1 ? */ 00124 }else{ /* If clearing all flags then enable RX on all interfaces */ 00125 /* Only SCI for now */ 00126 SCI0CR2 |= SCICR2_RX_ENABLE; 00127 SCI0CR2 |= SCICR2_RX_ISR_ENABLE; 00130 /* SPI ? I2C ? SCI1 ? */ 00131 } 00132 }
void SCI0ISR | ( | void | ) |
Serial Communication Interface 0 ISR.
SCI0 ISR handles all interrupts for SCI0 by reading flags and acting appropriately. Its functions are to send raw bytes out over the wire from a buffer and to receive bytes from the wire un-escape them, checksum them and store them in a buffer.
TODO Remove the debug code that uses the IO ports to light LEDs during specific actions.
Definition at line 147 of file commsISRs.c.
References BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, CLEAR_ALL_SOURCE_ID_FLAGS, COM_CLEAR_SCI0_INTERFACE_ID, COM_SET_SCI0_INTERFACE_ID, Counter::commsChecksumMismatches, Counters, ESCAPE_BYTE, ESCAPED_ESCAPE_BYTE, ESCAPED_START_BYTE, ESCAPED_STOP_BYTE, PORTA, PORTB, receiveAndIncrement(), resetReceiveState(), RuntimeVars, RX_BUFFER_SIZE, RX_READY_TO_PROCESS, RX_SCI_ESCAPED_NEXT, RX_SCI_NOT_ESCAPED_NEXT, RXBufferContentSourceID, RXBufferCurrentPosition, RXCalculatedChecksum, RXPacketLengthReceived, RXStateFlags, SCI0CR2, SCI0DRL, SCI0SR1, SCICR2_RX_DISABLE, SCICR2_RX_ISR_DISABLE, SCICR2_RX_ISR_ENABLE, SCICR2_TX_ISR_DISABLE, SCICR2_TX_ISR_ENABLE, SCISR1_RX_FRAMING, SCISR1_RX_NOISE, SCISR1_RX_OVERRUN, SCISR1_RX_PARITY, SCISR1_RX_REGISTER_FULL, SCISR1_TX_REGISTER_EMPTY, sendAndIncrement(), Counter::serialEscapePairMismatches, Counter::serialFramingErrors, RuntimeVar::serialISRRuntime, Counter::serialNoiseErrors, Counter::serialOverrunErrors, Counter::serialPacketsOverLength, Counter::serialParityErrors, Counter::serialStartsInsideAPacket, START_BYTE, STOP_BYTE, TCNT, TXBufferCurrentPositionSCI0, TXBufferInUseFlags, TXByteEscaped, and TXPacketLengthToSendSCI0.
00147 { 00148 /* Read the flags register */ 00149 unsigned char flags = SCI0SR1; 00150 /* Note: Combined with reading or writing the data register this also clears the flags. */ 00151 00152 /* Start counting */ 00153 unsigned short start = TCNT; 00154 00155 /* If the RX interrupt is enabled check RX related flags */ 00156 if(SCI0CR2 & SCICR2_RX_ISR_ENABLE){ 00157 /* Grab the received byte from the register */ 00158 unsigned char rawByte = SCI0DRL; 00159 00160 PORTB |= BIT0; 00161 00162 /* Record error conditions always */ 00163 unsigned char resetOnError = 0; 00164 /* If there is noise on the receive line record it */ 00165 if(flags & SCISR1_RX_NOISE){ 00166 Counters.serialNoiseErrors++; 00167 resetOnError++; 00168 }/* If an overrun occurs record it */ 00169 if(flags & SCISR1_RX_OVERRUN){ 00170 Counters.serialOverrunErrors++; 00171 resetOnError++; 00172 }/* If a framing error occurs record it */ 00173 if(flags & SCISR1_RX_FRAMING){ 00174 Counters.serialFramingErrors++; 00175 resetOnError++; 00176 }/* If a parity error occurs record it */ 00177 if(flags & SCISR1_RX_PARITY){ 00178 Counters.serialParityErrors++; 00179 resetOnError++; 00180 } 00181 00182 /* Drop out because of error flags */ 00183 if(resetOnError){ 00184 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS); 00185 PORTB |= BIT1; 00186 return; 00187 } 00188 00189 /* If there is data waiting to be received */ 00190 if(flags & SCISR1_RX_REGISTER_FULL){ 00191 PORTB |= BIT2; 00192 /* Look for a start bresetReceiveStateyte to indicate a new packet */ 00193 if(rawByte == START_BYTE){ 00194 PORTB |= BIT3; 00195 /* If another interface is using it (Note, clear flag, not normal) */ 00196 if(RXBufferContentSourceID & COM_CLEAR_SCI0_INTERFACE_ID){ 00197 /* Turn off our reception */ 00198 SCI0CR2 &= SCICR2_RX_DISABLE; 00199 SCI0CR2 &= SCICR2_RX_ISR_DISABLE; 00200 PORTB |= BIT4; 00201 }else{ 00202 PORTB |= BIT5; 00203 /* If we are using it */ 00204 if(RXBufferContentSourceID & COM_SET_SCI0_INTERFACE_ID){ 00205 /* Increment the counter */ 00206 Counters.serialStartsInsideAPacket++; 00207 } 00208 /* Reset to us using it unless someone else was */ 00209 resetReceiveState(COM_SET_SCI0_INTERFACE_ID); 00210 } 00211 }else if(RXPacketLengthReceived >= RX_BUFFER_SIZE){ 00212 /* Buffer was full, record and reset */ 00213 Counters.serialPacketsOverLength++; 00214 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS); 00215 PORTB |= BIT6; 00216 }else if(RXBufferContentSourceID & COM_SET_SCI0_INTERFACE_ID){ 00217 if(RXStateFlags & RX_SCI_ESCAPED_NEXT){ 00218 PORTB |= BIT7; 00219 /* Clear escaped byte next flag, thanks Karsten! ((~ != !) == (! ~= ~)) == LOL */ 00220 RXStateFlags &= RX_SCI_NOT_ESCAPED_NEXT; 00221 00222 if(rawByte == ESCAPED_ESCAPE_BYTE){ 00223 /* Store and checksum escape byte */ 00224 receiveAndIncrement(ESCAPE_BYTE); 00225 }else if(rawByte == ESCAPED_START_BYTE){ 00226 /* Store and checksum start byte */ 00227 receiveAndIncrement(START_BYTE); 00228 }else if(rawByte == ESCAPED_STOP_BYTE){ 00229 /* Store and checksum stop byte */ 00230 receiveAndIncrement(STOP_BYTE); 00231 }else{ 00232 /* Otherwise reset and record as data is bad */ 00233 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS); 00234 Counters.serialEscapePairMismatches++; 00235 } 00236 }else if(rawByte == ESCAPE_BYTE){ 00237 PORTA |= BIT0; 00238 /* Set flag to indicate that the next byte should be un-escaped. */ 00239 RXStateFlags |= RX_SCI_ESCAPED_NEXT; 00240 }else if(rawByte == STOP_BYTE){ 00241 PORTA |= BIT1; 00242 /* Turn off reception */ 00243 SCI0CR2 &= SCICR2_RX_DISABLE; 00244 SCI0CR2 &= SCICR2_RX_ISR_DISABLE; 00245 00246 /* Bring the checksum back to where it should be */ 00247 unsigned char RXReceivedChecksum = (unsigned char)*(RXBufferCurrentPosition - 1); 00248 RXCalculatedChecksum -= RXReceivedChecksum; 00249 00250 /* Check that the checksum matches */ 00251 if(RXCalculatedChecksum == RXReceivedChecksum){ 00252 /* If it's OK set process flag */ 00253 RXStateFlags |= RX_READY_TO_PROCESS; 00254 PORTA |= BIT2; 00255 }else{ 00256 PORTA |= BIT3; 00257 /* Otherwise reset the state and record it */ 00258 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS); 00259 Counters.commsChecksumMismatches++; 00260 } 00261 }else{ 00262 PORTA |= BIT4; 00263 /* If it isn't special process it! */ 00264 receiveAndIncrement(rawByte); 00265 } 00266 }else{ 00267 /* Do nothing : drop the byte */ 00268 PORTA |= BIT5; 00269 } 00270 } 00271 } 00272 00273 /* If the TX interrupt is enabled check the register empty flag. */ 00274 if((SCI0CR2 & SCICR2_TX_ISR_ENABLE) && (flags & SCISR1_TX_REGISTER_EMPTY)){ 00275 /* Get the byte to be sent from the buffer */ 00276 unsigned char rawValue = *TXBufferCurrentPositionSCI0; 00277 00278 if(TXPacketLengthToSendSCI0 > 0){ 00279 if(TXByteEscaped == 0){ 00280 /* If the raw value needs to be escaped */ 00281 if(rawValue == ESCAPE_BYTE){ 00282 SCI0DRL = ESCAPE_BYTE; 00283 TXByteEscaped = ESCAPED_ESCAPE_BYTE; 00284 }else if(rawValue == START_BYTE){ 00285 SCI0DRL = ESCAPE_BYTE; 00286 TXByteEscaped = ESCAPED_START_BYTE; 00287 }else if(rawValue == STOP_BYTE){ 00288 SCI0DRL = ESCAPE_BYTE; 00289 TXByteEscaped = ESCAPED_STOP_BYTE; 00290 }else{ /* Otherwise just send it */ 00291 sendAndIncrement(rawValue); 00292 } 00293 }else{ 00294 sendAndIncrement(TXByteEscaped); 00295 TXByteEscaped = 0; 00296 } 00297 }else{ /* Length is zero */ 00298 /* Turn off transmission interrupt */ 00299 SCI0CR2 &= SCICR2_TX_ISR_DISABLE; 00300 /* Send the stop byte */ 00301 SCI0DRL = STOP_BYTE; 00302 /* Clear the TX in progress flag */ 00303 TXBufferInUseFlags &= COM_CLEAR_SCI0_INTERFACE_ID; 00304 } 00305 } 00306 00307 /* Record how long the operation took */ 00308 RuntimeVars.serialISRRuntime = TCNT - start; 00309 }
void sendAndIncrement | ( | unsigned char | rawValue | ) | [inline] |
Send And Increment.
Increment the pointer, decrement the length, and send it!
rawValue | is the raw byte to be sent down the serial line. |
Definition at line 64 of file commsISRs.c.
References SCI0DRL, TXBufferCurrentPositionSCI0, and TXPacketLengthToSendSCI0.
Referenced by SCI0ISR().
00064 { 00065 SCI0DRL = rawValue; 00066 TXPacketLengthToSendSCI0--; 00067 TXBufferCurrentPositionSCI0++; 00068 }