#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 44 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 84 of file commsISRs.c.
References RXBufferCurrentPosition, RXCalculatedChecksum, and RXPacketLengthReceived.
Referenced by SCI0ISR().
00084 { 00085 *RXBufferCurrentPosition = value; 00086 RXCalculatedChecksum += value; 00087 RXBufferCurrentPosition++; 00088 RXPacketLengthReceived++; 00089 }
void resetReceiveState | ( | unsigned char | sourceIDState | ) |
Reset Receive State.
Reset communications reception to the state provided.
sourceIDState | is the state to apply to the RX buffer state variable. |
Definition at line 102 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().
00102 { 00103 /* Set the receive buffer pointer to the beginning */ 00104 RXBufferCurrentPosition = (unsigned char*)&RXBuffer; 00105 00106 /* Zero the flags, buffer length and checksum */ 00107 RXPacketLengthReceived = 0; 00108 RXCalculatedChecksum = 0; 00109 RXStateFlags = 0; 00110 00111 /* Set the source ID state (clear all or all but one flag(s)) */ 00112 RXBufferContentSourceID = sourceIDState; 00113 00114 /* Which ever interface we are setting is the one we came from. By definition */ 00115 /* it must be on and we want it to stay on, so just turn off all the others. */ 00116 if(sourceIDState & COM_SET_SCI0_INTERFACE_ID){ 00117 /* Turn off all others here */ 00120 /* SPI ? I2C ? SCI1 ? */ 00121 }else if(sourceIDState & COM_SET_CAN0_INTERFACE_ID){ 00122 /* Turn off all others here */ 00123 /* Only SCI for now */ 00124 SCI0CR2 &= SCICR2_RX_DISABLE; 00125 SCI0CR2 &= SCICR2_RX_ISR_DISABLE; 00126 /* SPI ? I2C ? SCI1 ? */ 00127 }else{ /* If clearing all flags then enable RX on all interfaces */ 00128 /* Only SCI for now */ 00129 SCI0CR2 |= SCICR2_RX_ENABLE; 00130 SCI0CR2 |= SCICR2_RX_ISR_ENABLE; 00133 /* SPI ? I2C ? SCI1 ? */ 00134 } 00135 }
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.
Definition at line 150 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.
00150 { 00151 /* Read the flags register */ 00152 unsigned char flags = SCI0SR1; 00153 /* Note: Combined with reading or writing the data register this also clears the flags. */ 00154 00155 /* Start counting */ 00156 unsigned short start = TCNT; 00157 00158 /* If the RX interrupt is enabled check RX related flags */ 00159 if(SCI0CR2 & SCICR2_RX_ISR_ENABLE){ 00160 /* Grab the received byte from the register */ 00161 unsigned char rawByte = SCI0DRL; 00162 00163 PORTB |= BIT0; 00164 00165 /* Record error conditions always */ 00166 unsigned char resetOnError = 0; 00167 /* If there is noise on the receive line record it */ 00168 if(flags & SCISR1_RX_NOISE){ 00169 Counters.serialNoiseErrors++; 00170 resetOnError++; 00171 }/* If an overrun occurs record it */ 00172 if(flags & SCISR1_RX_OVERRUN){ 00173 Counters.serialOverrunErrors++; 00174 resetOnError++; 00175 }/* If a framing error occurs record it */ 00176 if(flags & SCISR1_RX_FRAMING){ 00177 Counters.serialFramingErrors++; 00178 resetOnError++; 00179 }/* If a parity error occurs record it */ 00180 if(flags & SCISR1_RX_PARITY){ 00181 Counters.serialParityErrors++; 00182 resetOnError++; 00183 } 00184 00185 /* Drop out because of error flags */ 00186 if(resetOnError){ 00187 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS); 00188 PORTB |= BIT1; 00189 return; 00190 } 00191 00192 /* If there is data waiting to be received */ 00193 if(flags & SCISR1_RX_REGISTER_FULL){ 00194 PORTB |= BIT2; 00195 /* Look for a start bresetReceiveStateyte to indicate a new packet */ 00196 if(rawByte == START_BYTE){ 00197 PORTB |= BIT3; 00198 /* If another interface is using it (Note, clear flag, not normal) */ 00199 if(RXBufferContentSourceID & COM_CLEAR_SCI0_INTERFACE_ID){ 00200 /* Turn off our reception */ 00201 SCI0CR2 &= SCICR2_RX_DISABLE; 00202 SCI0CR2 &= SCICR2_RX_ISR_DISABLE; 00203 PORTB |= BIT4; 00204 }else{ 00205 PORTB |= BIT5; 00206 /* If we are using it */ 00207 if(RXBufferContentSourceID & COM_SET_SCI0_INTERFACE_ID){ 00208 /* Increment the counter */ 00209 Counters.serialStartsInsideAPacket++; 00210 } 00211 /* Reset to us using it unless someone else was */ 00212 resetReceiveState(COM_SET_SCI0_INTERFACE_ID); 00213 } 00214 }else if(RXPacketLengthReceived >= RX_BUFFER_SIZE){ 00215 /* Buffer was full, record and reset */ 00216 Counters.serialPacketsOverLength++; 00217 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS); 00218 PORTB |= BIT6; 00219 }else if(RXBufferContentSourceID & COM_SET_SCI0_INTERFACE_ID){ 00220 if(RXStateFlags & RX_SCI_ESCAPED_NEXT){ 00221 PORTB |= BIT7; 00222 /* Clear escaped byte next flag, thanks Karsten! ((~ != !) == (! ~= ~)) == LOL */ 00223 RXStateFlags &= RX_SCI_NOT_ESCAPED_NEXT; 00224 00225 if(rawByte == ESCAPED_ESCAPE_BYTE){ 00226 /* Store and checksum escape byte */ 00227 receiveAndIncrement(ESCAPE_BYTE); 00228 }else if(rawByte == ESCAPED_START_BYTE){ 00229 /* Store and checksum start byte */ 00230 receiveAndIncrement(START_BYTE); 00231 }else if(rawByte == ESCAPED_STOP_BYTE){ 00232 /* Store and checksum stop byte */ 00233 receiveAndIncrement(STOP_BYTE); 00234 }else{ 00235 /* Otherwise reset and record as data is bad */ 00236 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS); 00237 Counters.serialEscapePairMismatches++; 00238 } 00239 }else if(rawByte == ESCAPE_BYTE){ 00240 PORTA |= BIT0; 00241 /* Set flag to indicate that the next byte should be un-escaped. */ 00242 RXStateFlags |= RX_SCI_ESCAPED_NEXT; 00243 }else if(rawByte == STOP_BYTE){ 00244 PORTA |= BIT1; 00245 /* Turn off reception */ 00246 SCI0CR2 &= SCICR2_RX_DISABLE; 00247 SCI0CR2 &= SCICR2_RX_ISR_DISABLE; 00248 00249 /* Bring the checksum back to where it should be */ 00250 unsigned char RXReceivedChecksum = (unsigned char)*(RXBufferCurrentPosition - 1); 00251 RXCalculatedChecksum -= RXReceivedChecksum; 00252 00253 /* Check that the checksum matches */ 00254 if(RXCalculatedChecksum == RXReceivedChecksum){ 00255 /* If it's OK set process flag */ 00256 RXStateFlags |= RX_READY_TO_PROCESS; 00257 PORTA |= BIT2; 00258 }else{ 00259 PORTA |= BIT3; 00260 /* Otherwise reset the state and record it */ 00261 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS); 00262 Counters.commsChecksumMismatches++; 00263 } 00264 }else{ 00265 PORTA |= BIT4; 00266 /* If it isn't special process it! */ 00267 receiveAndIncrement(rawByte); 00268 } 00269 }else{ 00270 /* Do nothing : drop the byte */ 00271 PORTA |= BIT5; 00272 } 00273 } 00274 } 00275 00276 /* If the TX interrupt is enabled check the register empty flag. */ 00277 if((SCI0CR2 & SCICR2_TX_ISR_ENABLE) && (flags & SCISR1_TX_REGISTER_EMPTY)){ 00278 /* Get the byte to be sent from the buffer */ 00279 unsigned char rawValue = *TXBufferCurrentPositionSCI0; 00280 00281 if(TXPacketLengthToSendSCI0 > 0){ 00282 if(TXByteEscaped == 0){ 00283 /* If the raw value needs to be escaped */ 00284 if(rawValue == ESCAPE_BYTE){ 00285 SCI0DRL = ESCAPE_BYTE; 00286 TXByteEscaped = ESCAPED_ESCAPE_BYTE; 00287 }else if(rawValue == START_BYTE){ 00288 SCI0DRL = ESCAPE_BYTE; 00289 TXByteEscaped = ESCAPED_START_BYTE; 00290 }else if(rawValue == STOP_BYTE){ 00291 SCI0DRL = ESCAPE_BYTE; 00292 TXByteEscaped = ESCAPED_STOP_BYTE; 00293 }else{ /* Otherwise just send it */ 00294 sendAndIncrement(rawValue); 00295 } 00296 }else{ 00297 sendAndIncrement(TXByteEscaped); 00298 TXByteEscaped = 0; 00299 } 00300 }else{ /* Length is zero */ 00301 /* Turn off transmission interrupt */ 00302 SCI0CR2 &= SCICR2_TX_ISR_DISABLE; 00303 /* Send the stop byte */ 00304 SCI0DRL = STOP_BYTE; 00305 while(!(SCI0SR1 & 0x80)){/* Wait for ever until able to send then move on */} 00306 SCI0DRL = STOP_BYTE; // nasty hack that works... means at least one and most 2 stops are sent so stuff works, but is messy... there must be a better way. 00307 /* Clear the TX in progress flag */ 00308 TXBufferInUseFlags &= COM_CLEAR_SCI0_INTERFACE_ID; 00309 } 00310 } 00311 00312 /* Record how long the operation took */ 00313 RuntimeVars.serialISRRuntime = TCNT - start; 00314 }
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 67 of file commsISRs.c.
References SCI0DRL, TXBufferCurrentPositionSCI0, and TXPacketLengthToSendSCI0.
Referenced by SCI0ISR().
00067 { 00068 SCI0DRL = rawValue; 00069 TXPacketLengthToSendSCI0--; 00070 TXBufferCurrentPositionSCI0++; 00071 }