rhea icon indicating copy to clipboard operation
rhea copied to clipboard

instructions: xula_blinky_host.py on raspberry pi 3B [solved]

Open hstarmans opened this issue 7 years ago • 7 comments

Update Issue has been resolved, see my last two posts

Dear all,

I am trying to get xula_blinky_host.py working with a; Raspberry Pi 3B, Xula2-lx25, StickIt!-LedDigits and the Stickit!-MB v4. I have inserted the LedDigits in PM2. I am able to to run the LedDigitsTest, after changing the LedDigitsTest.UCF using xsconnect. I have verified the UART pins are working, by connecting chan 14 and 15 on the stickit board. I communicated via minicom and checked if I could receive echoes. I am able to create a bitstream from xula_blinky_host. If I upload this bitstream; nothing happens. The LedDigits module is off. This is not what i expect. I thought data could be written via uart to the xula2 and this would appear on the leddigit board on PM2. I can't write data.

Do the authors, @cfelton and @forumulator , have any advice on how to proceed!? Which settings should I use in minicom!? Should I try the example with a raspberry pi 2? What setup was used to verify the code!?

Notes: I use ubuntu 16.04.1, have a jumper on 5V-PWR and a jumper on GPIO-5V. The xula2-lx25 is connected via USB to the raspberry pi 3 or a raspberry pi 2 (tested both). I can only change the EEPROM via the Raspberry Pi 2. Similar question was asked in feb 2016 at the Xilinx forum.

Keep up the good work,

Rik

hstarmans avatar Nov 17 '16 14:11 hstarmans

You need to create a "packet" to send down to toggle the lights. The simple UART is typically configured for 115200. It has been awhile since I have looked at it, let me see if I can get some hardware setup this weekend and test.

cfelton avatar Nov 18 '16 11:11 cfelton

Thank you for your reply, I guess I need something along the lines of;

import serial
ser=serial.Serial("/dev/ttyS0",timeout=1) # rasp2 "/dev/ttyAMA0"
ser.baudrate=115200
# first byte fixed at DE
# command: 1 read 2 write --> write so 2
# address byte: 
#    peripheral address  4 bit;  set to ?
#    memory address     28 bit; set to 0
# length of data: 4 bytes (does not seem to matter packet length fixed at 12)
# sequence byte fixed at CA
# data byte; 4 bytes, arbitrarily fixed at '11'
# hexdata='DE'+'command byte'+'address byte'*4+'length of data'+'CA'+'data byte'*4
for command in [b'\x01',b'\x02']:  # command
    for i in [0,1,15]: # peripheral address
        per_adr=(i*16).to_bytes(1,byteorder='big')
        for j in [0,1,2,16,30,31,32]: # memory address
            mem_addr=(j).to_bytes(3,byteorder='big')
            packet=b'\xDE'+command+per_adr+mem_addr+b'\x04'+b'\xCA'+b'\x11'*4
            print("sending packet "+str(packet))
            ser.write(packet)
            #read possible reply
            s=ser.read(12) # read reply
            print("reply:"+s.decode())
ser.close()

As you might realize, the code does not work on a Raspberry Pi 2 and Raspberry Pi 3. Could you provide more info on the packet I should sent? Note: I also receive the following build warnings: signal is driven but no read: command_bridge_1_bytemon, command_bridge_1_bb_per_addr,command_bridge_1_error,command_bridge_1_controller_basic_1_tocnt, uartlite_1_fifo_fast_1_fbus_read_valid,uartlite_1_fifo_fast_2_fbus_full, signal is not driven: uartlite_1_fifo_fast_1_fbus_read_valid, uartlite_1_fifo_fast_2_fbus_clear

hstarmans avatar Nov 19 '16 11:11 hstarmans

This is the code I use to generate the packets. I have not tested/used from a RPi (others have). I am not sure what code they used on the RPi.

cfelton avatar Nov 23 '16 15:11 cfelton

Thank you for your reply. I do see changes now. I still don't receive any replies on UART but see changes on the LedDigits panel. If the reset pin is low; the number 8 is blinking on LED1 of the Leddigits test panel. If the reset pin is high; the Leddigits panel is off. If the reset pin is low and the value 0xFF is written to address 0x20, there are no changes. However, if the reset pin is put high again the number 8 remains. The led panel does not seem to be driven correctly via daisy chaining. As a result, I don't expect it to produce the right numbers. I have used the following code to test it:

import serial
import RPi.GPIO as GPIO
from time import sleep
from rhea.utils import CommandPacket
# connect to pin
GPIO.setmode(GPIO.BCM)
GPIO.setup(23,GPIO.OUT)  # i use a different pin!! use gxsconn to get the correct pins
# reset low
GPIO.output(23,0) # this should already be the case
# connect to serial port
ser=serial.Serial("/dev/ttyAMA0",timeout=2) # rasp2 used
ser.baudrate=115200
wcommand=CommandPacket(rnw=False,address=0x20,vals=[0xFF])
ser.write(wcommand.rawbytes)
rcommand=CommandPacket(rnw=True,address=0x20,vals=None)
ser.write(rcommand.rawbytes)
# read from the serial buffer
ser.read() 
# no value is received ; does not seem to work
GPIO.output(23,1)
# an 8 is visible on ledbank 1, if one does not write anything nothing is visible

hstarmans avatar Nov 24 '16 13:11 hstarmans

I have spotted one bug:

 # create the UART instance.
    uart_inst = uartlite(
        glbl, uart_fifo, serial_in=bcm14_txd, serial_out=bcm15_rxd,
        fifosize=4
)

Should be:

 # create the UART instance.
    uart_inst = uartlite(
        glbl, uart_fifo, serial_in=bcm15_rxd, serial_out=bcm14_txd,
        fifosize=4
)

Compare the code from Icestick with the xula, look at the defintion of uartlite I have the following files: test_blinky_host_xula.py

from __future__ import print_function, division

import myhdl
from myhdl import Signal, intbv, instance, delay, StopSimulation, ResetSignal

from rhea.system import Global, Clock, Reset
from rhea.models.uart import UARTModel
from rhea.utils.test import run_testbench, tb_args, tb_default_args, tb_convert
from rhea.utils import CommandPacket
from rhea.utils.command_packet import PACKET_LENGTH

from xula_blinky_host import xula2_blinky_host


def test_ibh(args=None):
    args = tb_default_args(args)
    numbytes = 13
    reset= ResetSignal(0, active=1, async=True) 
    clock = Clock(0, frequency=12e6)
    glbl = Global(clock, None)
    led = Signal(intbv(0)[8:])
    pmod = Signal(intbv(0)[8:])
    uart_tx = Signal(bool(0))
    uart_rx = Signal(bool(0))
    uart_dtr = Signal(bool(0)) # NOT USED
    uart_rts = Signal(bool(0)) # NOT USED
    uartmdl = UARTModel()

    @myhdl.block
    def bench_ibh():
        tbclk = clock.gen()
        tbmdl = uartmdl.process(glbl, uart_tx, uart_rx)
        tbdut = xula2_blinky_host(clock, reset, led, uart_tx, uart_rx)
        
        @instance
        def tbstim():
            yield delay(1000)
            
            # send a write
            pkt = CommandPacket(False, address=0x20, vals=[0xFF])
            for bb in pkt.rawbytes:
                uartmdl.write(bb)
            waitticks = int((1/115200.) / 1e-9) * 10 * 28 
            yield delay(waitticks)  
            timeout = 100
            # get the response packet
            for ii in range(PACKET_LENGTH):
                rb = uartmdl.read()
                while rb is None and timeout > 0:
                    yield clock.posedge
                    rb = uartmdl.read()
                    timeout -= 1
                if rb is None:
                    raise TimeoutError
            yield delay(waitticks) 
            # the last byte should be the byte written
            assert rb == 0xFF

            yield delay(1000)
             
            # send a read
            pkt = CommandPacket(True, address=0x20, vals=None)

            yield delay(1000)

            raise StopSimulation

        return tbclk, tbmdl, tbdut, tbstim

    run_testbench(bench_ibh, args=args)
    inst = xula2_blinky_host(
        clock, reset, led,
        uart_tx, uart_rx
    )
    #tb_convert(inst)


if __name__ == '__main__':
    test_ibh(tb_args())

The tests pass. I use the following xula_blinky_host file. I would suggest to call this xula2. I have also defined a resetsignal in the function test_instance().

xula_blinky_host.py

import argparse
import subprocess
from pprint import pprint

from myhdl import Signal, intbv, always_seq, always_comb, ResetSignal, block, instances

from rhea import Global, Clock, Reset
from rhea.system import Barebone, FIFOBus
from rhea.cores.uart import uartlite
from rhea.cores.memmap import command_bridge
from rhea.cores.misc import glbl_timer_ticks
from rhea.build.boards import get_board


@block
def xula2_blinky_host(clock, reset, led, bcm14_txd, bcm15_rxd):
    """
    The LEDs are controlled from the RPi over the UART
    to the FPGA.
    """

    glbl = Global(clock, reset)
    ledreg = Signal(intbv(0)[8:])

    # create the timer tick instance
    tick_inst = glbl_timer_ticks(glbl, include_seconds=True)

    # create the interfaces to the UART
    uart_fifo = FIFOBus(width=8)

    # create the memmap (CSR) interface
    memmap = Barebone(glbl, data_width=32, address_width=32)

    # create the UART instance.
    uart_inst = uartlite(
        glbl, uart_fifo, bcm15_rxd, bcm14_txd, fifosize=4
    ) #NOTE: switched 15_r and 14_t, icestick example does not specify fifosize

    # create the packet command instance
    cmd_inst = command_bridge(glbl, uart_fifo, memmap)

    @always_seq(clock.posedge, reset=reset)
    def beh_led_control():
        memmap.done.next = not (memmap.write or memmap.read)
        if memmap.write and memmap.mem_addr == 0x20:
            ledreg.next = memmap.write_data

    @always_comb
    def beh_led_read():
        if memmap.read and memmap.mem_addr == 0x20:
            memmap.read_data.next = ledreg
        else:
            memmap.read_data.next = 0
    
    # blink one of the LEDs
    tone = Signal(intbv(0)[8:])

    @always_seq(clock.posedge, reset=reset)
    def beh_assign():
        if glbl.tick_sec:
            tone.next = (~tone) & 0x1
        led.next = ledreg | tone[5:] 
            
    return instances()


def build(args):
    brd = get_board('xula2_stickit_mb')
    brd.add_port_name('led', 'pm3', slice(0, 8))  # NOTE: pm3 instead of pm2
    brd.add_reset('reset', active=1, async=True, pins=('C16',)) # NOTE: use different pin
    flow = brd.get_flow(top=xula2_blinky_host)
    flow.run()
    info = flow.get_utilization()
    pprint(info)


def program(args):
    subprocess.check_call(
        ["xsload",
         "--fpga", "xilinx/xula2_stickit_mb.bit",
         "-b", "xula2-lx25"]
    )


def cliparse():
    parser = argparse.ArgumentParser()
    parser.add_argument("--build", default=False, action='store_true')
    parser.add_argument("--test", default=False, action='store_true')
    parser.add_argument("--program", default=False, action='store_true')
    parser.add_argument("--walk", default=False, action='store_true')
    args = parser.parse_args()
    return args


def test_instance():    
    # check for basic syntax errors, use test_ice* to test
    # functionality
    xula2_blinky_host(
        clock=Clock(0, frequency=12e6),
        led=Signal(intbv(0)[8:]),
        reset=ResetSignal(bool(0),active=1, async=True),   #NOTE: not in original
        bcm14_txd=Signal(bool(0)),
        bcm15_rxd=Signal(bool(0)))

    
def main():
    args = cliparse()
    if args.test:
        test_instance()
        
    if args.build:
        build(args)

    if args.program:
        program(args)

    # @todo: add walk function

if __name__ == '__main__':
    main()

Finally, I use the following file to test the code on a raspberry pi 2 with Python 3 and the latest rhea and myhdl. rasp2test.py

import serial
from rhea.utils import CommandPacket
ser=serial.Serial("/dev/ttyAMA0",timeout=2)  #NOTE: used raspberry pi 2 for test
ser.baudrate=115200 
w=CommandPacket(rnw=False,address=0x20,vals=[0xFF])
ser.write(w.rawbytes)  
print(len(ser.read()))
r=CommandPacket(rnw=True,address=0x20,vals=None)
ser.write(r.rawbytes)
assert 0!=len(ser.read())

Conclusion:

  • I have a blinking LED
  • The Myhdl code passes test_blinky_host_xula.py and looks "fine" in GTKwave
  • I do receive replies on UART, rasp2test.py passes

hstarmans avatar Jan 10 '17 14:01 hstarmans

@cfelton ; shall I change xula_blinky_host and add my rasptest and test_blinky_host_xula!? The pins of the xula2 seem to be flipped both in the definition and the uart test.

hstarmans avatar Jan 11 '17 07:01 hstarmans

@hstarmans that is great you go it going!

Can you link the documentation that shows the names being flipped? It has been awhile and I don't recall if I was trying to standardize the UART signals always being from a certain perspective.

Go ahead and create a PR and I will review it.

cfelton avatar Jan 12 '17 05:01 cfelton