This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

SCI interrupt problem

Other Parts Discussed in Thread: TMS320F2812

Hi all,

Im relatively new to the dsp environment. Im using the eZdsp TMS320F2812 from spectrum digital and using CCSv4 to compile my project.

I finally able to use the interrupt for receving and tranmistting - i have tested it using simple algorithm. But in project I am doing a lot of numbers computational, and need to output them to the serial port. Using the same algorithm, for some reason Im getting a different output at my hyperterminal.

I'll explain further below.

I just print a simple array of characters to test the interrupt.

char message1[]={"F2812 - read2 !\n\r"};

and main is as below:

    while(1) {
        ScibRegs.SCITXBUF=message1[index++]; //if no interrupt happens, sending message1 to the transmit
        counter = strlen(message1);            //find the length of message1 so that transmitter know the exact size of it
        while (i<30000) {                    //Delay loop for every the message1
            i++;                            //Increment i while it is in idle state
            //printf("%d\n", i);

            if(j==1) {                        //if interrupt happens, go to idle state
                while(1){                    //in idle state, keep waiting for incoming messages
                    if (k==1) {                //if statement given an EOF reach
                        k=0;                //set the flag of EOF reached and continue transmitting
                        break;
                    }
                }
            }
        }
        i=0;
    }

and my transmit interrupt function

interrupt void SCI_B_TX_isr(void)
{
    if (counter1 == 1) {
        if (index < (counter+1)) ScibRegs.SCITXBUF=send[index++];
        else {index=0;counter1=0;}
    }
    else {
        if (index < (counter+1)) ScibRegs.SCITXBUF=message1[index++];
        else index=0;
    }
    // Reinitialize the PIE for next SCI-A TX-Interrupt
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;   // Acknowledge interrupt to PIE
    return;
}

 

so the basic overview is, keep printing message1 to the serial while there is no receive interrupt. If there an interrupt at receiver, go to the while(1) and keep waiting until EOF reached - EOF is denoted with K==0 hence its breaking out of the loop. Once it broke off the while(1), the program will continue printing message1. The transmit function will always go to the else{} given that there is interrupt received; if receive interrupt happen, it will go to if(counter==1){} to print whatever character is received.

and that worked fine.. i get the character as I wanted, and i got what i expect on my hyperterminal.

eg.

F2812 - read2 !
F2812 - read2 !
F2812 - read2 !
F2812 - read2 !
F2812 - read2 !
F2812 - read2 !
F2812 - read2 !
F2812 - read2 !
F2812 - read2 !
F2812 - read2 !
F2812 - read2 !
F2812 - read2 !
F2812 - read2 !
F2812 - read2 !

But if i port this entire code, and make adjustment to my project, the output of message1 will start look funny; it doesn't print the whole character, sometimes its missing some characters, and quite often doesnt print out the \r\n.

below is what shown in my hyperterminal after I integrate the code to my project:

F2812 - readF2812 - readF2812 - readF2812 - readF2812 - readF2812 - readF2812 - read2F2812 - readF2812 - read2F2812 - readF2812 - read2F2812 - readF2812 - read2F2812 - readF2812 - readF2812 - readF2812 - readF2812 - readF2812 - readF2812 - reaF2812 - readF2812 - readF2812 - readF2812 - readF2812 - readF2812 - readF2812 - reaF2812 - readF2812 - readF2812 - readF2812 - read2F2812 - readF2812 - readF2812 - readF2812 - read2 !
                                                                             F2812 - readF2812 - read2F2812 - read2 F2812 - readF2812 - read2F2812 - read2F2812 - readF2812 - readF2812 - readF2812 - read2F2812 - read2 F2812 - read2F2812 - read2F2812 - readF2812 - read2F2812 - read2F2812 - read2F2812 - read2 F2812 - read2F2812 - read2F2812 - readF2812 - readF2812 - read2 F2812 - read2F2812 - read2 F2812 - read2 F2812 - read2 F2812 - read2 F2812 - read2F2812 - readF2812 - read2 !F2812 - readF2812 - readF2812 - read2F2812 - read2F2812 - readF2812 - readF2812 - read2F2812 - read2 !

comparatively speaking, it is nearly constantly mising the "!", "\r", "\n". but both have exactly the same setting.

if I run my trial code before my while loop, it worked fine, but once i remove the trial code and let my loop to do printing, it messed up.

If I modifiy the interrupt transmit code to be below

interrupt void SCI_B_TX_isr(void)
{
    if (counter1 == 1) {
        if (index < (counter+1)) ScibRegs.SCITXBUF=send[index++];
        else {index=0;counter1=0;}
    }
    else {
        if (index < (17) ScibRegs.SCITXBUF=message1[index++];
        else index=0;
    }
    // Reinitialize the PIE for next SCI-A TX-Interrupt
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;   // Acknowledge interrupt to PIE
    return;
}

where 17 is the string length, it prints out fine and works fine. but it is not possible to have a fix constant in my if statement such as 17 because my string length will always change depending on the floating number generated( this floating number got converted to string at the end).

Anyone has ever experience in this?

Any help will greatly appreciated - i've stuck with this for more than 1 week and still couldnt figure it out.

I really2 appreciate everyones help.

Thank you very much.

Kind regards,

Sucahyo

  • Are you using the FIFO?  If so, what is the trigger setting for the interrupt?

    In your compiler settings, do you have optimization turned on? If yes, try using "volatile" keyword in all variables used by the interrupt (especially "counter" and "index").

    --------

    Also, in your code you have...

                if(j==1) {                        //if interrupt happens, go to idle state

    Where does j get set or cleared?

    --------

    In your interrupt routine, why is there two different counters? (counter1 and counter)

     

    Another consideration, instead of using counter; why not just check if the next character in the string is null ('\0') to detect the end of string?

  • Hi quark,

    Many thanks for your kind reply.

    The optimization is not turned ON in the compiler settings, I left this option blank.

    Also, J got set when there is an received interrupt happen:

    interrupt void SCI_B_RX_isr(void)
    {

     ReceivedChar = ScibRegs.SCIRXBUF.all;
     if (ReceivedChar == 92) {   
                    j=0;
                    k=1;
                    counter = strlen(send);
                    ScibRegs.SCITXBUF = send[index++];
                    strcpy(send, "");
      }

    else if (ReceivedChar == 49) {
                    counter1 =1;
                    j=1;
                    tmp = "1";
                    strcat(send,tmp);
     }

    }

    So pratically, the current operation will resume once the received interrupt == 92 (as a sign of EOF)

    Uh oh..Uhm.. I haven't try checking the next character if its null, will do now and see if I can get something going.

    Thank you very much for your help.

  • I believe you may be overwriting the SCI buffer before it was done sending it out.  Depending on your baud rate, the "while (i<30000)" line may be the problem.  You may want to try using a flag (such as a mutex) to keep from overwriting.

     

    Here is code that attempts to copy what you're trying to do.  I don't know if it'll work as you wish but it may give you some ideas.  When I could, I used some of the same variable names that you did to help make it more understandable to you.

     

    -----

     

    #ifndef BREAKPOINT
    #define BREAKPOINT    asm("        ESTOP0")
    #endif

    typedef enum
    {
        MUTEX_FREE, MUTEX_BUSY
    } mutex_t;


    typedef enum
    {
        SCIST_IDLE, SCIST_RECEIVING, SCIST_TRANSMITTING
    } sciState_t;



    char message1[]={"F2812 - read2 !\n\r"};

    char* sciTxPt;
    char* sciTxPtStop;

    char send[128];    // Send buffer for receive isr
    char *sndPtr;
    char *sndPrtEnd;


    volatile sciState_t  state = SCIST_IDLE;
    volatile mutex_t     sciTxMutex = MUTEX_FREE;

    void main( void )
    {

        /* a bunch of missing init stuff here */
        sndPtr = send;
        sndPtrEnd = send;
       
        for(;;)  // infinite loop
        {
            switch( state )
            {
                case SCIST_IDLE:
                    // Do other stuff until time to transmit
                    // blah blah blah ...
                    // ....
                    // OK, now is time to transmit
                    state = SCIST_TRANSMITTING;
                break;
                           
                case SCIST_TRANSMITTING:
                    if( sciTxMutex == MUTEX_FREE )
                    {   // OK to send next message
                        counter = strlen(message1);
                        sciTxPt = message1;
                        sciTxPtStop = & (message1[counter]);

                        // Send first character
                        sciTxMutex = MUTEX_BUSY;
                        ScibRegs.SCITXBUF = *sciTxPt;
                        sciTxPt++;
                    }
                break;
               
                case SCIST_RECEIVING:
                    // Do nothing???
                break;
                           
                default:
                    // Should NEVER get here!
                    BREAKPOINT;
                    state = SCIST_IDLE;
            } // END switch
        } // END for(;;)
    } // END main

    interrupt void SCI_B_TX_isr(void)
    {
        if( sciTxPt < sciTxPtStop )
        {
            ScibRegs.SCITXBUF = *sciTxPt;
            sciTxPt++;
        }
        else
        {   // Done transmitting.
            sciTxMutex = MUTEX_FREE;
        }

        PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;   // Acknowledge interrupt to PIE
        return;
    }

    interrupt void SCI_B_RX_isr(void)
    {
        static const char receiveStart = 49;
        static const char receiveEnd = 92;

        ReceivedChar = ScibRegs.SCIRXBUF.all;
     
        if( ReceivedChar == receiveStart )
        {
            state = SCIST_RECEIVING;
           
            *sndPtrEnd = '1';        // Append a '1' to "send" string
            sndPtrEnd++;
            *sndPtrEnd = '\0';        // Always NULL terminate string
        }
        else if( ReceivedChar == receiveEnd )
        {
            state = SCIST_IDLE;
           
            // Prepare to transmit the "send" string
            sciTxPt = send;
            sciTxPtStop = sndPtrEnd;

            // Send first character
            sciTxMutex = MUTEX_BUSY;
            ScibRegs.SCITXBUF = *sciTxPt;
            sciTxPt++;
        }
       
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;   // Acknowledge interrupt to PIE
    }

       

  • Hi Sucahyo,

    Did you try to add the character '0' (48  Ascii) to your output?

    Try a simple example using hyperterminal and you'll notice that the number you are receiving from hyperterminal is different. If you want to see this number on hyperterminal you must add the character '0' (48 ascii)  to see it on hyperterminal too.

    Regards

    Gastón

  • Sorry for the other post,  I guessed you was trying to see number on hypertermnal. I have some question for you

    1) Why in the interrupt  you make a conditional?

    2)

    wouldn´t be better to use index  from 0 to the length of the array you want ?

    example:

    counter=sizeof(message1)

     for(index=0;index<counter;index++){ ScibRegs.SCITXBUF=message1[index] };

    Regards

    Gastón