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.

AM625: Generate Eye diagram

Part Number: AM625
Other Parts Discussed in Thread: SK-AM62-LP

Hi, 

I want to generate eye diagram for custom am62x board with lpddr4. Referring to DDR-MARGIN-FW, through the UART load.

I felt command mentioned  in readme.txt  looks support window method to capture.

Please share equivalent command run on Linux,

 

Regards,

Gireesh Hiremath 

  • Greetings Gireesh,

    The commands are O/S agnostic as they use javascript and python scripts. The only part of the readme that uses software exclusive to Windows is the serial software used as an example, TeraTerm. This can freely be replaced by whichever serial software you prefer to use, as noted in the readme section "Serial Terminal":

    Serial Terminal
    --------------------------
    For the host PC that will be connected to the target device during runtime, serial terminal software is required.
    Free software like TeraTerm or Putty are popular options.

    Sincerely,

    Lucas

  • Hi Lucas,

    Thanks for the info. I gone through the readme.txt but not clear on the boot mode switch,

    what is preferred boot switch position for UART load and JTAG load?

    is DFU boot mode switch position can be used as alternative of UART load  ?

    If only DFU boot mode switch left with custom board, what is changes need to be done to load  DDR-MARGIN-FW?

    Regards,

    Gireesh Hiremath

  • Greetings Gireesh,

    There is no preferred boot mode for the firmware, it is completely independent of the booting process. From my experience, JTAG load is often the simplest method to use, while UART boot is the one most customers will have access to (usually as a debugging aid).

    Yes, you can use DFU boot in place of UART boot, there is no restriction from the firmware. The only hard requirement is that you have UART0 pinned out for the host to capture the serial output of the firmware.

    Sincerely,

    Lucas

  • Greetings Gireesh,

    I am not sure if you have your custom board available yet to try, but here is an example of how you could load the tool using the MCU+SDK on an SK-AM62-LP EVM. The steps for your board will likely be similar, but you will probably need to recompile SBL_UART if you have a different DDR configuration compared to the EVM. This is not specific to the firmware either, you could load any application using this general flow as well:

    USB DFU Boot-> Boot to SBL_UART->Send images over XMODEM to UART-> Firmware start

    1. Set the bootmode switches for USB DFU boot (in your case, your board would have this by default)
    2. Download and install the MCU+SDK (I used the latest at this time, 12.00.00.27). 
      1. Once installed, cd to <SDK_install_dir>/tools/boot
    3. Download and copy the firmware to <SDK_install_dir>/tools/boot
    4. Build an M4 hello world. This is used later so the MCU+SDK SBL will initialize the M4 memory the tool will be using
      1. gmake -C ..\..\examples\hello_world\am62x-sk-lp\m4fss0-0_nortos\ti-arm-clang\
        cp ..\..\examples\hello_world\am62x-sk-lp\m4fss0-0_nortos\ti-arm-clang\hello_world.release.appimage.hs_fs .\
    5. Create and sign the firmware appimage the SBL can use 
      1. node .\out2rprc\elf2rprc.js .\AM62X_TEye_A53_read.out 0x0C00001B 
        node .\multicoreImageGen\multicoreImageGen.js --devID 55 .\AM62X_TEye_A53_read.rprc@0 --out .\AM62X_TEye_A53_read_unsigned.appimage 
        python .\signing\appimage_x509_cert_gen.py --bin .\AM62X_TEye_A53_read_unsigned.appimage --authtype 0 --loadaddr 84000000 --key .\signing\app_degenerateKey.pem --output .\AM62X_TEye_A53_read_signed.appimage --keyversion 1.5
    6. Send SBL UART over USB DFU (on Linux systems I believe you should have dfu-util by default)
      1. dfu-util-static.exe -R -a bootloader -D ".\sbl_prebuilt\am62x-sk-lp\sbl_uart.release.hs_fs.tiimage"
    7. Send the appimages using XMODEM. There are many ways to do this, but the simplest method is to likely use the serial software of your preference. I used TeraTerm on Windows, but you could modify the python scripts in the SDK for this hybrid bootflow. They are meant for loading the bootloader and application using UART boot, but it is not a large modification for this usecase.
      1. Send the hello world for the M4 first
      2. Send the signed firmware appimage
      3. Send and end of file message, this file can be used: magic_word_file.dat

    Sincerely,

    Lucas

  • Hi Lucas,

    Thanks for info, I will try to load binary.

    Thanks,

    Gireesh

  • Greetings Gireesh,

    Sounds good, let me know if you run into any problems.

    Sincerely,

    Lucas

  • Hi Lucas,

     I Followed the below steps as you suggested and facing the difficulty to load images

    1> update the custom lpddr header form generated tool to ~/ti/mcu_plus_sdk_am62x_12_00_00_27/source/drivers/ddr/v0/soc/am62x/board_lpddrReginit.h

    2> Rebuilt SBL_UART

    make -s -C examples/drivers/boot/sbl_uart/am62x-sk-lp/r5fss0-0_nortos/ti-arm-clang   PROFILE=release    DEVICE_TYPE=HS_FS

    3> compiled hello world

    gmake -C examples/hello_world/am62x-sk-lp/m4fss0-0_nortos/ti-arm-clang/

    4> compiled the firmware by taking the AM62X_TEye_A53_read.out from am62x_ddr_margin_firmware_1_9_0

    node ./out2rprc/elf2rprc.js ./AM62X_TEye_A53_read.out 0x0C00001B

    node ./multicoreImageGen/multicoreImageGen.js --devID 55 ./AM62X_TEye_A53_read.rprc@0 --out ./AM62X_TEye_A53_read_unsigned.appimage

    python3  ./signing/appimage_x509_cert_gen.py --bin ./AM62X_TEye_A53_read_unsigned.appimage --authtype 0 --loadaddr 84000000 --key  ./signing/app_degenerateKey.pem --output ./AM62X_TEye_A53_read_signed.appimage --keyversion 1.5

    Generating certificate for ./AM62X_TEye_A53_read_unsigned.appimage ...

    5> load SBL_uart

    a> check device

    $ dfu-util  -l

    dfu-util 0.11

    Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.

    Copyright 2010-2021 Tormod Volden and Stefan Schmidt

    This program is Free Software and has ABSOLUTELY NO WARRANTY

    Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

     

    Found DFU: [0451:6165] ver=0200, devnum=7, cfg=1, intf=0, path="1-1", alt=1, name="SocId", serial="01.00.00.00"

    Found DFU: [0451:6165] ver=0200, devnum=7, cfg=1, intf=0, path="1-1", alt=0, name="bootloader", serial="01.00.00.00"

     

    b> send sbl

     

    $ dfu-util -R -a bootloader -D "../../examples/drivers/boot/sbl_uart/am62x-sk-lp/r5fss0-0_nortos/ti-arm-clang/sbl_uart.release.hs_fs.tiimage"

    dfu-util 0.11

     

    Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.

    Copyright 2010-2021 Tormod Volden and Stefan Schmidt

    This program is Free Software and has ABSOLUTELY NO WARRANTY

    Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

     

    dfu-util: Warning: Invalid DFU suffix signature

    dfu-util: A valid DFU suffix will be required in a future dfu-util release

    Opening DFU capable USB device...

    Device ID 0451:6165

    Device DFU version 0110

    Claiming USB DFU Interface...

    Setting Alternate Interface #0 ...

    Determining device status...

    DFU state(2) = dfuIDLE, status(0) = No error condition is present

    DFU mode device DFU version 0110

    Device returned transfer size 512

    Copying data from PC to DFU device

    Download        [=========================] 100%       265943 bytes

    Download done.

    DFU state(6) = dfuMANIFEST-SYNC, status(0) = No error condition is present

    dfu-util: unable to read DFU status after completion (LIBUSB_ERROR_TIMEOUT)

     

    5> Now I see "CCCCC" on teraterm.

    6> transfer hello_world.release.appimage.hs_fs via x-modem successful

    7> transfer AM62X_TEye_A53_read_unsigned.appimage/AM62X_TEye_A53_read_signed.appimage  this is not success and XMODEM window closes after some seconds

         enter again in to dfu mode and "CCCCC" seen on teraterm

    $ dfu-util  -l

    dfu-util 0.11

     

    Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.

    Copyright 2010-2021 Tormod Volden and Stefan Schmidt

    This program is Free Software and has ABSOLUTELY NO WARRANTY

    Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

     

    dfu-util: Failed to retrieve language identifiers

    dfu-util: Failed to retrieve language identifiers

    dfu-util: Failed to retrieve language identifiers

    dfu-util: Failed to retrieve language identifiers

    Found DFU: [0451:6165] ver=0200, devnum=13, cfg=1, intf=0, path="1-1", alt=1, name="UNKNOWN", serial="UNKNOWN"

    Found DFU: [0451:6165] ver=0200, devnum=13, cfg=1, intf=0, path="1-1", alt=0, name="UNKNOWN", serial="UNKNOW

     

    Please give suggestion to overcome this issue and can you give access to download magic_word_file.dat

    Regards,

    Gireesh Hiremath

  • Greetings Gireesh,

    The contents of the magic word file are below, you can paste this into a simple text file and send it. Ensure there are no carriage returns or other newline characters.

    EOFT

    After you transfer the hello world, can you wait until you see C characters coming out on the console again? I tested it again and it seemed to take roughly 30 seconds for the SBL to resume outputting again after loading the hello world. 

    I will modify the existing UART bootloader python scripts so we can test the exact same way as well and post it as a follow up.

    Sincerely,

    Lucas

  • Greetings Gireesh,

    You can also try the below python uart bootloader script I've slightly modified. It can be called like:

    python  uart_bootloader.py -p COM23 --bootloader hello_world.release.appimage.hs_fs --file AM62X_TEye_A53_read_signed.appimage

    import os
    import sys
    import getopt
    import time
    import shlex
    import string
    import struct
    
    try:
        import serial
        from tqdm import tqdm
        from xmodem import XMODEM, XMODEM1k
    except ImportError:
        print('[ERROR] Dependant modules not installed, use below pip command to install them. MAKE sure proxy for pip is setup if needed.')
        print('')
        print('python -m pip install pyserial tqdm xmodem --proxy={http://your proxy server:port or leave blank if no proxy}')
        sys.exit(2)
    
    usage_string = '''
    USAGE: python uart_bootloader.py [OPTIONS]
    
    -p, --serial-port=   Serial port to use for the transfer.
                         COM3, COM4 etc if on windows and /dev/ttyUSB1,
                         /dev/ttyUSB2 etc if on linux. Mandatory argument
    
    -b, --bootloader=    Path to the UART Bootloader binary
    
    -f, --file=          Path to the appimage binary
    
    --cfg=               Path to the configuration file with the entries of the two flags given above, namely bootloader and file.
                         This file can be used as an alternative to passing the two flags given above.
                         Use either the --cfg flag or the --bootloader and --file flags.
    '''
    
    BOOTLOADER_UART_STATUS_LOAD_SUCCESS            = 0x53554343
    BOOTLOADER_UART_STATUS_LOAD_FAIL               = 0x4641494C
    BOOTLOADER_UART_STATUS_APPIMAGE_SIZE_EXCEEDED  = 0x45584344
    
    BOOTLOADER_END_OF_FILES_TRANSFER               = 0x454F4654
    BOOTLOADER_END_OF_FILES_TRANSFER_WORD_LENGTH   = 4
    
    BOOTLOADER_UART_MAGIC                          = 0xBF0000BF
    BOOTLOADER_UART_FILE_RECEIVE_COMPLETE          = 0xBF000002
    BOOTLOADER_UART_SEND_FILE                      = 0xBF000003
    
    mySerPort = "No Serial Port Chosen"
    myBaudRate = 115200
    ser = serial.Serial(timeout=30)
    
    def open_serial_port():
        ser.baudrate = 115200
        ser.port = mySerPort
        ser.open()
    
    def close_serial_port():
        ser.close()
    
    # Parse response sent from EVM
    def parse_response_evm(filename):
        f = open(filename, "rb")
        resp_bytes = f.read(128)
        f.close()
    
        status = 0
    
        response = int.from_bytes(resp_bytes[0:4], 'little')
    
        if(response == BOOTLOADER_UART_STATUS_LOAD_SUCCESS):
            status = "[STATUS] Application load SUCCESS !!!"
        elif(response == BOOTLOADER_UART_STATUS_LOAD_FAIL):
            status = "[STATUS] ERROR: Application load FAILED !!!"
        elif(response == BOOTLOADER_UART_STATUS_APPIMAGE_SIZE_EXCEEDED):
            status = "[STATUS] ERROR: Application load FAILED, file size exceeds LIMIT on the EVM !!!"
        else:
            status = "[STATUS] ERROR: Bad response from EVM !!!"
    
        return status
    
    # Parse message requests for program segments from EVM
    def parse_msg_response(resp_bytes):
        '''
        /* UART protocol request header */
        typedef struct Bootloader_UartProtocolReq_s
        {
            uint64_t magic;
            uint64_t virtMemOffset;
            uint64_t cmd;
            uint64_t len;
    
        } Bootloader_UartProtocolReq;
        '''
    
        uart_header_str = "<QQQQ"
    
        status = -1
    
        magic, virt_mem_offset, cmd , req_length = struct.unpack(uart_header_str, resp_bytes)
    
        if(magic == BOOTLOADER_UART_MAGIC):
            status = 0
        else:
            status = -1
    
        return status, cmd, virt_mem_offset, req_length
    
    # Send the file to EVM
    def xmodem_send_file(port, baudrate, timeout, f_stream, show_progress):
    
        status = None
        open_serial_port();
    
        f_stream.seek(0, os.SEEK_END)
        bar_filesize = f_stream.tell()
        f_stream.seek(0, os.SEEK_SET)
    
        if show_progress:
            bar = tqdm(total=bar_filesize, unit="bytes", leave=True, desc="Sending file part ...")
            def getc(size, timeout=1):
                return ser.read(size) or None
    
            def putc(data, timeout=1):
                bar.update(len(data));
                bar.refresh()
                return ser.write(data)  # note that this ignores the timeout
    
            modem = XMODEM1k(getc, putc)
    
            status = modem.send(f_stream, retry=100, quiet=True)
    
            bar.close()
        else:
            def getc(size, timeout=1):
                return ser.read(size) or None
    
            def putc(data, timeout=1):
                return ser.write(data)  # note that this ignores the timeout
    
            modem = XMODEM1k(getc, putc)
    
            status = modem.send(f_stream, retry=100, quiet=True)
    
        close_serial_port()
    
        return status
    
    #Receive the file from EVM
    def xmodem_recv_file(port, baudrate, timeout):
    
        receiverespfilename = "receiverespfile.part"
        recvrespfile = open(receiverespfilename, "wb")
    
        open_serial_port();
    
        def getc(size, timeout=1):
            return ser.read(size) or None
    
        def putc(data, timeout=1):
            return ser.write(data)  # note that this ignores the timeout
    
        modem = XMODEM1k(getc, putc)
        status = modem.recv(recvrespfile, quiet=True, timeout=1000)
    
        close_serial_port()
    
        recvrespfile.close()
    
        return receiverespfilename
    
    # Sends the mcelf image meta data, program segments as requested by EVM via xmodem
    # Receives request from EVM, parse the request frame and send the requested segment
    def xmodem_send_segments(filename, serialport, baudrate=115200, timeout=10):
        status = False
        timetaken = 0
        show_progress=True
    
        total_file_size = os.path.getsize(filename)
        print(f"Total filesize = {total_file_size} bytes")
    
        #Open the file
        try:
            stream = open(filename, 'rb')
        except FileNotFoundError:
            print('[ERROR] File [' + filename + '] not found !!!');
            sys.exit();
    
        #Read the file
        file_bytes = stream.read()
        stream.close()
    
        stop_transaction = False
    
        respfilename = "resp_cmd.dat"
        resp_status = -1
        offset = -1
        req_length = -1
    
        #Send the initial metadata of file of around 8kB
        tstart = time.time()
    
        with open("tempfilepart.part", 'wb') as f_part:
            f_part.write(file_bytes[0:8192])
        part_stream = open("tempfilepart.part", 'rb')
        xmodem_send_file(serialport, baudrate, timeout, part_stream, show_progress)
        part_stream.close()
        os.remove("tempfilepart.part")
    
        #Receive the request frame from target containing the offset and length of required segment
        while(not stop_transaction):
            resp_file_name = xmodem_recv_file(serialport, baudrate, 100)
            resp_fh = open(resp_file_name, "rb")
            buf = resp_fh.read(32)
            resp_fh.close()
            os.remove(resp_file_name)
            resp_status, cmd, virt_mem_offset, req_length = parse_msg_response(buf)
    
            if(resp_status==0):
                if(cmd == BOOTLOADER_UART_SEND_FILE):
                    if(virt_mem_offset+req_length <= total_file_size):
                        # Create a tempfile with the size requested
                        with open("tempfilepart.part", 'wb') as f_part:
                            f_part.write(file_bytes[virt_mem_offset:virt_mem_offset+req_length])
                    else:
                    # Error
                       print(f"Request exceeding file size !! Sending remaining bytes ...")
    
                    part_stream = open("tempfilepart.part", 'rb')
                    xmodem_send_file(serialport, baudrate, timeout, part_stream, show_progress)
                    part_stream.close()
                    os.remove("tempfilepart.part")
    
                elif(cmd == BOOTLOADER_UART_FILE_RECEIVE_COMPLETE):
                    resp_status = "[STATUS] Application load SUCCESS !!!"
                    stop_transaction = True
                else:
                    resp_status = "[STATUS] ERROR: Application load FAILED !!!"
            else:
                pass
    
        tstop = time.time()
        timetaken = (tstop - tstart)
    
        return resp_status, timetaken
    
    # Sends the file to EVM via xmodem, receives response from EVM and returns the response status
    def xmodem_send_receive_file(filename, serialport, baudrate=115200, get_response=True):
        status = False
        timetaken = 0
        try:
            global mySerPort, myBaudRate
            bar_filesize = os.path.getsize(filename)
            mySerPort = serialport
            myBaudRate = baudrate
            open_serial_port();
            stream = open(filename, 'rb')
        except FileNotFoundError:
            print('[ERROR] File [' + filename + '] not found !!!')
            sys.exit()
        except serial.serialutil.SerialException:
            print('[ERROR] Serial port [' + serialport + '] not found or not accessible !!!')
            sys.exit()
    
        bar_cursize = 0
        bar = tqdm(total=bar_filesize, unit="bytes", leave=False, desc="Sending {}".format(filename))
    
        def getc(size, timeout=1):
            return ser.read(size) or None
    
        def putc(data, timeout=1):
            bar.update(len(data))
            bar.refresh()
            return ser.write(data)  # note that this ignores the timeout
    
        try:
            modem = XMODEM1k(getc, putc)
            tstart = time.time()
            status = modem.send(stream, quiet=True, timeout=30, retry=10)
            tstop = time.time()
            timetaken = round(tstop-tstart, 2)
        except:
            status = False
    
        stream.close()
    
        if( status is False ) :
            print("")
            print ("[ERROR] XMODEM send failed, no response OR incorrect response from EVM OR cancelled by user,");
            print ("        Power cycle EVM and run this script again !!!");
            sys.exit()
    
        resp_status = 0
    
        # Don't do the receive if get_response is False
        if(get_response):
            respfilename = "resp_uart_bootloader.dat"
            try:
                respfile = open(respfilename, "wb")
                status = modem.recv(respfile, quiet=True, timeout=20)
                respfile.close()
                resp_status = parse_response_evm(respfilename)
                os.remove(respfilename)
            except:
                status = None
            if( status is None ) :
                print("")
                print ("[ERROR] XMODEM recv failed, no response OR incorrect response from EVM OR cancelled by user,");
                print ("        Power cycle EVM and run this script again !!!");
                sys.exit()
    
        close_serial_port()
    
        bar.close()
    
        return resp_status, timetaken
    
    def main(argv):
    
        def help() :
            print(usage_string)
    
        serialport = None
        appimage_file = None
        bootloader_file = None
        config_file = None
    
        try:
            opts, args = getopt.getopt(argv,"hf:b:p:",["help", "file=","bootloader=","serial-port=","cfg="])
        except getopt.GetoptError:
            help()
            sys.exit()
        for opt, arg in opts:
            if opt in ("-h", "--help"):
                help()
                sys.exit()
            elif opt in ("-f, --file"):
                appimage_file = arg
            elif opt in ("-b", "--bootloader"):
                bootloader_file = arg
            elif opt in ("-p", "--serial-port"):
                serialport = arg
            elif opt in ("--cfg"):
                config_file = arg
    
        status = 0
    
        if(serialport == None):
                status = "[ERROR] Provide a serial port with option -p or --serial-port=, use -h option to see detailed help !!!"
                print(status)
                sys.exit()
    
        if(config_file != None):
            # Check if file exists
            if not os.path.exists(config_file):
                print('[ERROR] Configuration file [' + config_file + '] not found !!!')
                sys.exit()
    
            print("")
            print("Parsing config file ...")
            filecfg = FileCfg(config_file)
            parse_status = filecfg.parse()
    
            if(filecfg.soc_index != None):
                device = filecfg.cfgs[filecfg.soc_index].soc
            else:
                device = None
    
            if(parse_status != 0):
                print(parse_status)
                sys.exit()
    
            else:
    
                print("Parsing config file ... SUCCESS. Found {} command(s) !!!".format(len(filecfg.cfgs)))
                print("")
    
                if(filecfg.soc_index != None):
                    length = len(filecfg.cfgs) - 1
                else:
                    length = len(filecfg.cfgs)
    
                if(filecfg.bootloader_index != None):
                    cfg_bootloader_file = filecfg.cfgs[filecfg.bootloader_index].bootloader
                    print("Executing command {} of {} ...".format(1, length))
                    print("Found the UART bootloader ... sending {}".format(cfg_bootloader_file))
                    send_status, timetaken = xmodem_send_receive_file(cfg_bootloader_file, serialport, get_response=False)
                    print("Sent bootloader {} of size {} bytes in {}s.".format(cfg_bootloader_file, os.path.getsize(cfg_bootloader_file), timetaken))
                    print("")
    
                else:
                    status = "[ERROR] Provide path to the uart bootloader binary with option -b or --bootloader=, use -h option to see detailed help !!!"
                    print(status)
                    sys.exit()
    
                # loop through cfgs and lines, skip the process for bootloader
                for i in range(0, len(filecfg.cfgs)):
                    if((i != filecfg.bootloader_index) and (i != filecfg.soc_index)):
                        line = filecfg.lines[i]
                        linecfg = filecfg.cfgs[i]
                        orig_filename = linecfg.filename
    
                        if(filecfg.soc_index != None):
                            curr = i
                        else:
                            curr = i+1
    
                        print("Executing command {} of {} ...".format(curr, length))
                        print("Command arguments : {}".format(line.rstrip('\n')))
    
                        if(device != "am275x"):
                           send_status, timetaken = xmodem_send_receive_file(linecfg.filename, serialport, get_response=True)
                        elif(device == "am275x"):
                            send_status, timetaken = xmodem_send_segments(linecfg.filename, serialport)
    
                        print("Sent {} of size {} bytes in {}s.".format(orig_filename, os.path.getsize(orig_filename), timetaken))
                        print(send_status)
                        print("")
    
                if(length != 1):
                    magic_word_filename = "magic_word_file.dat"
                    magic_word_file     = open(magic_word_filename,"wb")
                    magic_word_bytes    = BOOTLOADER_END_OF_FILES_TRANSFER.to_bytes(BOOTLOADER_END_OF_FILES_TRANSFER_WORD_LENGTH,"big")
                    magic_word_file.write(magic_word_bytes)
                    magic_word_file.close()
                    sendd_status, timetaken = xmodem_send_receive_file(magic_word_filename, serialport, get_response=False)
                    print("")
                    print(" Sent End Of File Transfer message of size {} bytes in {}s.".format( os.path.getsize(magic_word_filename), timetaken))
                    print("")
                    os.remove(magic_word_filename)
                    print("All commands from config file are executed !!!")
                    if("SUCCESS" in send_status):
                        print("Connect to UART in 5 seconds to see logs from UART !!!")
    
        else:
            # Validate the cmdline config
            if(bootloader_file == None):
                status = "[ERROR] Provide path to the uart bootloader binary with option -b or --bootloader=, use -h option to see detailed help !!!"
                print(status)
                sys.exit()
    
            if(appimage_file == None):
                status = "[ERROR] Provide path to an appimage binary to be sent via UART with option -f or --file=, , use -h option to see detailed help !!!"
                print(status)
                sys.exit()
    
            if(status == 0):
                # Check both SBL and appimage files exists
                try:
                    appimage_file_handle = open(appimage_file, "r")
                except FileNotFoundError:
                    status = '[ERROR] Application file [' + appimage_file + '] not found !!!'
                    print(status)
                    sys.exit()
    
                try:
                    bootloader_file_handle = open(bootloader_file, "r")
                except FileNotFoundError:
                    status = '[ERROR] Bootloader file [' + bootloader_file + '] not found !!!'
                    print(status)
                    sys.exit()
    
                # All good, now send files
                print("Sending the UART bootloader {} ...".format(bootloader_file))
                send_status, timetaken = xmodem_send_receive_file(bootloader_file, serialport, get_response=True)
                print("Sent bootloader {} of size {} bytes in {}s.".format(bootloader_file, os.path.getsize(bootloader_file), timetaken))
                print("")
    
                print("Sending the application {} ...".format(appimage_file))
                send_status, timetaken = xmodem_send_receive_file(appimage_file, serialport, get_response=True)
                print("Sent application {} of size {} bytes in {}s.".format(appimage_file, os.path.getsize(appimage_file), timetaken))
                print(send_status)
                
                magic_word_filename = "magic_word_file.dat"
                magic_word_file     = open(magic_word_filename,"wb")
                magic_word_bytes    = BOOTLOADER_END_OF_FILES_TRANSFER.to_bytes(BOOTLOADER_END_OF_FILES_TRANSFER_WORD_LENGTH,"big")
                magic_word_file.write(magic_word_bytes)
                magic_word_file.close()
                sendd_status, timetaken = xmodem_send_receive_file(magic_word_filename, serialport, get_response=False)
                print("")
                print(" Sent End Of File Transfer message of size {} bytes in {}s.".format( os.path.getsize(magic_word_filename), timetaken))
                print("")
                os.remove(magic_word_filename)
                print("All commands from config file are executed !!!")
                if("SUCCESS" in send_status):
                    print("Connect to UART in 5 seconds to see logs from UART !!!")
    
    # Class definitions used
    class LineCfg():
        def __init__(self, line=None, filename=None, bootloader=None, soc=None):
            self.line = line
            self.filename = filename
            self.bootloader = bootloader
            self.exit_now = False
            self.soc = soc
    
        # Takes a string of comma separated key=value pairs and parses into a dictionary
        def parse_to_dict(self, config_string):
            config_dict = dict()
            splitter = shlex.shlex(config_string, posix=True)
            splitter.commenters="#"
            splitter.whitespace = ' '
            splitter.whitespace_split = True
    
            for key_value_pair in splitter:
                kv = key_value_pair.strip()
                if not kv:
                    continue
                kv_t = kv.split('=', 1)
                if(len(kv_t)==1):
                    #error, no value
                    pass
                else:
                    config_dict[kv_t[0]] = kv_t[1]
    
            return config_dict
    
        def validate(self):
            status = 0
            if(self.line!=None):
                # Called from config_file
                config_dict = self.parse_to_dict(self.line)
    
                if not config_dict:
                    status = "invalid_line"
                else:
                    # check for bootloader
                    if ("--bootloader" not in config_dict.keys() and "--soc" not in config_dict.keys()):
                        if "--file" not in config_dict.keys():
                            status = "[ERROR] No filename provided !!!"
                            return status
                        else:
                            self.filename = config_dict["--file"]
    
                        try:
                            f = open(self.filename)
                        except FileNotFoundError:
                            status = "[ERROR] File not found !!!"
                            return status
    
                    elif("--bootloader" in config_dict.keys()):
                        self.bootloader = config_dict["--bootloader"]
    
                        try:
                            f = open(self.bootloader)
                        except FileNotFoundError:
                            status = "[ERROR] Bootloader file not found !!!"
                            return status
    
                    elif("--soc" in config_dict.keys()):
                        self.soc = config_dict["--soc"]
                        return status
            else:
                # Should not hit this
                status = -1
            return status
    
    class FileCfg():
        def __init__(self, filename=None):
            self.filename = filename
            self.lines = list()
            self.cfgs = list()
            self.errors = list()
            self.soc_index = None
            self.bootloader_index = None
    
        def parse(self):
            f = open(self.filename, "r")
            lines = f.readlines()
            f.close()
            parse_status = 0
            linecount = 0
            found_fw = False
            valid_cfg_count = 0
    
            for line in lines:
                linecfg = LineCfg(line=line)
                status = linecfg.validate()
    
                if(status != 0 and status != "invalid_line"):
                    self.errors.append("[ERROR] Parsing error found on line {} of {}\n{}\n".format(linecount+1, self.filename, status))
                else:
                    if(status != "invalid_line"):
                        if(linecfg.bootloader != None):
                            if(found_fw == True):
                                # error, another instance of bootloader found
                                bootloader_error_msg = "[ERROR] Redefinition of Bootloader !!!"
                                self.errors.append("[ERROR] Parsing error found on line {} of {}\n{}\n".format(linecount+1, self.filename, bootloader_error_msg))
                            else:
                                found_fw = True
                                self.cfgs.append(linecfg)
                                self.lines.append(line.rstrip('\n'))
                                self.bootloader_index = valid_cfg_count
                                valid_cfg_count += 1
                        elif(linecfg.soc != None):
                            self.cfgs.append(linecfg)
                            self.lines.append(line.rstrip('\n'))
                            self.soc_index = valid_cfg_count
                            valid_cfg_count += 1
                        else:
                            self.cfgs.append(linecfg)
                            self.lines.append(line.rstrip('\n'))
                            valid_cfg_count += 1
                linecount += 1
    
            if(len(self.errors) > 0):
                # Some commands have errors
                parse_status = "Parsing config file ... ERROR. {} error(s).\n\n".format(len(self.errors)) + "\n".join(self.errors)
    
            return parse_status
    
    if __name__ == "__main__":
       main(sys.argv[1:])

    This script will automatically create and delete the magic word file, no need to send it manually.

    Sincerely,

    Lucas

  • Hi Lucas,

    I tried to load binary with latest uart_bootloader.py but still it struck 

    1> load SBL_UART through dfu => loaded 

    2> load firmware : hello_world.release.appimage.hs_fs => loaded 

                                  AM62X_TEye_A53_read_signed.appimage => fail and gives "XMODEM send failed"

    log as below

    /mcu_plus_sdk_am62x_12_00_00_27/tools/boot$ python uart_bootloader.py -p /dev/ttyUSB0 --bootloader hello_world.release.appimage.hs_fs --file AM62X_TEye_A53_read_signed.appimage
    Sending the UART bootloader hello_world.release.appimage.hs_fs ...
    Sent bootloader hello_world.release.appimage.hs_fs of size 26717 bytes in 4.3s.                                                   

    Sending the application AM62X_TEye_A53_read_signed.appimage ...
    Sending AM62X_TEye_A53_read_signed.appimage:   0%|                                                  | 0/219702 [00:00<?, ?bytes/s]send error: error_count reached 10, aborting.
    Sending AM62X_TEye_A53_read_signed.appimage:   0%|                                     | 2/219702 [00:33<2017:25:19, 33.06s/bytes]
    [ERROR] XMODEM send failed, no response OR incorrect response from EVM OR cancelled by user,
            Power cycle EVM and run this script again !!!

    Please give suggestion,

    Regards,

    Gireesh Hiremath

  • Greetings Gireesh,

    Let's start with some basic steps:

    1. Do you have an SK-AM62-LP EVM to sanity check this flow with your setup?
    2. If you send the hello world manually over XMODEM to your custom board, can you confirm you see any C character output from the SBL after sending? This took roughly 30 seconds after being sent on my setup. 
      1. If you do confirm C characters after the hello world has finished, this should indicate the SBL is ready to receive another image. Then try sending the eye manually again at this point.

    Sincerely,

    Lucas

  • Hi Lucas,

    Thanks for the information. Now I am able to generate eye diagram from our custom am62x HS-FS device.

    Next I need to generate same on HS device,  for that, generated the SBL_UART by copying the our custMpk.pem  but not getting "CCC" after loading "sbl_uart.release.hs.tiimage".

    Please Give suggestion.

    Regards,

    Gireesh Hiremath  

  • Greetings Gireesh,

    I cannot help with that, I will re-assign this thread to another colleague who can. Please give them time to understand the issue you're presenting and come back with a response.

    Sincerely,

    Lucas

  • Hi,

    Next I need to generate same on HS device,  for that, generated the SBL_UART by copying the our custMpk.pem  but not getting "CCC" after loading "sbl_uart.release.hs.tiimage".

    Once you boot SBL over UART, you wouldn't see the CCC being printed on the console.

    ROM Code sends these C characters over UART when SoC is configured in UART boot mode and it is waiting for an image (SBL), as you have already booted SBL, you will not see these characters being printed.

    Best Regards,

    Meet.

  • Hi Meet Thakar,

    Currently for AM62x HS FS: I am loading "sbl_uart.release.hs_fs.tiimage via DFU then I am able to see "CCC" on console, further binary loaded via Xmodem from teraterm to get eye diagram.

    For AM62x HS FS : included our custMpk.pem and rebuilt "sbl_uart.release.hs.tiimage", after loading this over DFU not able to see "CCC" on console to load further binary.

    Please give suggestion, any other action need to be taken to build "sbl_uart.release.hs.tiimage"

    Regards,

    Gireesh Hiremath