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.

RTOS/LAUNCHXL-CC2640R2: sent break signal via UART

Part Number: LAUNCHXL-CC2640R2
Other Parts Discussed in Thread: CC2640

Tool/software: TI-RTOS

Hi,

I'm trying to send a break signal over UART which is minium 13 bit-times long.

The documentation of CC26xx UART.h says, that can be done in the following way:

__STATIC_INLINE void
UARTBreakCtl(uint32_t ui32Base, bool bBreakState)
{
//
// Check the arguments.
//
 ASSERT(UARTBaseValid(ui32Base));
 
//

// Set the break condition as requested.

//
HWREG(ui32Base + UART_O_LCRH) =

(bBreakState ?

(HWREG(ui32Base + UART_O_LCRH) | UART_LCRH_BRK) :

(HWREG(ui32Base + UART_O_LCRH) & ~(UART_LCRH_BRK)));
 }

There is also the following note:

For proper transmission of a break command, the break must be asserted for at least two complete frames.

Can someone give me a code example using the command? I didn't fully understand, what is meant with the note.

Thank you

best wishes

Maximilian

  • Maximilian,

    I'm waiting to hear back to see how this is used with driverlib. Stay tuned!

    In regards to the note, I'm thinking that you might have to:

    1. enable UARTBreakCtrl( baseAddr , 1)
    2. then send at least to uart frames. I think you could do a UART_Write() with 2 bytes.
    3. Afterwards, you'd disable UARTBreakCtrl (baseAddr, 0)

    Thanks,
    Tom
  • Hi Tom,

    I have already tried this with the following way:

        while (1) {
            HWREG(UART0_BASE + UART_O_LCRH) =
            (true ?
            (HWREG(UART0_BASE + UART_O_LCRH) | UART_LCRH_BRK) :
            (HWREG(UART0_BASE + UART_O_LCRH) & ~(UART_LCRH_BRK)));
    
            GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_ON);
            UART_write(uart, &Break, 1);
            UART_write(uart, &Break, 1);
            HWREG(UART0_BASE + UART_O_LCRH) =
            (false ?
            (HWREG(UART0_BASE + UART_O_LCRH) | UART_LCRH_BRK) :
            (HWREG(UART0_BASE + UART_O_LCRH) & ~(UART_LCRH_BRK)));
    
            Task_sleep(1000 * (1000 / Clock_tickPeriod));
            GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_OFF);
         }

    It compiles, but it seems like the device stucks at the UART_write() command. 

    This is maybe a stupid question, but can you tell me how can i use the CC26xx driver libary? In my UART.h file, the function UARTBreakCtl is not declared as i posted above.

    I'm using the SimpleLink CC2640R2 SDK 1.30.00.25

    Thanks.

    Maximilian

  • 1. enable UARTBreakCtrl( baseAddr , 1)
    2. then send at least to uart frames. I think you could do a UART_Write() with 2 bytes.
    3. Afterwards, you'd disable UARTBreakCtrl (baseAddr, 0)

    If UART_Write() just puts the bytes into the TX FIFO, then the elapsed time is essentially zero.

    An the UART is about to be used to send actual data, so there's likely to be an interrupt handler, which might do strange things when it is told that two unexpected bytes have been sent.

    So I'd guess the proper sequence would be:

    1. wait for the TX FIFO to empty (UARTBusy());
    2. disable the TX interrupt;
    3. enable break;
    4. send two bytes;
    5. wait for the TX FIFO to empty again;
    6. disable break;
    7. re-enable the TX interrupt.

    I don't know if busy-waiting is a good in this application …

  • Clemens Ladisch said:

    So I'd guess the proper sequence would be:

    1. wait for the TX FIFO to empty (UARTBusy());
    2. disable the TX interrupt;
    3. enable break;
    4. send two bytes;
    5. wait for the TX FIFO to empty again;
    6. disable break;
    7. re-enable the TX interrupt.

    I have tried this in following way:

        while (1) {
    
            GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_ON);
    
            if(UARTBusy(UART0_BASE) == false) {
                UARTIntDisable(UART0_BASE, UART_INT_TX);
                UARTBreakCtl(UART0_BASE, true);
                UART_write(uart, 0x00, 1);
                UART_write(uart, 0x00, 1);
                }
            if(UARTBusy(UART0_BASE) == false) {
                UARTBreakCtl(UART0_BASE, false);
                UARTIntEnable(UART0_BASE, UART_INT_TX);
            }
    
            GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_OFF);
    
            Task_sleep(1000 * (1000 / Clock_tickPeriod));
        }

    In the moment i have no Oszilloscope available, so I am trying to figure it out with the LED1 if the code is working. 

    According to the Code, the LED1 should have to blink, but it doesn't. It stays on all the time. 

    I'm quiete new in programming. Can you give me a hint what could be wrong?

    best wishes

    Maximilian

  • An "if" does not implement a wait. To wait until the UART is not busy, use code like this:

    while (UARTBusy(UART0_BASE))
        ;  // do nothing

    And if UART_write() wants a buffer pointer, giving it 0x00 will just make it blow up; you have to use a one-byte buffer (or a single call with a two-byte buffer).

  • Hi,

    also while will not work.

    unsigned char LIN_break[2] = {0x55, 0x55};
    

        while(UARTBusy(UART0_BASE)); // wait until UART is available
    
        UARTIntDisable(UART0_BASE, UART_INT_TX); //Disable tx Interrupt
        UARTBreakCtl(UART0_BASE, true);     //set Break
    //    Task_sleep(1050 / Clock_tickPeriod); //assert two frame times
    
        UART_write(uart, &LIN_break, 2);
        while(UARTBusy(UART0_BASE)); //wait until UART is available
    
        UARTBreakCtl(UART0_BASE, false);        //unset Break
        UARTIntEnable(UART0_BASE, UART_INT_TX); //enable UART Interrupt
    

    The device hangs at the UART_write() command. If i comment these line out, it run, but no break is generated.

  • Hello,

    does nobody know how to implement the break?

    best wishes

    Maximilian
  • For master, if the UART Tx pin could be assigned as a GPIO mode, you can set it to the mode and then generate the falling-edge signal for the break with 13-bit low state or more for between 677us and 1ms, and then you can drive it to high and then simply swith the mode to UART mode. Slave can recognze the low state as a break-signal.

    or utiilize 9600bps mode to generate the break-signal by using 0x00 and then switch to 19200bps mode and then Sync(0x55) + PID.

    In my experience, GPIO driving is easier than the baud rate switching.

    For salve, you can use the same approach. at first, the UART Rx pin should be used as a GPIO and the pin should generate an interrupt/system event for falling-edge and rising-edge.

    When the edge is triggered, you need to check for the pair and also the duration between fallding and rising, if the duration exceeded 1ms, the signal should be discard.

    And if successfully, break signal is detected well, immediately switch to UART mode to receive Sync + PID. during UART operation, if received data is not what you want,  you need to immediately switch to GPIO mode again to detect the break signal again. 19200bps is used during UART operation.

    BR,
    Ji Won

  • Ji Won Lee said:
    For master, if the UART Tx pin could be assigned as a GPIO mode, you can set it to the mode and then generate the falling-edge signal for the break with 13-bit low state or more for between 677us and 1ms, and then you can drive it to high and then simply swith the mode to UART mode. Slave can recognze the low state as a break-signal.

    In my hardware design, this will be my fallback solution.

    Ji Won Lee said:
    or utiilize 9600bps mode to generate the break-signal by using 0x00 and then switch to 19200bps mode and then Sync(0x55) + PID.

    This is at the moment my solution which is working. The disadvantage is, i have no control above the inter-Byte Space between Break and Sync Byte because i have to close the UART, switch the baudrate and enable it again. 

    I've descided to use the CC2640 because i thougt, the generation of the break signal is easy. 

    it seems to be not :-/

  • Anyway, GPIO driving is much easier than baud-rate switching to handle the break-signal and IBS.
    Good luck.
  • Today, Rx implementation is done through the return flag of scifUartRxGetChar() API Sensor Controller is providing.
    This case doesn't need to use GPIO triggering.

    uint16 return_value = scifUartRxGetChar();
    uint8 rx_data = return_value & 0x00ff;
    if ( (rx_data == 0x00) && (return_value & 0x0300) )
    {
    //Display_print0(dispHandle, 2, 0, "\r\nBreak or Frame error detected\r\n");
    setBreakSignalDetect(TRUE);
    }
  • I think you are talking about recieving, but i want to transmit a break signal.

    It's not a very serious way, but for the moment i sent the break via baud-rate switching and it works.

  • I know.

    I just intended to share my things with you and others.

    I also generated the break-signal through the APIs Sensor Controller provides.

           if(dev_idx == MAIN_CENTRAL_DEVICE_NODE)

           {      

               // Enable baud rate generation

               scifUartSetBaudRate(9600);    

               scifUartTxPutChar(stBuff.data_buff[0]);

               scifWaitOnNbl(500);

               // Enable baud rate generation

               scifUartSetBaudRate(19200);            

               scifUartTxPutChars(&stBuff.data_buff[1], u8Length-1);

    BR,

    Ji Won

  • Hi,

    did you also create a custom hardware?

    If yes, which module or package are you using?

    At the moment I'm trying to flash my custom board with the cc2640 launchpad and searching for board.h file for the innocomm bm15 module

    best wishes

    Maximilian
  • Yes, I am using our custom board and it can be programmed through Launchpad board without the jumpers.

    And our board is simply including the CC2640R2-Q1 chipset. Not module.

    BR,

    Ji Won