Jump to content
  • 0

32bit data transfer using uartlite


Weevil

Question

Hi all,

actual i try to transfer a data stream from the DMA via uart to my PC.

In my design an DDS-compiler generates a 32bit sine wave, which should be transfered via uart and read by a python script. The general data transfer works, but sometimes i get some noisy signal. This signal happens also when using a lower sample rate.

For the uart data transfer actual i did not add any marker where the 32 bit value begins or ends. So i expect this is the problem, but i don't know how to include this in my SDK and python code.

Maybe any suggestion?

 

(The FPGA design is similar to my previous post https://forum.digilentinc.com/topic/8966-axi-dma-timing/?page=0#comment-26920 using the Cmod A7)

Plot of the result with pyqtgraph:

Unbenannt.thumb.PNG.0477270a87c2b350ed9c92f31ca9e229.PNG

 

SDK code:

int XAxiDma_Poll_Uart(u16 DeviceId)
{
	int Status, Index;
	int Tries = NUMBER_OF_TRANSFERS;
	u32 *RxBufferPtr;
	u32 *RxPacket;
	u8 BytesSent;


	RxBufferPtr = (u32 *) RX_BUFFER_BASE;
	RxPacket = (u32 *) RX_BUFFER_BASE;

	for (Index = 0; Index < MAX_PKT_LEN_WORDS; Index ++)
	{
		RxBufferPtr[Index] = 0xCC;
	}

	/* Flush the SrcBuffer before the DMA transfer, in case the Data Cache is enabled*/
	Xil_DCacheFlushRange((u32)RxBufferPtr, MAX_PKT_LEN);


	Status = XAxiDma_SimpleTransfer(&AxiDma, (u32) RxBufferPtr, MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);

	if (Status != XST_SUCCESS) {return XST_FAILURE;}

	while (XAxiDma_Busy(&AxiDma, XAXIDMA_DEVICE_TO_DMA)) {/* Wait*/}


	/* Invalidate the TestBuffer before receiving the data, in case the Data Cache is enabled*/
	Xil_DCacheInvalidateRange((u32)RxPacket, MAX_PKT_LEN);


	//send data to uart
	BytesSent = XUartLite_Send(&UartLite, RX_BUFFER_BASE, sizeof(RxPacket));

	while (XUartLite_IsSending(&UartLite)) {/*Wait*/}


	return XST_SUCCESS;
}

 

Python code:

import numpy as np
import sys
import serial


buffersize = 512
byte_number = 4
  
  
ser = serial.Serial(
        port='COM6',\
        baudrate=921600,\
        parity=serial.PARITY_NONE,\
        stopbits=serial.STOPBITS_ONE,\
        bytesize=serial.EIGHTBITS,\
            timeout=0)



for u in range(20):
  
  #read serial buffer
  s = ser.read(buffersize)
  
  
  #convert to integer
  for i in range (int(len(s)/byte_number)):     
    res_value = dataSerial[(i*byte_number):((i+1)*byte_number)]
    value = int.from_bytes(res_value, byteorder='little', signed = True)
    dataSerialFormated = np.append(dataSerialFormated, value)
  
  

 

Link to comment
Share on other sites

6 answers to this question

Recommended Posts

Hi,

BytesSent = XUartLite_Send(&UartLite, RX_BUFFER_BASE, sizeof(RxPacket));

I don't know the Xilinx routines by heart. That said, with similar functions in other applications I usually need to check the actual number of "BytesSent" and possibly call again, e.g.

char* p =  RX_BUFFER_BASE;
int nRem = sizeof(RxPacket);
while (nRem){
	int nProc = XuartLite_Send(&UartLite, p, nRem);
	// Error handling here (if any)
	nRem -= nProc;
	p += nProc;
}

I'm just guessing, it may be something completely different.

What I'd do to debug is plot against an ideal sine wave. Most likely each glitch will cause an offset of one sample => missing bytes.

If it turns out there is no offset, it could mean that the data stream remains in sync but bits get scrambled for unknown reasons.

 

Link to comment
Share on other sites

@xc6lx45

I did a test to add some "x00" value before sending the 32 bit value in my SDK and print out the result of the python script. So in my result sometimes there is a shift, which i expect cause the wrong values. So i will orientate the start of an 4 bit value at the "x00". Maybe there is some other, smarter possibility?

 

Unbenannt.thumb.PNG.26110bd128ae4d66c108a02fb5ffdb35.PNG

 

SDK code:

int XAxiDma_Poll_Uart(u16 DeviceId)
{
	int Status, Index;
	int Tries = NUMBER_OF_TRANSFERS;
	u32 *RxBufferPtr;
	u32 *RxPacket;
	u8 BytesSent;
	u8 emptyvalue = 111;
	

	RxBufferPtr = (u32 *) RX_BUFFER_BASE;
	RxPacket = (u32 *) RX_BUFFER_BASE;

	//MAX_PKT_LEN = 16 (in byte) -> uart max 16 byte
	for (Index = 0; Index < MAX_PKT_LEN_WORDS; Index ++)
	{
		RxBufferPtr[Index] = 0xCC;
	}

	/* Flush the SrcBuffer before the DMA transfer, in case the Data Cache is enabled*/
	Xil_DCacheFlushRange((u32)RxBufferPtr, MAX_PKT_LEN);


	Status = XAxiDma_SimpleTransfer(&AxiDma, (u32) RxBufferPtr, MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);

	if (Status != XST_SUCCESS) {return XST_FAILURE;}

	while (XAxiDma_Busy(&AxiDma, XAXIDMA_DEVICE_TO_DMA)) {/* Wait*/}


	/* Invalidate the TestBuffer before receiving the data, in case the Data Cache is enabled*/
	Xil_DCacheInvalidateRange((u32)RxPacket, MAX_PKT_LEN);


	


	char* p = RX_BUFFER_BASE;
	int nRem = sizeof(RxPacket);

	XUartLite_Send(&UartLite, emptyvalue, sizeof(emptyvalue));

	while (nRem){

		//send data to uart
		int nProc = XUartLite_Send(&UartLite, p, nRem);

		nRem -= nProc;
		p += nProc;
	}
	






	return XST_SUCCESS;
}

 

Link to comment
Share on other sites

I've seen similar issues on Windows, when reading binary data in (default) text format. It glitches when it runs into a sequence of decimal 13 and 10 (Windows CR/LF).
At first glance I can't see a "binary" option for Python's serial library but I've never used this one myself.

inserting zeros was a good idea.
Now how about dumping the five bytes as hex? I found this from stackexchange:

print myVar.encode('hex')
Link to comment
Share on other sites

I had similar issues with UART on Windows as well. In one case Zynq board was sending large files containing 32bit binary data over UART to PC. When I used SDK terminal I didn't have any glitches but when I used any of Windows terminal applications a few bytes were missing at some points. BTW, binary data itself can be transferred over RS232 you just need an application accepting binary not just text data. In the past I also had similar problems transferring large chunks of data on Windows in Java application. In our findings the issue was related to the serial port buffer overflow.

On my projects I use RS232 only for short messaging, data transfer function is delegated to a faster and more reliable CANbus. It took some time to learn how to use CAN but was worth it.

Link to comment
Share on other sites

@xc6lx45 and @Notarobot

thank you very much for your comments.

I will further try the thing you suggest. For the first step i got a solution by looking at the "x00" and reordering my results from the uart with it.

 

In future i want do to something like wfjmueller posted in this thread, but for doing that i have to learn many things before :)

https://forum.digilentinc.com/topic/1053-arty-schematics-missing-ft2232-component/

 

Python code:

import numpy as np
import sys
import serial


buffersize = 512
byte_number = 4
  
  
ser = serial.Serial(
        port='COM6',\
        baudrate=921600,\
        parity=serial.PARITY_NONE,\
        stopbits=serial.STOPBITS_ONE,\
        bytesize=serial.EIGHTBITS,\
            timeout=0)



for u in range(20):
  
  	#read serial buffer
  	s = ser.read(buffersize)
	data_left = ser.inWaiting()
	s += ser.read(data_left)
      
        for i in range(len(dataSerial)):
            if (dataSerial[i] == 0):
                j = 0
                frame = bytearray()
            else:
                frame.append(dataSerial[i])
                j = j+1
            if (j>3):
                dataSerialFormated = int.from_bytes(frame, byteorder='little', signed = True)
                bufferToSend[k] = dataSerialFormated
                k=k+1
                frame = bytearray()
                j= 0
        bufferToSend = bufferToSend[bufferToSend!=0]
  
  

 

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...