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.

MSP432P401R: Problem with UART

Part Number: MSP432P401R

Hello,

I want to send a data frame through the UART. I have two MSP432 : the one, the master, sends a data frame which is read by the slave. This slave extracts data from the frame and when the data is correct, I want the slave to answer to the master.

For the first part (master -> slave), no problem, the data is sent. Then the part where the slave tests the data is good too. The problem is the send back to the master. I use the same code than for the master, but when the program of the slave is in freerun, the data frame sent is not complete (two last characters are not sent - there is OxFF instead).

I would think that there is a problem in my code, but when I put a stop point and sends the character one after the other, the data frame is completely sent. It's only when I let the program in freerun that there is a problem.

So I thought about an interrupt pending while I'm sending my frame, but I turned off all of them except for the sending, and the pb is the same...

Here is my slave code. In the while(1), I test the data received :

                                    if (G_uint32Data_trame == 0x41464431) // If data received is good (AFD1)
                                    {
                                        encodage_trame_retour_ADC_vers_maitre(); // Function that sends the data frame as an answer to the master
                                        EUSCI_A1->IFG |= EUSCI_A_IFG_TXIFG;// Clear TXIFG flag
                                        EUSCI_A1->IE |= EUSCI_A_IE_TXIE;    // Enable TX interrupt
                                    }

Then I call the function "encodage_trame_retour_ADC_vers_maitre":

void encodage_trame_retour_ADC_vers_maitre(void)
{
    snap_t snap;
    snap_init(&snap);
    snap_set_local_address(&snap,G_uint8Adresse_locale);
    snap_set_peer_address(&snap,1);
    uint8_t in[]={'O','p'}; // Ask For Data, capteur 1
    size_t in_size = sizeof(in)/sizeof(in[0]);
    size_t out_size = snap_encode_bound(&snap,in_size);
    G_uint8Longueur_trame = out_size ; // Variable globale pour dire au programme d'envoi quel nombre d'octets fait la trame codée
    size_t out_pos = 0;
    snap_encode(&snap,in,in_size,G_uint8Trame_retour_ADC_vers_maitre,&out_pos,out_size);
    out_pos --;
}


This function make a data frame with "Op" as data inside.

Then I authorized the interrupts TX :

                                        EUSCI_A1->IFG |= EUSCI_A_IFG_TXIFG;// Clear TXIFG flag
                                        EUSCI_A1->IE |= EUSCI_A_IE_TXIE;    // Enable TX interrupt

And here is my interrupt routine :

    void eUSCIA1IsrHandler(void)
    {
        if (UCA1IFG & UCRXIFG)
            {
            G_uint8ReceptionFlag = 1;
            while(!(UCA1IFG&UCRXIFG));
        G_uint8Tableau_reception_trame[G_uint8Compteur_octet_trame] = UCA1RXBUF;
            }
        UCA1IFG &=~ UCRXIFG;

        if (UCA1IFG & UCTXIFG)
            {
        while (G_uint8Compteur_octet_trame_2 <= (G_uint8Longueur_trame-1)) // G_uint8Longueur_trame contient le nombre total d'octets de la trame codée ; s'adapte donc automatiquement au nombre de data
            {
            while(!(UCA1IFG&UCTXIFG)); // On attend que le buffer de transmission soit prêt
            EUSCI_A1->TXBUF = G_uint8Trame_retour_ADC_vers_maitre[G_uint8Compteur_octet_trame_2]; // Envoi car après car
                G_uint8Compteur_octet_trame_2 ++;
            }
                G_uint8Longueur_trame = 0;
                G_uint8Compteur_octet_trame_2 = 0;
            }
        UCA1IFG &=~ UCTXIFG;
    }

Once again, when I put a stop point (debug point) after the end of the sending (for example in front of  G_uint8Compteur_octet_trame_2 = 0; (see just above), the data frame is complete. When I freerun the program, or when I put the debug point far away, the data frame is not complete and sends a right beginning but sends 0xFF instead of Op.

Thank you in advance

Sylvain

  • >         UCA1IFG &=~ UCTXIFG;

    At this moment, UCTXIFG is (with high probability) not set. Rather, it will come on some time later, after the (n-1)-th packet byte is sent. That means that the ISR will be re-entered with G_uint8Longueur_trame=0. If (as the name suggests) this is declared unsigned, this code will send the first byte of the packet again (due to the "-1"). I can't tie this definitively with your final symptom without seeing the receive logic at the master, but it is something that would change with the timing, e.g. breakpoint.

    Generally, I recommend against directly manipulating UCTXIFG, since that loses some state that might be important. Instead, I suggest setting UCTXIE=1 when you have something to send, then setting UCTXIE=0 when you run out of things to send. What result do you get if you change that line to

    >         UCA1IE &=~ UCTXIE;

  • Hello,

    Thank you for your answer. I tried, it did not work...

    I modified like this :

        void eUSCIA1IsrHandler(void)
        {
            if (UCA1IFG & UCRXIFG)
                {
                G_uint8ReceptionFlag = 1;
                while(!(UCA1IFG&UCRXIFG));
            G_uint8Tableau_reception_trame[G_uint8Compteur_octet_trame] = UCA1RXBUF;
                }
           // UCA1IE &=~ UCRXIE;

            if (UCA1IFG & UCTXIFG)
                {
                    UCA1IE &= ~UCRXIE;
                    while (G_uint8Compteur_octet_trame_2 <= (G_uint8Longueur_trame-1)) // G_uint8Longueur_trame contient le nombre total d'octets de la trame codée ; s'adapte donc automatiquement au nombre de data
                        {
                            while(!(UCA1IFG&UCTXIFG)); // On attend que le buffer de transmission soit prêt
                            EUSCI_A1->TXBUF = G_uint8Trame_retour_ADC_vers_maitre[G_uint8Compteur_octet_trame_2]; // Envoi car après car
                            G_uint8Compteur_octet_trame_2 ++;
                        }
                    G_uint8Longueur_trame = 0;
                    G_uint8Compteur_octet_trame_2 = 0;
                }
            UCA1IE &= ~UCTXIE;
        }

    I thought that a RX interrupt was happening during the sending of the frame, and so I desactivated the RX interrupts, but still not working.

    One more thing : when I send a byte with OP as data, it sends the data frame without OP and with FF instead, but when I send OPKG as data, it sends OP but not KG. It seems that only the two last bytes are not sent, independently of the size of the frame...

    Thank you,

    Sylvain

  • > while (G_uint8Compteur_octet_trame_2 <= (G_uint8Longueur_trame-1)) 

    How is G_uint8LLongueur_frame declared? If (as I suspect) it is unsigned this check will malfunction if G_uint8Longueur_trame==0. Try instead:

    > while (G_uint8Compteur_octet_trame_2 < (G_uint8Longueur_trame)) 

  • Hi Bruce,

    It doesn't change anything.

    I thought that the sending of the data frame would be done inside the interrupt routine, but it is done in the main, three of four lines after the TXIE. See :

                                        if (G_uint32Data_trame == 0x41464431) // Si la data est une demande d'adc (AFD1)
                                        {
                                            encodage_trame_retour_ADC_vers_maitre();
                                            EUSCI_A1->IE |= EUSCI_A_IE_TXIE;    // Enable TX interrupt   ===> THIS is where I launch the sending
                                        }
                                    }
                            else if(G_uint8Adresse_recepteur != G_uint8Adresse_locale && G_uint8Adresse_recepteur != G_uint8Broadcast)
                            {
                                //memset(G_uint8Tableau_reception_trame,0,50);
                                //UCA1TXBUF = 'b';
                            }
                            G_uint32Data_trame = 0;    ====> THIS is where the dataframe is actually sent (after the G_uint32Data_trame line and before the free(response) line)
                            free(response);
                            free(result);
                            memset(G_uint8Tableau_reception_trame,0,15);
                            memset(G_uint8Trame_retour_ADC_vers_maitre,0,15);

    When I put a debug point I can see the complete sending of the data frame. But when I don't put it, the data is not complete.

    Thanks,

  • I can put as many bytes of data as I want, it's always the two last bytes that are like "forgotten".

    Thanks

  • Those two statements appear to be neighbors, so you're probably seeing the IE-setting propagation delay over the bus out to (and back from) the eUSCI. 

    I don't quite understand the significance of the ISR running two clocks earlier/later, but one way to deal with the propagation delay is to read back the IE register after you write it. [My Devil's Advocate says "If you really really need the data to be sent Right Now, you should do it Right Now rather than relying on an ISR to do it".]

  • Thanks for yous answer ; I tried to keep the program in a while like this :

                                        if (G_uint32Data_trame == 0x41464431) // Si la data est une demande d'adc (AFD1)
                                        {
                                            encodage_trame_retour_ADC_vers_maitre();
                                            EUSCI_A1->IE |= EUSCI_A_IE_TXIE;    // Enable TX interrupt
                                            while(!(UCA1IFG&UCTXIE));
                                        }
                                    }
                            else if(G_uint8Adresse_recepteur != G_uint8Adresse_locale && G_uint8Adresse_recepteur != G_uint8Broadcast)
                            {
                                //memset(G_uint8Tableau_reception_trame,0,50);
                                //UCA1TXBUF = 'b';
                            }
                            G_uint32Data_trame = 0;
                            free(response);
                            free(result);
                            memset(G_uint8Tableau_reception_trame,0,15);
                            memset(G_uint8Trame_retour_ADC_vers_maitre,0,15);
                }

    Now the dataframe is sent before the G_uint32Data_trame, while precedently it was sent after.

    But it does not solve the problem..!

    Another idea..?

    Thanks

  • Bruce,

    I finally found the solution... My Tx pin was set in High Z some time after the sending of the dataframe (because I have several slaves on the line), and it was set too early apparently.

    Thank you very much for your help. You taught me things depsite everything!

    Thanks,

    Sylvain