Pynq Microblaze UART not working with PYNQ overlay

Dear all,

I am having issues trying to use axi uart from with a microblaze using the pynqmicroblaze library.
I made my own block design and custom overlay following all connections according to the PYNQ MicroBlaze Subsystem. See Pics.

First I built the project in Vitis and program the microblaze using JTAG in vitis in debug mode. It works perfectly, i.e., the axi uart peripherals receive the data I send correctly.

The problem comes when I use the pynq overlay and the from pynq.lib import PynqMicroblaze library to use the uBlaze subsystem. I follow the steps, program the microblaze writing the memory and now the Axi uart peripherals receive garbage…

I attach python code and code in microblaze.

from pynq.lib import PynqMicroblaze
from pynq import PL
import struct
import time

#reload object from file
fd = open(r'/home/xilinx/base_drone.pkl', 'rb')
ip_dict = pickle.load(fd)
fd.close()

# Check dictionaries for names
ip_dict = PL.ip_dict
gpio_dict = PL.gpio_dict
intr_dict = PL.interrupt_pins

mb_info = {'ip_name': 'iop_ub0/axi_bram_ctrl',
        'rst_name': 'mb_iop_ub0_reset'
#         'intr_pin_name': 'iop_ub0/dff_en_reset_vector_0/q', 
#         'intr_ack_name': 'mb_iop_ub0_intr_ack'
          }
uBlaze_PROGRAM = "/home/xilinx/droneUb_fw.bin"

uBlaze_obj = PynqMicroblaze(mb_info, uBlaze_PROGRAM)

uBlaze_MEM = ip_dict["iop_ub0/axi_bram_ctrl"]

MAILBOX_OFFSET = int(uBlaze_MEM["parameters"]["C_S_AXI_BASEADDR"],0)
MAILBOX_BGN = 0x0000FF00
MAILBOX_END = 0x0000FFFF
MAILBOX_4BYTES = 0x4

# Addresses
MAILBOX_CMD_ADDR = MAILBOX_END - (MAILBOX_4BYTES - 0x1)
MAILBOX_ADDR = MAILBOX_END - (MAILBOX_4BYTES*2 - 0x1)

# Commands
RESET = 0x1
UPDATE_VALUES = 0x3

# uBlaze_obj.program
uBlaze_obj.write(MAILBOX_CMD_ADDR, RESET)
while (uBlaze_obj.read(MAILBOX_CMD_ADDR, 1) != 0):
    time.sleep(0.001)

print("pass")

flag = 1
while (flag):
    time.sleep(1)
    uBlaze_obj.write(MAILBOX_CMD_ADDR, UPDATE_VALUES)
    reg = uBlaze_obj.read(MAILBOX_BGN + MAILBOX_4BYTES*0, 4+25)
    value = reg[0:4]
    print(value)
    
    converted = [int(x) for x in reg[5:29]]
    
    print(converted)
    
    flag = 0
/***************************** Include Files *********************************/
	#include<stdio.h>
	#include<stdlib.h>
	#include<cstring>
	
	#include "../include/pynq_ublaze/uart.h"
	//#include "i2c.h"
	//#include "ads111x.h"
	// Call the library
	//#include "common/mavlink.h"
	
	/************************** Constant Definitions *****************************/
	// #define DEBUG_MAV
	#define MASK_32BITS 0xFFFFFFFF
	
	// Uart definitions
	#define uart_device_id_0 	0U
	#define uart_device_id_1 	1U
	#define uart_buff_size 		16
	
	#define uart_space 			32U
	#define uart_end_of_line 	10U
	
	// i2c definitios
	#define i2c_device_id_0 0U
	#define sniffbot_nh3_addr 0x49
	
	// Mailbox definitions
	// command from A9 to MB0
	// command from A9 to MB0
	#define MAILBOX_CMD_ADDR (*(volatile uint32_t *)(0x0000FFFC))
	// address of MB0
	#define MAILBOX_ADDR (*(volatile uint32_t *)(0x0000FFF8))
	#define MAILBOX_DATA(x) (*(volatile uint32_t *)(0x0000FF00+((x)*4)))
	#define MAILBOX_ADDR_FLOAT (*(volatile float *)(0x0000FFF8))
	#define MAILBOX_DATA_FLOAT(x) (*(volatile float *)(0x0000FF00+((x)*4)))
	
	/* Command format
	*  bit[0] : MP issued command when 1
	*  bit[1] : Read/Write   => 0 :  Python requests write
	*                           1 : Python requests read
	*/
	// Command arrived from Zynq
	#define UPDATE_VALUES 0x01
	
	// Gas Defines
	#define CH_GAS 65
	
	/************************** Struct Definitions ******************************/
	struct gas_64ch_struct{
		uart 	uart_device;
		uint8_t msg[25];
		uint8_t flag = 0;
		uint8_t new_data = 0;
		uint8_t uart_cont = 0;
		uint8_t ch_cont = 0;
		float values[CH_GAS];
	};
	
	typedef gas_64ch_struct gas_64ch_struct;
	typedef gas_64ch_struct *gas_64ch;
	
	/************************** Function Prototypes ******************************/
	// Gas Functions
	void gas_begin(gas_64ch _self, uint16_t uart_device);
	void gas_read_incoming(gas_64ch _self);
	void gas_update_values(gas_64ch _self);
	
	/************************** Variable Definitions *****************************/
	
	#ifdef DEBUG_MAV
	int msgid_hist[255];
	uint8_t msgid_cont = 0;
	#endif
	
	//uint8_t gas_flag = 0;
	//float gas_data[65];
	
	/******************************************************************************/
	/**
	*
	* Main function 
	*
	*
	*******************************************************************************/
	
	// Launch the serial port in setup
	int main() {
	#ifdef DEBUG_MAV
		memset(msgid_hist,-1,255*sizeof(msgid_hist[0]));
	#endif
		// Create Gas Object
		gas_64ch gas_ptr;
		gas_begin(gas_ptr, uart_device_id_1);
	
		// Start i2c device
		//i2c gas_i2c = i2c_open_device(i2c_device_id_0);
		//i2c_reset(gas_i2c);
	
		// Start ads1115
		//ads111x my_nh3 = ads111x_configure(gas_i2c, sniffbot_nh3_addr);
		//uint16_t nh3_value[4] = {0,0,0,0};
		//uint8_t channel = 0;
	
		// infinite loop
		while(1){
			/* Command format
			*  bit[0] : MP issued command when 1
			*  bit[1] : Read/Write   => 0 :  Python requests write
			*                           1 : Python requests read
			*/
			// Command arrived from Zynq
			uint8_t cmd = MAILBOX_CMD_ADDR;
			switch(cmd){
			case UPDATE_VALUES:
			{
				// write out reading, reset mailbox
				gas_update_values(gas_ptr);
				MAILBOX_CMD_ADDR = 0x0;
				break;
			}
			default:
			{
				// otherwise continue updating
				MAILBOX_CMD_ADDR = 0x0;
				// Gas data update
				gas_read_incoming(gas_ptr);
				// NH3 sensor
				//nh3_value[channel] = ads111x_value(my_nh3,channel);
				//channel++;
				//if (channel > 3)
				//channel = 0;
				break;
			}
			}
		}
		return 0;
	}
	
	//----------------------------------------------------------------
	void gas_read_incoming(gas_64ch _self){
		if (uart_rx_empty(_self->uart_device) == 0){
			uint8_t c;
			uart_read(_self->uart_device, &c, 1);
			if (_self->flag == 1){
				_self->msg[_self->uart_cont] = c;
				_self->uart_cont++;
				if (c == ' '){
					float gas_f = atof((const char *)_self->msg);
					_self->values[_self->ch_cont] = gas_f;
					_self->ch_cont++;
				}
			}
			if (c == uart_end_of_line){
				_self->flag = 1;
				_self->uart_cont = 0;
				_self->ch_cont = 0;
				_self->new_data = (_self->ch_cont == CH_GAS)? 1 : 0;
			}
			_self->uart_cont = (c == ' ')? 0 : _self->uart_cont;
		}
	}
	
	//----------------------------------------------------------------
	void gas_update_values(gas_64ch _self){
		for (uint16_t cont_mail = 0; cont_mail<CH_GAS; cont_mail++){
			MAILBOX_DATA_FLOAT(cont_mail) = _self->values[cont_mail];
		}
	}
	
	//---------------------------------------------------------------
	void gas_begin(gas_64ch _self, uint16_t uart_device){
		// Start uart devices
		_self->uart_device = uart_open_device(uart_device);
		uart_reset(_self->uart_device);
		// Start Variables
		_self->flag = 0;
		_self->new_data = 0;
		_self->uart_cont = 0;
		_self->ch_cont = 0;
		memset(_self->msg, 0, sizeof(_self->msg));
		memset(_self->values, 0, sizeof(_self->values));
	}

has anyone else had this issue?

Please help. I am very desperate :frowning:

FYI, I use PYNQ 2.6 and Vivado 2020.1

1 Like