This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

IO-Link driver using UARTE and EndTx event.

I'm developing IO-Link driver using UARTE peripherial.

Is it possible to get event on end of transmition with EasyDMA Tx. Event ENDTX is fired before all transmited bytes are send.

Second question: Is it possible to disable Rx line while transmiting on Tx? IO-link phy layer is single line and every Tx char is reflected on Rx line.

Why I get characters received in rx buffer even when TASK_STARTRX is not fired?

Parents
  • Hi Robert, 

    You are right, ENDTX comes when the last byte is being clocked out. But the TXDRDY event of the last byte should come after the byte is clocked. Maybe you can catch the TXDRDY after you receive ENDTX. It will be the TXDRDY of the last byte. 

    I'm not aware of that RX buffer is being affected even TASK_STARTRX is not called. Is it possible to reproduce it using our example ? Have you made sure there is no PPI or SHORT that can trigger the task ? 

Reply
  • Hi Robert, 

    You are right, ENDTX comes when the last byte is being clocked out. But the TXDRDY event of the last byte should come after the byte is clocked. Maybe you can catch the TXDRDY after you receive ENDTX. It will be the TXDRDY of the last byte. 

    I'm not aware of that RX buffer is being affected even TASK_STARTRX is not called. Is it possible to reproduce it using our example ? Have you made sure there is no PPI or SHORT that can trigger the task ? 

Children
  • Hi,

    Yes, I do this sequence with ENDTX.

    1. Wait for ENDTX.

    2. Enable TXRDY interrupt and wait for them. But this interrupt never came.

    Regarding this picture I was shore that this interrupt came after ENDTX.

    Could you test, if this sequence work.

    Regarding this picture, I think that TXRDY interrupt must came after last stop bit was send.

    Is this true? 

    This is my interrupt service rutine. Code came only to EVENTS_ENDTX.

    inline void clNRF52Uart::isr (void)
    {
    	volatile u32_t dummy;
    	volatile u32_t inten = port->INTEN;
    
    	/*if(port->EVENTS_RXSTARTED){
    		port->EVENTS_RXSTARTED = 0;
    		dummy = port->EVENTS_RXSTARTED;
    		//port->RXD.PTR = (u32_t)buf1;
    	}*/
    
    	/*if(port->EVENTS_RXDRDY){
    		port->EVENTS_RXDRDY = 0;
    		dummy = port->EVENTS_RXDRDY;
    		//if(port->EVENTS_ERROR == false){
    			//port->TASKS_FLUSHRX = 1;
    			//LedBLUE->OutToggle();
    		//}
    	}*/
    
    	if(inten & (1<<17) ){
    		if(port->EVENTS_RXTO){
    			port->INTENCLR = (1<<17);
    			port->EVENTS_RXTO = 0;
    			dummy = port->EVENTS_RXTO;
    			k_sem_give(&sem);
    		}
    	}
    
    	if(inten & (1<<9) ){
    		if(port->EVENTS_ERROR){
    			port->INTENCLR = (1<<9);
    			port->EVENTS_ERROR = 0;
    			dummy = port->EVENTS_ERROR;
    			comerr = port->ERRORSRC;
    			port->ERRORSRC = comerr;
    			port->INTENSET = (1<<17);
    			port->TASKS_STOPRX = 1;
    		}
    	}
    
    	if(inten & (1<<4) ){
    		if(port->EVENTS_ENDRX){
    			port->INTENCLR = (1<<4);
    			port->EVENTS_ENDRX = 0;
    			dummy = port->EVENTS_ENDRX;
    			if(comerr == 0) k_sem_give(&sem);
    			//q.Fire(&onrx, (void*)((u32_t)buf[0]));
    		}
    	}
    
    	if(inten & (1<<20) ){
    		if(port->EVENTS_TXSTARTED){
    			port->INTENCLR = (1<<20);
    			port->EVENTS_TXSTARTED = 0;
    			dummy = port->EVENTS_TXSTARTED;
    			//LedBLUE->OutClr();
    			//tc->AlarmSet(txtime, 0, this);
    		}
    	}
    
    	if(inten & (1<<7) ){
    		if(port->EVENTS_TXDRDY){
    			port->INTENCLR = (1<<7);
    			port->EVENTS_TXDRDY = 0;
    			dummy = port->EVENTS_TXDRDY;
    			k_sem_give(&semtx);
    		}
    	}
    
    	if(inten & (1<<8) ){
    		if(port->EVENTS_ENDTX){
    			port->INTENCLR = (1<<8);
    			port->EVENTS_ENDTX = 0;
    			dummy = port->EVENTS_ENDTX;
    
    			port->EVENTS_TXDRDY = 0;
    			dummy = port->EVENTS_TXDRDY;
    			port->INTENSET = (1<<7); // enable txdrdy
    			//k_sem_give(&semtx);
    			//tc->AlarmSet(txtime, 0, this);
    		}
    	}
    
    }
    
    int clNRF52Uart::Write ( u8_t * Data , u16_t Size )
    {
    	port->EVENTS_ENDTX = 0;
    	volatile u32_t dummy = port->EVENTS_ENDTX;
    	port->INTENSET = (1<<8); //enable endtx
    
    	//txtime = tc->TicksFrom_us(420);
    	port->TXD.PTR = (u32_t)Data;
    	port->TXD.MAXCNT = Size;
    	port->TASKS_STARTTX = 1;
    
    	k_sem_take(&semtx, K_FOREVER);
    
    	return port->TXD.AMOUNT;
    }
    

  • Hi Robert, 

    I double checked the spec and it says: 

    When all bytes in the TXD buffer, as specified in the TXD.MAXCNT register, have been transmitted, the
    UARTE transmission will end automatically and an ENDTX event will be generated.

    This meant the ENDTX will be triggered after the last byte is clocked out. Not when it's transmitting. 

    So ENDTX and the last TXDRDY will come at the same time. My last suggestion was wrong. 

    I did a logic trace here and it confirmed what in the spec: 

    You can see that TXDRDY and ENDTX came at the same time. And they come after the last bit of the last byte is clocked. I'm not sure why in your question you mentioned "  Event ENDTX is fired before all transmited bytes are send."

     

  • Hi,

    Yes, problem is that TXEND and TXDRDY are fired after last data bit and not after parity and stop bit witch is important in my situation.

    In IO-link and also in RS-485 communication you must enable transmiter before first byte was send (this is not a problem) and disable after all bits are sent including parity and stop bit.

  • Would adding any hardcoded timing helps? Sorry that I'm not very familiar with IO-link. 

Related