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/CC2640: UART_read issue

Part Number: CC2640

Tool/software: TI-RTOS

Hi all,

I try to make a communication between a NXP microcontroller and CC2640 based Sable-X in UART.

The microcontroller send looped data to the CC2640, but the Sable-X don't seems to read it.

I've make some tests with an oscilloscope, and I see that data arrive well on Rx pin of the Sable-x, but when I make UART_read, it return 0 for the first package of data, and then it return loop -1.

The result is that I'm not able to go through the readCallback function.

I have already try example projects like the echo project, and it work, but when I try to make the UART of the Sable-X work with an extern microcontroller, I've got nothing. 

Rx pin and Tx pin are respectively IOID 1 and IOID 0, size of buffer and package of data match and the baudrate is good. 

I don't know why it doesn't work, and it's making me crazy !

Here is some of my code : 

void receiveUART(){
	int ret;
	ret = UART_read(hUart, UART_rxBuf, 20);
	printf("The UART read %d bytes\n", ret));
}


UART_Params* UART_Init(){
    UART_Params_init(&paramsUart);

    paramsUart.writeDataMode = UART_DATA_BINARY;
    paramsUart.readMode = UART_MODE_CALLBACK;
    paramsUart.readCallback = readCallback;
    paramsUart.readEcho = UART_ECHO_OFF;
    paramsUart.readDataMode = UART_DATA_BINARY;
    paramsUart.baudRate  = 115200;
    paramsUart.readReturnMode = UART_RETURN_FULL;
    hUart = UART_open(Board_UART, &paramsUart);
    if (!hUart){
    	printf("UART did not open");
    }
    printf("UART OPEN\n");
    return &paramsUart;
}

thanks in advance.

  • Hi Lucas Poingt,

    The way you use UART_read is incorrect. I send you my code for reference 

    void FIOT_UART_Serial_Rx_Cb(UART_Handle iHandle, void *oData, size_t count)
    {  
      //!***********************************************
      //!Copy UART_Rx_Buf to UART_Tx_Buf
      //!***********************************************    
    
      //!***********************************************
      //!Wake task to process
      //!***********************************************        
      Semaphore_post(UART_hSem);
    } 
    /********************************************************************************
     * FUNCTIONS - TASK
     ********************************************************************************/
    /*!
     ********************************************************************************
     * @fn      void FIOT_UART_CreateTask(void)
     * 
     * @brief   Task creation function for the protocol
     * 
     * @param   None
     * 
     * @return  None
     *
     ********************************************************************************/ 
    void FIOT_UART_CreateTask(void)
    {
      Task_Params TaskParams;
      //!***********************************************
      //!Configure task
      //!***********************************************    
      Task_Params_init(&TaskParams);
      TaskParams.stack          = UART_TaskStack;
      TaskParams.stackSize  = UART_TASK_STACK_SIZE;
      TaskParams.priority   = UART_TASK_PRIORITY;
    
      Task_construct(&UART_TaskStruct, FIOT_UART_TaskFxn, &TaskParams, NULL);
    }
    /*!
     ********************************************************************************
     * @fn      void FIOT_UART_InitTask(void)
     * 
     * @brief   Initilize UART layer
     * 
     * @param   None
     * 
     * @return  None
     *
     ********************************************************************************/
    void FIOT_UART_InitTask(void)
    {
      //!***********************************************
      //!Initilize UART
      //!***********************************************
      UART_Params uParams;
        
      UART_Params_init(&uParams);
      
      uParams.writeDataMode  = UART_DATA_BINARY;
      uParams.readDataMode   = UART_DATA_BINARY;
      uParams.readReturnMode = UART_RETURN_FULL;
      uParams.readMode       = UART_MODE_CALLBACK;
      uParams.readCallback   = FIOT_UART_Serial_Rx_Cb;
    
      UART_uHandle = UART_open(Board_UART,&uParams);    
      //!***********************************************
      //!Initilize Semaphore
      //!***********************************************    
      Semaphore_Params sParams;
      Semaphore_Params_init(&sParams);
      sParams.mode = Semaphore_Mode_BINARY;
    
      Semaphore_construct(&UART_sSem, 0, &sParams);
      UART_hSem = Semaphore_handle(&UART_sSem); 
    }
    /*!
     ********************************************************************************
     * @fn      void FIOT_UART_TaskFxn(UArg a0, UArg a1)
     * 
     * @brief   Application task entry point for the protocol.
     * 
     * @param   a0, a1 - not used.
     * 
     * @return  None
     *
     ********************************************************************************/
    void FIOT_UART_TaskFxn(UArg a0, UArg a1)
    {               
      //!***********************************************
      //!Initilize uart layer
      //!***********************************************    
      FIOT_UART_InitTask();
      //!***********************************************
      //!Loop of uart layer
      //!***********************************************        
      for (;;)
      {
        //!***********************************************
        //!Refesh to read new Data
        //!***********************************************    
        UART_read(UART_uHandle, &UART_Rx, 1);
    
        Semaphore_pend(UART_hSem, BIOS_WAIT_FOREVER);
        //!***********************************************
        //!Process Data
        //!***********************************************  
      }
    }

  • Hi Luu Vy,  thanks for your answer.

    I don't understand why the way I use UART_read is incorect.

    I see that you use semaphore, but I don't need it in my project because the function receiveUART() (where my UART_read function is called) is triggered by interruption (I'm sorry I think I've forgot this detail). This interruption is triggered by the nxp microcontroller when it send data. This interruption is well triggered but I've nothing on my read buffer.

    If I make a read cancel like this :

    void receiveUART(){
    	int ret;
    	ret = UART_read(hUart, UART_rxBuf, 20);
    	printf("The UART read %d bytes\n", ret);
    	UART_readCancel(hUart);
    }

    Then I go in my readCallback function, but it does nothing because it haven't data to process.

    maybe you have other suggestions?

    regards,

    Lucas Poingt

  • Hi Lucas Poingt
    When you call UART_read(hUart, UART_rxBuf, 20), the cc2640 will prepare a buffer to read 20 bytes on UART automatically, and it only go callback handler of UART after cc2640 received 20 bytes. After go to callback handler, the received data was stored in UART_rxBuf and you need call UART_read again to receive the next data.
    That mean you have to call UART_read before you read data on uart.
    In my code, I generate a task to read data on UART. I call the UART_read to read a byte then this task go to sleep. When the UART callback is called, I will wake up this task to process the received data and call UART_read again to read the next byte.
  • Hi Luu Vy, thanks for your time,

    Ok, so I made a callback function like this :

    void readCallback(UART_Handle handle, void *rxBuf, size_t size){
    	/*
    	 * PROCESS DATA
    	 */
    	int ret;
    	ret = UART_read(hUart, UART_rxBuf, 20);
    	printf("The UART read %d bytes\n", ret);
    }

    and I got this output :

    [Cortex_M3_0] The UART read 0 bytes
    The UART read 0 bytes
    The UART read -1 bytes
    The UART read 0 bytes
    The UART read -1 bytes
    The UART read 0 bytes
    The UART read -1 bytes
    The UART read 0 bytes
    The UART read -1 bytes
    The UART read 0 bytes
    The UART read -1 bytes
    The UART read 0 bytes

    actually, I go in the callback function, but my receiveUART function is recalled because of the interruption. And I don't know why I get  "-1", I think it's because of a read error.

    Regards,

    Lucas Poingt

  • Hi Lucas Poingt,

    The received data is stored in your UART_rxBuf. You only red UART_rxBuf to process

    void readCallback(UART_Handle handle, void *rxBuf, size_t size){
        /*
         * PROCESS RECEIVED DATA 
         */    
        printf("The UART read %d bytes\n", size);
        //Read the received data UART_rxBuf
        for(uint8_t i = 0;i<size;i++)
          printf("The Rx UART[%d]= %d bytes\n",i, UART_rxBuf[i]); 
        /*
         * PREPARE BUFFER TO READ THE NEXT 20 BYTES
         */ 
        UART_read(hUart, UART_rxBuf, 20);
    }

  • Hi Luu Vy,

    I've try what you give to me, but given that the first read return 0, the "size" parameter is equal to 0, and it don't make the second "printf".

    another question : when you say "PREPARE BUFFER TO READ THE NEXT 20 BYTES", does it means that I need to make it empty?

    Regards,
    Lucas Poingt
  • Hi Lucas Poingt,

    uint8_t UART_Rx[20]={0};
    void FIOT_UART_Serial_Rx_Cb(UART_Handle iHandle, void *oData, size_t count)
    {  
      //!***********************************************
      //! PROCESS RX DATA
      //!***********************************************   
      //!Len of received data is 20 bytes because callback is called.
      //!The received data is stored UART_Rx. Only read value in UART_Rx buffer to process
        for(uint8_t i = 0;i<20;i++)
          printf("The Rx UART[%d]= %d bytes\n",20, UART_Rx[i]);  
      //!***********************************************
      //! PREPARE BUFFER TO READ THE NEXT 20 BYTES
      //! The old received data is cleared 
      //!***********************************************
      UART_read(UART_uHandle, &UART_Rx, 20);      
    } 
    void FIOT_UART_InitTask(void)
    {
      //!***********************************************
      //!Initilize UART
      //!***********************************************
      UART_Params uParams;
        
      UART_Params_init(&uParams);
      
      uParams.writeDataMode  = UART_DATA_BINARY;
      uParams.readDataMode   = UART_DATA_BINARY;
      uParams.readReturnMode = UART_RETURN_FULL;
      uParams.readMode       = UART_MODE_CALLBACK;
      uParams.readCallback   = FIOT_UART_Serial_Rx_Cb;
    
      UART_uHandle = UART_open(Board_UART,&uParams); 
      //!PREPARE BUFFER TO READ THE 20 BYTES
      //!FIOT_UART_Serial_Rx_Cb only is called if device received 20 bytes
      UART_read(UART_uHandle, &UART_Rx, 20); 
    }

  • Hi Luu Vy, Thank for your answer.

    As I say, length of received data is equal to 0. My callback was called only because I put "UART_readCancel(hUart);" at the end of my receiveUART function. My issue is just that UART_read return always 0 (If I let the readCancel, Else it would return -1).

    And when you write "The old received data is cleared", does that mean that I need to clear it or is it made automatically?

    Regards,
    Lucas Poingt
  • Hi Lucas Poingt,

    Data in buffer isn't cleared to zero. Data is kept the old value. However, the new received data of UART will be stored on the old received data of UART.
  • Hi Luu Vy,

    Ok so Data in read buffer will be overwrite. But I still don't know why my UART_read always return 0 or -1. This issue disturb me a lot since a couple of days...

    Regards,
    Lucas Poingt
  • Hi Lucas Poingt,
    You use UART_Callback. Return of UART_read dont need with you because we dont have any new data at this time. There are many reasons to return UART_ERROR. I depend on your code.

    "For example, if one thread calls UART_read(uart0, buffer0...), any other thread attempting UART_read(uart0, buffer1...) will result in an error of UART_ERROR, until all the data from the first UART_read() has been transferred to buffer0. This applies to both UART_MODE_CALLBACK and UART_MODE_BLOCKING modes. So applications must either synchronize UART_read() (or UART_write()) calls that use the same UART handle, or check for the UART_ERROR return code indicating that a transfer is still ongoing."

    You can see more details in UART.h

  • Hi Luu Vy,

    thanks to you, I think that I'm not far from the origin of the problem, but it still don't work.

    I've try something like this:

    void receiveUART(){
    	int ret;
    	UART_read(hUart, UART_rxBuf, 20);
    }
    
    void readCallbackTest(UART_Handle handle, void *rxBuf, size_t size){
    	printf("The UART read %d bytes\n", size);
    	uint8_t i;
    	//Read the received data UART_rxBuf
    	for(i = 0 ; i<size ; i++)
    	    printf("The Rx UART[%d]= %d bytes\n",i, UART_rxBuf[i]);
    	    /*
    	     * PREPARE BUFFER TO READ THE NEXT 20 BYTES
    	     */
    	UART_read(hUart, UART_rxBuf, 20);
    }

    It seems to never go in the callback function once more, surely because UART_read function read nothing...

    This code is the one that send data on Rx pin from the nxp microcontroller to the Sable-X module:

    while(1){
    		unsigned char Data[20];
    		Data[0]=ID_SERIAL; // ID_SERIAL is the ID of the package of data, it will be usefull in process data
    		for (int i=1;i<20;i++)
    		{
    			Data[i]='A'; // just an example
    		}
    
    		LEDn_PutVal(1);// interrupt pin (to let the Sable-X aware of a data incoming) that trigger receiveUART function of the Sable-X
    		vTaskDelay(( TickType_t ) 1);//let some time to the Sable-X to see the rising edge
    		SendStringEasy(Data, 20);//SendStringEasy() send data on UART (it work)
    		vTaskDelay(( TickType_t ) 1);
    		LEDn_PutVal(0);
    		vTaskDelay(( TickType_t ) 1000);// let some time before the second transmission
    		for (int i=1;i<20;i++)
    		{
    			Data[i]='B';// another example with the same ID_SERIAL (just to make a difference between the two examples)
    		}
    
    		LEDn_PutVal(1);
    		vTaskDelay(( TickType_t ) 1);
    		SendStringEasy(Data, 20);
    		vTaskDelay(( TickType_t ) 1);
    		LEDn_PutVal(0);
    		vTaskDelay(( TickType_t ) 1000);
    	}

    Maybe it will help to find the issue, but with all the tests that I've made, I'm sure that sending data work.

    Regards,

    Lucas Poingt

  • Hi Lucas Poingt

    Where do you call receiveUART? Are you sure about setting of UART pin correctly? I need more details of your code.
  • Hi Luu Vy,

    I call the receiveUART function in the uartRX_Interrupt. This interrupt is triggered when the nxp microcontroller put "1" on the interrupt pin (called LEDn). I set the UART_Rx Pin on IOID_1 and UART_Tx Pin on IOID_0 (I've take them from the Sable-X module datasheet)

    Here is the pin configuration of Rx and Tx :

        Board_UART_RX  | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_DIS | PIN_IRQ_NEGEDGE | PIN_DRVSTR_MAX,            /* DevPack */ 
        Board_UART_TX  | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_NOPULL| PIN_DRVSTR_MAX,                        /* DevPack */

    Regards,

    Lucas Poingt

  • HI Lucas Poingt,

    Do you use a custom PCB or TI development kit?
    If you use Launchpad, your can try to remove the jumper on TXD and RXD.
  • Hi Luu Vy,
    I use a custom PCB, I make a direct link between Rx/ Tx and Tx/Rx of the nxp microcontroller and the Sable-X module. I don't have any jumper on my board.

    Regards,
    Lucas Poingt
  • Hi Lucas Poingt,

    Is your project developed based on simple_peripheral example ?
    You can try to do

    • 1/ Open simple_peripheral project
    • 2/ Edit RX and TX pin
    • 3/ Call UART_Init() in SimpleBLEPeripheral_init
    • 4/ Call receiveUART() after UART_Init() in SimpleBLEPeripheral_init
    • 5/ Rebuild, download stack and app to device. And add the break point at the Callback function.
    • 6/ Use nxp microcontroller to send 20 bytes to your device