AnsweredAssumed Answered

Bug in Serial_LDD Transmission Complete before InterruptTx

Question asked by Sven Kolberg on Oct 1, 2015
Latest reply on Oct 5, 2015 by Sven Kolberg

In the Kinetis Design Studio v3.0.0 I found the following generated Code:

 

 

PE_ISR(ASerialLdd1_Interrupt)

{

  /* {FreeRTOS RTOS Adapter} ISR parameter is passed through the global variable */

  ASerialLdd1_TDeviceDataPtr DeviceDataPrv = INT_UART0_RX_TX__BAREBOARD_RTOS_ISRPARAM;

  register uint32_t StatReg = UART_PDD_ReadInterruptStatusReg(UART0_BASE_PTR); /* Read status register */

  register uint16_t OnErrorFlags = 0U; /* Temporary variable for flags */

  register uint8_t  OnBreakFlag = 0U;  /* Temporary variable flag for OnBreak event */

  register uint16_t Data;              /* Temporary variable for data */

 

  if (StatReg & (UART_S1_NF_MASK | UART_S1_OR_MASK | UART_S1_FE_MASK | UART_S1_PF_MASK)) { /* Is any error flag set? */

    Data = (uint16_t)UART_PDD_GetChar8(UART0_BASE_PTR); /* Read an 8-bit character from receiver */

    if ((StatReg & UART_S1_FE_MASK) != 0U) { /* Is the framing error detected? */

      if (((StatReg & UART_S1_RDRF_MASK) != 0U) && (Data == 0U)) { /* Is the zero character in the receiver? */

        OnBreakFlag++;

        DeviceDataPrv->SerFlag |= BREAK_DETECTED; /* If yes then set the flag */

      } else {

        OnErrorFlags |= LDD_SERIAL_FRAMING_ERROR; /* If yes then set the flag */

      }

    }

    if ((StatReg & UART_S1_OR_MASK) != 0U) { /* Is the overrun error flag set? */

      OnErrorFlags |= LDD_SERIAL_RX_OVERRUN; /* If yes then set the flag */

    }

    if ((StatReg & UART_S1_PF_MASK) != 0U) { /* Is the parity error flag set? */

      OnErrorFlags |= LDD_SERIAL_PARITY_ERROR; /* If yes then set the flag */

    }

    if ((StatReg & UART_S1_NF_MASK) != 0U) { /* Is the noise error flag set? */

      OnErrorFlags |= LDD_SERIAL_NOISE_ERROR; /* If yes then set the flag */

    }

    DeviceDataPrv->ErrFlag |= OnErrorFlags; /* Copy flags status to ErrFlag status variable */

    StatReg &= (uint32_t)(~(uint32_t)UART_S1_RDRF_MASK); /* Clear the receive data flag to discard the errorneous data */

    if (OnBreakFlag != 0U) {

      ASerialLdd1_OnBreak(DeviceDataPrv->UserDataPtr); /* If yes then invoke user event */

    } else {

      ASerialLdd1_OnError(DeviceDataPrv->UserDataPtr); /* Invoke user event */

    }

  }

  if (StatReg & UART_S1_RDRF_MASK) {   /* Is the receiver's interrupt flag set? */

    InterruptRx(DeviceDataPrv);        /* If yes, then invoke the internal service routine. This routine is inlined. */

  }

  if (DeviceDataPrv->SerFlag & ENABLED_TX_INT) { /* Is the transmitter interrupt enabled? */

    if (StatReg & UART_S1_TDRE_MASK) { /* Is the transmitter empty? */

      InterruptTx(DeviceDataPrv);      /* If yes, then invoke the internal service routine. This routine is inlined. */

    }

  }

  if ((UART_PDD_GetTxCompleteInterruptMask(UART0_BASE_PTR) != 0U)  && (StatReg & UART_S1_TC_MASK)) { /* Is a transmission completed? */

    UART_PDD_DisableInterrupt(UART0_BASE_PTR, UART_PDD_INTERRUPT_TRANSMITTER_COMPLETE); /* If yes then disable TX complete interrupt */

    ASerialLdd1_OnTxComplete(DeviceDataPrv->UserDataPtr); /* If yes then invoke user event */

  }

}

 

 

Suppose the Line;

     if (DeviceDataPrv->SerFlag & ENABLED_TX_INT) { /* Is the transmitter interrupt enabled? */

evaluates to true, the InterruptTx will be called and a new char will be send.

 

If coincidentally the Transmission complete flag is set when the StatReg was Read, the Line:

  if ((UART_PDD_GetTxCompleteInterruptMask(UART0_BASE_PTR) != 0U)  && (StatReg & UART_S1_TC_MASK)) { /* Is a transmission completed? */

evaluates to true and the tx complete interrupt will be disabled for the new transfer and the OnTxComplete Event will be called, too.

 

To my understanding, this  behaviour is not correct. The OnTxComplete Event will be called even though a transmission is ongoing.

 

In my Application I used the OnTxComplete to disable the RS485 DriveEnable. But because of this it shows a rather strange behaviour.

 

Is there a way to fix the code?

Outcomes