2
\$\begingroup\$

If im not wrong, an ISR is supposed to do minimal processing when it receives a data serially(via UART). Im planning on implementing such a protocol for communication between 2 systems via uart. This is a rough situation of how i plan on coding the ISR. Assume 2 system A & B where A is sending a message to B: Keyword is used to indicate start of message(Established-data/length cannot be the keyword). ChannelOK,Length of data,RxLength,RxData,Packet received flag in B's process are default 0.Length of data=no. of(all data)in bytes(ex:if all data=1,Length of data=1)

A's Process                               
 Send Keyword
 Send Length of data
 Send all data                

B's Process
 Rx Interrupt
 enter ISR
 ISR: if(Received Byte == Keyword && !ChannelOK)
      {
        Set ChannelOK 
      }

      if(ChannelOK && RxLength)
      {
       Set Length of data=received byte 
       ChannelOK=0
       RxLength=0
      }

      if(Length of data != 0 && RxData)
      {
        Store Data
        --Length of data
        if(Length of data==0)
        {
         Set Packet received flag
         RxData=0
        }
      } 

      if(ChannelOK)
      {
       Set RxLength
      } 

      if(Length of data)
      {
       Set RxData
      }
     Reset to Interrupt Again

My doubt is: B has so many stuff to do in the ISR while A is sending continuously. Asumming A sends data at 7.5Mbps(11 bits per transfer), the ISR has to reset the interrupt ever (11/7.5M) seconds. This seems very very small. Will data be lost if i fail to reset the interrupt on time or will it be stored in the 16 byte FIFO so that an interrupt can be immediately triggered the second i reset the interrupt or must i slow down A Tx process by waiting for an ACK for each byte(slows down a lot)???

Im a newbie to ISR's.Please do help Any ISR designs or protocols for serial data communication would be useful

Thanks

\$\endgroup\$
  • 1
    \$\begingroup\$ I can't make sense of the second half of your first paragraph. \$\endgroup\$ – Olin Lathrop Feb 12 '16 at 11:47
  • \$\begingroup\$ Keyword will be the a hex value like 0x5A. When the ISR sees this value only it will attempt to store the data following this. Example: 1st byte- 0x5A,2nd byte-3,3rd byte-0x12(cmd),4th byte-some status,5th byte-msg checksum. 0x5a can never be a data or length. It can only indicate the start of a message. Once a complete message is received it has to check for 0x5a to receive again \$\endgroup\$ – Akshay Immanuel D Feb 12 '16 at 11:54
  • \$\begingroup\$ You have 82.5 us for each byte... how long does the your main loop (assuming worst case) take to process everything?. if it 80 us or less then there should not be a problem. This is easy in assembler to estimate.. with higher languages you may have to look at simulating or (gasp!) instrumenting your code and actually measure the loop time (making sure your taking the longest paths through the code). \$\endgroup\$ – Spoon Feb 12 '16 at 12:33
  • \$\begingroup\$ How 82.5us? Thats the problem, I dont want to get down to the bare level of how long each instruction takes(though possible). I want to keep ISR as simple as possible so that the time saved in keeping ISR simple could be concentrated elsewhere \$\endgroup\$ – Akshay Immanuel D Feb 12 '16 at 12:40
1
\$\begingroup\$

I will propose a method that you may find helpful with some modification to suit your needs.

In this method the ISR is so small , it only saves data in an array for later decoding in the main program , two counters are used to detect of received data and decoded data. offcourse you can use pointer instead of the counters.

   ISR:
 { 
    Receivedbytes[i++]= Rxbuffer;
    dataReceived++;
    }

    main:

    void UARTdecode{

    if (dataDecoded<dataRecived)
    {
    Received byte = Receivedbytes[j++];
    ///// where routine 
    if(Received Byte == Keyword && !ChannelOK)
          {
            Set ChannelOK 
          }
    ..
    ..
    ..
    //// end of routine 

    dataDecoded+=x; (where x is the amount of data decoded or message length)
    }

    }

P.S:It is VERY IMPORTANT that i and j are declared as Static variables

You can also check arduino hardware serial library source code , it is open source and it uses ISR to receive data "HardwareSerial.h" in the installation directory

\$\endgroup\$
  • \$\begingroup\$ So your saying i just copy the data in ISR to a buffer and do the entire processing written in my ISR in the main()? \$\endgroup\$ – Akshay Immanuel D Feb 12 '16 at 12:17
  • \$\begingroup\$ Finally I just check if dataDecoded = Length of data+2 \$\endgroup\$ – Akshay Immanuel D Feb 12 '16 at 12:32
  • \$\begingroup\$ yes ! if this is the answer you are looking for , but i still recommand that you take a look at arduino hardware serial library. and please note that the counters i mensioned are important because you have to know which characters in the array you have read and which you havenot . experiment with this and if you still have doubts , post them. \$\endgroup\$ – ElectronS Feb 12 '16 at 12:33
  • \$\begingroup\$ Yes i agree that the counter values need to be static.Thanks :) il have a look at the library. Il Post here if any doubts \$\endgroup\$ – Akshay Immanuel D Feb 12 '16 at 12:43
  • \$\begingroup\$ This looks like a ring buffer implementation \$\endgroup\$ – Akshay Immanuel D Apr 12 '16 at 6:17
2
\$\begingroup\$
B has so many stuff to do in the ISR

No, at least not if you architect the system right. I would keep any decoding logic out of the ISR. Usually my UART interrupt handler grabs the byte from the hardware, clears the interrupt condition, and stuffs the byte into a FIFO. The foreground code can take it from there. Make the FIFO large enough so that the foreground code can run in bursts and the FIFO doesn't overflow between bursts.

If there's just too much to do per byte, then you have a fundamental problem that firmware can't fix. You need a faster processor or slower communication.

\$\endgroup\$
  • \$\begingroup\$ So your saying that i just copy the received data in the ISR to a global buffer{[RxBuffer[Loc++]} and reset the interrupt. In the main() I go & check if the value in RxBuffer[0] is the Keyword. If its the keyword,process RxBuffer[1]--RxBuffer[FinalLoc].If not,Clear the RxBuffer. But how do you know when the complete packet has arrived? By using something like a stack check algorithm where i initialize all loc of the RxBuffer to a defined const value(like keyword but diff value like 0xa5). If the value at RxBuffer[Length+1] != const value, message received. Else complete message not yet Rxd. \$\endgroup\$ – Akshay Immanuel D Feb 12 '16 at 12:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.