LdB
Posts: 903
Joined: Wed Dec 07, 2016 2:29 pm

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Mon Jun 18, 2018 9:32 am

Okay I have been thru this to death and even setup xinu in 64bit on the Pi3 and the behaviour is absolutely consistent.

What I do notice compared to my usb driver is there is no real setup except hitting the fifo registers and clearing interrupts on the xinu code it just sort of seems to assumes it is setup ready to go. Many of the registers USPI, circle and I hit are actual untouched in the driver. So my guess is there is some setup that we need on the Pi3.

So I will try moving some of my setup code into the xinu driver and see what happens :-)

rlatinov
Posts: 22
Joined: Mon Jun 26, 2017 7:35 pm

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Mon Jun 18, 2018 2:41 pm

I noticed as well that the setup code is very sparse, which is what I originally thought was the issue. I will take a look at your code and see how you set it up and see if I can learn anything.

LdB
Posts: 903
Joined: Wed Dec 07, 2016 2:29 pm

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Mon Jun 18, 2018 2:44 pm

SOLVED IT .. I end up almost replacing all the code before I noticed the dam thing.

It wasn't the setup ... the code didn't change the ARM address to VC address for the DMA transfer.
I am surprised it got away with it even on the old Pi1.
With the MMU on that is a drop dead on the Pi2 or Pi3.

So two lines you need to fix in "dwc_channel_start_xfer".
It's the OR'ing of the 0xC0000000 to convert the address from ARM to VC4

Code: Select all

  /* Set up DMA buffer.  */
    if (IS_WORD_ALIGNED(data))
    {
        /* Can DMA directly from source or to destination if word-aligned.  */
        chanptr->dma_address = (uint32_t)data | 0xC0000000;
    }
    else
    {
        /* Need to use alternate buffer for DMA, since the actual source or
         * destination is not word-aligned.  If the attempted transfer size
         * overflows this alternate buffer, cap it to the greatest number of
         * whole packets that fit.  */
        chanptr->dma_address = (uint32_t)aligned_bufs[chan] | 0xC0000000;
It's really slow connecting will need to look at that process and I suspect it may get the stall bug because of lack of startup code. If you want me to patch that in let me know.

If you end up with a good sample throw me a link, I am doing the AARCH64 version at the moment and cleaning some of this stuff up.

rlatinov
Posts: 22
Joined: Mon Jun 26, 2017 7:35 pm

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Mon Jun 18, 2018 3:14 pm

Wow! Thanks!

The ARM to VC address conversion was a damn good catch, I don't know how you saw that!
The LAN7515 hub looks like it is attaching properly now!

I took out the FPU code that you included because, for some reason, it made the UART input stop working properly, making it unable to type in the shell.

Another thing is now that when I run the command usbinfo after it connects, it doesn't show the device there, even though it looks like it attaches properly made visible by the USB debug messages.

Code: Select all

xsh$ usbinfo                                                                                                                                                                                          
[USB Device 001]                                                                                                                                                                                                
    [Device Descriptor]                                                                                                                                                                                         
    bLength:             18
    bDescriptorType:     0x01 (Device)
    bcdUSB:              0x200 (USB 2.0 compliant)
    bDeviceClass:        0x09 (Hub)
    bDeviceSubClass:     0x00
    bDeviceProtocol:     0x00
    bMaxPacketSize0:     64
    idVendor:            0x0000
    idProduct:           0x0000
    iManufacturer:       0
    iProduct:            1
    iSerialNumber:       0
    bNumConfigurations:  1

        [Configuration Descriptor]
        bLength:             9
        bDescriptorType:     0x02 (Configuration)
        wTotalLength:        25
        bNumInterfaces:      1
        bConfigurationValue: 1
        iConfiguration:      0
        bmAttributes:        0xc0
            (Self powered)
        bMaxPower:           0 (0 mA)

            [Interface Descriptor]
            bLength:             9
            bDescriptorType:     0x04 (Interface)
            bInterfaceNumber:    0
            bAlternateSetting:   0
            bNumEndpoints:       1
            bInterfaceClass:     0x09 (Hub)
            bInterfaceSubClass:  0x00
            bInterfaceProtocol:  0x00
            iInterface:          0

                [Endpoint Descriptor]
                bLength:             7
                bDescriptorType:     0x05 (Endpoint)
                bEndpointAddress:    0x81 (Number 1, IN)
                bmAttributes:        0x03 (interrupt endpoint)
                wMaxPacketSize:      0x40 (max packet size 64 bytes)
                bInterval:           255



Diagram of USB:

001 [high-speed USB 2.0 Hub class device (idVendor=0x0000, idProduct=0x0000)]
It still shows only the root hub, despite the debug messages clearly showing that it attached as a hub device.

UPDATE: ignore that... it just needed some extra time to register everything..

LdB
Posts: 903
Joined: Wed Dec 07, 2016 2:29 pm

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Mon Jun 18, 2018 3:24 pm

Yeah was slow attaching .. I noticed.

The typing will be the context switch with interrupt I need to look at the interrupt routine, the switcher was so simple I thought they just turned them off. Pretty easy to fix let you know when it's done, should do the fiq at same time in case it gets used.

So I will change the file irq_handler.S and add to the changed files in the repo when done, it needs to save those extra registers. Sorry been ages since I played around with a switcher this simple I forgot about it.
Last edited by LdB on Mon Jun 18, 2018 3:31 pm, edited 1 time in total.

rlatinov
Posts: 22
Joined: Mon Jun 26, 2017 7:35 pm

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Mon Jun 18, 2018 3:30 pm

Great to hear!

I also noticed one more thing. After waiting a few minutes for all the devices to be attached, it shows that there are 2 LAN7515 hubs...

Code: Select all

Diagram of USB:

001 [high-speed USB 2.0 Hub class device (idVendor=0x0000, idProduct=0x0000)]
|
|
------002 [high-speed USB 2.0 Hub class device (idVendor=0x0424, idProduct=0x2514)]
      |
      |
      ------003 [high-speed USB 2.0 Hub class device (idVendor=0x0424, idProduct=0x2514)]
            |
            |
            ------004 [high-speed USB 2.1 device (idVendor=0x0424, idProduct=0x7800)]
            |
            |
            ------005 [low-speed USB 2.0 HID (Human Interface Device) class device (idVendor=0x03f0, idProduct=0x134a)]
1 = roothub
2 = LAN hub
3 = is also LAN hub..??
4 = ethernet device
5 = mouse

Their descriptors also look identical...

Code: Select all

[USB Device 002] 
    [Device Descriptor]                                                                                                                                                                                                                                                                                                                      
    bLength:             18                                                                                                                                                                                                                                                                                                                  
    bDescriptorType:     0x01 (Device)                                                                                                                                                                                                                                                                                                       
    bcdUSB:              0x200 (USB 2.0 compliant)                                                                                                                                                                                                                                                                                           
    bDeviceClass:        0x09 (Hub)                                                                                                                                                                                                                                                                                                          
    bDeviceSubClass:     0x00
    bDeviceProtocol:     0x02
    bMaxPacketSize0:     64
    idVendor:            0x0424
    idProduct:           0x2514
    iManufacturer:       0
    iProduct:            0
    iSerialNumber:       0
    bNumConfigurations:  1

        [Configuration Descriptor]
        bLength:             9
        bDescriptorType:     0x02 (Configuration)
        wTotalLength:        41
        bNumInterfaces:      1
        bConfigurationValue: 1
        iConfiguration:      0
        bmAttributes:        0xe0
            (Self powered)
            (Remote wakeup)
        bMaxPower:           1 (2 mA)

            [Interface Descriptor]
            bLength:             9
            bDescriptorType:     0x04 (Interface)
            bInterfaceNumber:    0
            bAlternateSetting:   0
            bNumEndpoints:       1
            bInterfaceClass:     0x09 (Hub)
            bInterfaceSubClass:  0x00
            bInterfaceProtocol:  0x01
            iInterface:          0

                [Endpoint Descriptor]
                bLength:             7
                bDescriptorType:     0x05 (Endpoint)
                bEndpointAddress:    0x81 (Number 1, IN)
                bmAttributes:        0x03 (interrupt endpoint)
                wMaxPacketSize:      0x01 (max packet size 1 bytes)
                bInterval:           12

Code: Select all

[USB Device 003]
    [Device Descriptor]
    bLength:             18
    bDescriptorType:     0x01 (Device)
    bcdUSB:              0x200 (USB 2.0 compliant)
    bDeviceClass:        0x09 (Hub)
    bDeviceSubClass:     0x00
    bDeviceProtocol:     0x02
    bMaxPacketSize0:     64
    idVendor:            0x0424
    idProduct:           0x2514
    iManufacturer:       0
    iProduct:            0
    iSerialNumber:       0
    bNumConfigurations:  1

        [Configuration Descriptor]
        bLength:             9
        bDescriptorType:     0x02 (Configuration)
        wTotalLength:        41
        bNumInterfaces:      1
        bConfigurationValue: 1
        iConfiguration:      0
        bmAttributes:        0xe0
            (Self powered)
            (Remote wakeup)
        bMaxPower:           1 (2 mA)

            [Interface Descriptor]
            bLength:             9
            bDescriptorType:     0x04 (Interface)
            bInterfaceNumber:    0
            bAlternateSetting:   0
            bNumEndpoints:       1
            bInterfaceClass:     0x09 (Hub)
            bInterfaceSubClass:  0x00
            bInterfaceProtocol:  0x01
            iInterface:          0

                [Endpoint Descriptor]
                bLength:             7
                bDescriptorType:     0x05 (Endpoint)
                bEndpointAddress:    0x81 (Number 1, IN)
                bmAttributes:        0x03 (interrupt endpoint)
                wMaxPacketSize:      0x01 (max packet size 1 bytes)
                bInterval:           12

LdB
Posts: 903
Joined: Wed Dec 07, 2016 2:29 pm

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Mon Jun 18, 2018 3:33 pm

Yes it is a bug in the original code they translated .. I had a post on the forum complaining same thing.
Here:
https://lb.raspberrypi.org/forums/viewt ... p?t=178162

How do you get it display the tree and I will patch it?

rlatinov
Posts: 22
Joined: Mon Jun 26, 2017 7:35 pm

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Mon Jun 18, 2018 3:35 pm

Bug in who's code?

If you have access to input (keyboard or uart), there is a shell command "usbinfo" that prints out the information of the devices and the device tree.

LdB
Posts: 903
Joined: Wed Dec 07, 2016 2:29 pm

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Mon Jun 18, 2018 3:40 pm

I got the screen up now as well but slow as .. need to go look at it.
Cheers need to read up on using this thing.
I haven't looked yet are all the core switching there is some weird messages going thru debugger stub?

Oh the bug is in the enumeration of the fake hub (tm) code it enumerates the onboard hub twice, you wont get it on the Pi1 because it powers different. There is an actual reset of the physical port on the Pi2/3 and you get two port status changes.
Last edited by LdB on Mon Jun 18, 2018 3:46 pm, edited 2 times in total.

rlatinov
Posts: 22
Joined: Mon Jun 26, 2017 7:35 pm

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Mon Jun 18, 2018 3:44 pm

Currently, only Core 0 is running and Cores 1,2,3 are staying in a sleep state.
They can be started by using unparkcore() and specifying what method you want it to run.

That's what I figured what was happening, although I don't know what's causing the bug.
Oh the bug is in the enumeration of the fake hub (tm) code it enumerates the onboard hub twice, you wont get it on the Pi1 because it powers different. There is an actual reset of the physical port on the Pi2/3 and you get two port status changes.
Is it because the dwc sends packets to it at different times, resets it, then sees it as a new device?

User avatar
Ultibo
Posts: 137
Joined: Wed Sep 30, 2015 10:29 am
Location: Australia
Contact: Website

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Tue Jun 19, 2018 12:34 am

rlatinov wrote:
Mon Jun 18, 2018 3:30 pm
I also noticed one more thing. After waiting a few minutes for all the devices to be attached, it shows that there are 2 LAN7515 hubs...

1 = roothub
2 = LAN hub
3 = is also LAN hub..??
4 = ethernet device
5 = mouse
Hi rlatinov,

The Pi3B+ has two hubs built into the LAN7515 device, this is normal and enumerates exactly the same under Linux.

See here https://www.rs-online.com/designspark/r ... -3-model-b

PS. Great that you are working on porting Xinu to support newer Pi models, it's a great resource and far better for people to learn real OS concepts from than many of the simplified bare metal examples around. It does make some assumptions though which will not be true if you want to implement multi-core etc so you will have some hard work to do.
Ultibo.org | Make something amazing
https://ultibo.org

Threads, multi-core, OpenGL, Camera, FAT, NTFS, TCP/IP, USB and more in 3MB with 2 second boot!

LdB
Posts: 903
Joined: Wed Dec 07, 2016 2:29 pm

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Wed Jun 20, 2018 6:02 pm

rlatinov any chance I could get a conf.h with everything on, so it saves me having to install linux :-)

Got everything working I think and just leaves me to deal with multicore which I suspect I will have to rework the switcher.

rlatinov
Posts: 22
Joined: Mon Jun 26, 2017 7:35 pm

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Wed Jun 20, 2018 8:42 pm

The Pi3B+ has two hubs built into the LAN7515 device, this is normal and enumerates exactly the same under Linux.
That's good to know thanks.

LdB,
Could you elaborate on what you said earlier,
It's really slow connecting will need to look at that process and I suspect it may get the stall bug because of lack of startup code. If you want me to patch that in let me know.
I still am getting the slow attachment times, despite my efforts to change it.

Also,
I enabled everything in xinu.conf and platformVars and here is the conf.h and conf.c:

Code: Select all

/* conf.h (GENERATED FILE; DO NOT EDIT) */

#ifndef _CONF_H_
#define _CONF_H_

#include <stddef.h>

/* Device table declarations */

/* Device table entry */
typedef struct dentry
{
    int     num;
    int     minor;
    char    *name;
    devcall (*init)(struct dentry *);
    devcall (*open)(struct dentry *, ...);
    devcall (*close)(struct dentry *);
    devcall (*read)(struct dentry *, void *, uint);
    devcall (*write)(struct dentry *, const void *, uint);
    devcall (*seek)(struct dentry *, long);
    devcall (*getc)(struct dentry *);
    devcall (*putc)(struct dentry *, char);
    devcall (*control)(struct dentry *, int, long, long);
    void    *csr;
    void    (*intr)(void);
    uchar   irq;
} device;

extern const device devtab[]; /* one entry per device */

/* Device name definitions */

#define SERIAL0     0       /* type uart     */
#define USBKBD0     1       /* type usbkbd   */
#define KBDMON0     2       /* type kbdmon   */
#define FRAMEBUF    3       /* type framebuffer */
#define DEVNULL     4       /* type null     */
#define LOOP0       5       /* type loopback */
#define CONSOLE     6       /* type tty      */
#define TTY1        7       /* type tty      */
#define TTYLOOP     8       /* type tty      */
#define ETH0        9       /* type ether    */
#define ELOOP       10       /* type ethloop  */
#define RAW0        11       /* type raw      */
#define RAW1        12       /* type raw      */
#define UDP0        13       /* type udp      */
#define UDP1        14       /* type udp      */
#define UDP2        15       /* type udp      */
#define UDP3        16       /* type udp      */
#define TCP0        17       /* type tcp      */
#define TCP1        18       /* type tcp      */
#define TCP2        19       /* type tcp      */
#define TCP3        20       /* type tcp      */
#define TCP4        21       /* type tcp      */
#define TCP5        22       /* type tcp      */
#define TCP6        23       /* type tcp      */
#define TELNET0     24       /* type telnet   */
#define TELNET1     25       /* type telnet   */
#define TELNET2     26       /* type telnet   */

/* Control block sizes */

#define NLOOPBACK 1
#define NNULL 1
#define NUART 1
#define NFRAMEBUFFER 1
#define NTTY 3
#define NETHER 1
#define NETHLOOP 1
#define NRAW 2
#define NUDP 4
#define NTCP 7
#define NTELNET 3
#define NUSBKBD 1
#define NKBDMON 1

#define DEVMAXNAME 20
#define NDEVS 27


/* Configuration and Size Constants */

#define LITTLE_ENDIAN 0x1234
#define BIG_ENDIAN    0x4321

#define BYTE_ORDER    LITTLE_ENDIAN

#define NTHREAD   100           /* number of user threads           */
#define NSEM      100           /* number of semaphores             */
#define NMAILBOX  15            /* number of mailboxes              */
#define RTCLOCK   TRUE          /* timer support                    */
#define NETEMU    FALSE         /* Network Emulator support         */
#define NVRAM     FALSE         /* nvram support                    */
#define SB_BUS    FALSE         /* Silicon Backplane support        */
#define USE_TLB   FALSE         /* make use of TLB                  */
#define USE_TAR   FALSE         /* enable data archives             */
#define NPOOL     8             /* number of buffer pools available */
#define POOL_MAX_BUFSIZE 2048   /* max size of a buffer in a pool   */
#define POOL_MIN_BUFSIZE 8      /* min size of a buffer in a pool   */
#define POOL_MAX_NBUFS   8192   /* max number of buffers in a pool  */
#define WITH_USB                /* USB support                      */
#define WITH_DHCPC              /* DHCP client support              */

#endif /* _CONF_H_ */

Code: Select all

/* conf.c (GENERATED FILE; DO NOT EDIT) */

#include <conf.h>
#include <device.h>

#include <loopback.h>
#include <null.h>
#include <uart.h>
#include <framebuffer.h>
#include <tty.h>
#include <ether.h>
#include <ethloop.h>
#include <raw.h>
#include <udp.h>
#include <tcp.h>
#include <telnet.h>
#include <usbkbd.h>
#include <kbdmon.h>

extern devcall ioerr(void);
extern devcall ionull(void);

/* device independent I/O switch */

const device devtab[NDEVS] =
{
/**
 * Format of entries is:
 * dev-number, minor-number, dev-name,
 * init, open, close,
 * read, write, seek,
 * getc, putc, control,
 * dev-csr-address, intr-handler, irq
 */

/* SERIAL0 is uart */
    { 0, 0, "SERIAL0",
      (void *)uartInit, (void *)ionull, (void *)ionull,
      (void *)uartRead, (void *)uartWrite, (void *)ioerr,
      (void *)uartGetc, (void *)uartPutc, (void *)uartControl,
      (void *)0x3f201000, (void *)uartInterrupt, 57 },

/* USBKBD0 is usbkbd */
    { 1, 0, "USBKBD0",
      (void *)usbKbdInit, (void *)ionull, (void *)ionull,
      (void *)usbKbdRead, (void *)ioerr, (void *)ioerr,
      (void *)usbKbdGetc, (void *)ioerr, (void *)usbKbdControl,
      (void *)0x0, (void *)ioerr, 0 },

/* KBDMON0 is kbdmon */
    { 2, 0, "KBDMON0",
      (void *)ionull, (void *)ionull, (void *)ionull,
      (void *)usbKbdRead, (void *)fbWrite, (void *)ioerr,
      (void *)usbKbdGetc, (void *)fbPutc, (void *)ioerr,
      (void *)0x0, (void *)ioerr, 0 },

/* FRAMEBUF is framebuffer */
    { 3, 0, "FRAMEBUF",
      (void *)ionull, (void *)ionull, (void *)ionull,
      (void *)ioerr, (void *)fbWrite, (void *)ioerr,
      (void *)ioerr, (void *)fbPutc, (void *)ioerr,
      (void *)0x0, (void *)ioerr, 0 },

/* DEVNULL is null */
    { 4, 0, "DEVNULL",
      (void *)ionull, (void *)ionull, (void *)ionull,
      (void *)ionull, (void *)ionull, (void *)ioerr,
      (void *)ionull, (void *)ionull, (void *)ioerr,
      (void *)0x0, (void *)ioerr, 0 },

/* LOOP0 is loopback */
    { 5, 0, "LOOP0",
      (void *)loopbackInit, (void *)loopbackOpen, (void *)loopbackClose,
      (void *)loopbackRead, (void *)loopbackWrite, (void *)ioerr,
      (void *)loopbackGetc, (void *)loopbackPutc, (void *)loopbackControl,
      (void *)0x0, (void *)ioerr, 0 },

/* CONSOLE is tty */
    { 6, 0, "CONSOLE",
      (void *)ttyInit, (void *)ttyOpen, (void *)ttyClose,
      (void *)ttyRead, (void *)ttyWrite, (void *)ioerr,
      (void *)ttyGetc, (void *)ttyPutc, (void *)ttyControl,
      (void *)0x0, (void *)ioerr, 0 },

/* TTY1 is tty */
    { 7, 1, "TTY1",
      (void *)ttyInit, (void *)ttyOpen, (void *)ttyClose,
      (void *)ttyRead, (void *)ttyWrite, (void *)ioerr,
      (void *)ttyGetc, (void *)ttyPutc, (void *)ttyControl,
      (void *)0x0, (void *)ioerr, 0 },

/* TTYLOOP is tty */
    { 8, 2, "TTYLOOP",
      (void *)ttyInit, (void *)ttyOpen, (void *)ttyClose,
      (void *)ttyRead, (void *)ttyWrite, (void *)ioerr,
      (void *)ttyGetc, (void *)ttyPutc, (void *)ttyControl,
      (void *)0x0, (void *)ioerr, 0 },

/* ETH0 is ether */
    { 9, 0, "ETH0",
      (void *)etherInit, (void *)etherOpen, (void *)etherClose,
      (void *)etherRead, (void *)etherWrite, (void *)ioerr,
      (void *)ioerr, (void *)ioerr, (void *)etherControl,
      (void *)0x0, (void *)ioerr, 0 },

/* ELOOP is ethloop */
    { 10, 0, "ELOOP",
      (void *)ethloopInit, (void *)ethloopOpen, (void *)ethloopClose,
      (void *)ethloopRead, (void *)ethloopWrite, (void *)ioerr,
      (void *)ioerr, (void *)ioerr, (void *)ethloopControl,
      (void *)0x0, (void *)ioerr, 0 },

/* RAW0 is raw */
    { 11, 0, "RAW0",
      (void *)rawInit, (void *)rawOpen, (void *)rawClose,
      (void *)rawRead, (void *)rawWrite, (void *)ioerr,
      (void *)ioerr, (void *)ioerr, (void *)rawControl,
      (void *)0x0, (void *)ioerr, 0 },

/* RAW1 is raw */
    { 12, 1, "RAW1",
      (void *)rawInit, (void *)rawOpen, (void *)rawClose,
      (void *)rawRead, (void *)rawWrite, (void *)ioerr,
      (void *)ioerr, (void *)ioerr, (void *)rawControl,
      (void *)0x0, (void *)ioerr, 0 },

/* UDP0 is udp */
    { 13, 0, "UDP0",
      (void *)udpInit, (void *)udpOpen, (void *)udpClose,
      (void *)udpRead, (void *)udpWrite, (void *)ioerr,
      (void *)ioerr, (void *)ioerr, (void *)udpControl,
      (void *)0x0, (void *)ioerr, 0 },

/* UDP1 is udp */
    { 14, 1, "UDP1",
      (void *)udpInit, (void *)udpOpen, (void *)udpClose,
      (void *)udpRead, (void *)udpWrite, (void *)ioerr,
      (void *)ioerr, (void *)ioerr, (void *)udpControl,
      (void *)0x0, (void *)ioerr, 0 },

/* UDP2 is udp */
    { 15, 2, "UDP2",
      (void *)udpInit, (void *)udpOpen, (void *)udpClose,
      (void *)udpRead, (void *)udpWrite, (void *)ioerr,
      (void *)ioerr, (void *)ioerr, (void *)udpControl,
      (void *)0x0, (void *)ioerr, 0 },

/* UDP3 is udp */
    { 16, 3, "UDP3",
      (void *)udpInit, (void *)udpOpen, (void *)udpClose,
      (void *)udpRead, (void *)udpWrite, (void *)ioerr,
      (void *)ioerr, (void *)ioerr, (void *)udpControl,
      (void *)0x0, (void *)ioerr, 0 },

/* TCP0 is tcp */
    { 17, 0, "TCP0",
      (void *)tcpInit, (void *)tcpOpen, (void *)tcpClose,
      (void *)tcpRead, (void *)tcpWrite, (void *)ioerr,
      (void *)tcpGetc, (void *)tcpPutc, (void *)tcpControl,
      (void *)0x0, (void *)ioerr, 0 },

/* TCP1 is tcp */
    { 18, 1, "TCP1",
      (void *)tcpInit, (void *)tcpOpen, (void *)tcpClose,
      (void *)tcpRead, (void *)tcpWrite, (void *)ioerr,
      (void *)tcpGetc, (void *)tcpPutc, (void *)tcpControl,
      (void *)0x0, (void *)ioerr, 0 },

/* TCP2 is tcp */
    { 19, 2, "TCP2",
      (void *)tcpInit, (void *)tcpOpen, (void *)tcpClose,
      (void *)tcpRead, (void *)tcpWrite, (void *)ioerr,
      (void *)tcpGetc, (void *)tcpPutc, (void *)tcpControl,
      (void *)0x0, (void *)ioerr, 0 },

/* TCP3 is tcp */
    { 20, 3, "TCP3",
      (void *)tcpInit, (void *)tcpOpen, (void *)tcpClose,
      (void *)tcpRead, (void *)tcpWrite, (void *)ioerr,
      (void *)tcpGetc, (void *)tcpPutc, (void *)tcpControl,
      (void *)0x0, (void *)ioerr, 0 },

/* TCP4 is tcp */
    { 21, 4, "TCP4",
      (void *)tcpInit, (void *)tcpOpen, (void *)tcpClose,
      (void *)tcpRead, (void *)tcpWrite, (void *)ioerr,
      (void *)tcpGetc, (void *)tcpPutc, (void *)tcpControl,
      (void *)0x0, (void *)ioerr, 0 },

/* TCP5 is tcp */
    { 22, 5, "TCP5",
      (void *)tcpInit, (void *)tcpOpen, (void *)tcpClose,
      (void *)tcpRead, (void *)tcpWrite, (void *)ioerr,
      (void *)tcpGetc, (void *)tcpPutc, (void *)tcpControl,
      (void *)0x0, (void *)ioerr, 0 },

/* TCP6 is tcp */
    { 23, 6, "TCP6",
      (void *)tcpInit, (void *)tcpOpen, (void *)tcpClose,
      (void *)tcpRead, (void *)tcpWrite, (void *)ioerr,
      (void *)tcpGetc, (void *)tcpPutc, (void *)tcpControl,
      (void *)0x0, (void *)ioerr, 0 },

/* TELNET0 is telnet */
    { 24, 0, "TELNET0",
      (void *)telnetInit, (void *)telnetOpen, (void *)telnetClose,
      (void *)telnetRead, (void *)telnetWrite, (void *)ioerr,
      (void *)telnetGetc, (void *)telnetPutc, (void *)telnetControl,
      (void *)0x0, (void *)ioerr, 0 },

/* TELNET1 is telnet */
    { 25, 1, "TELNET1",
      (void *)telnetInit, (void *)telnetOpen, (void *)telnetClose,
      (void *)telnetRead, (void *)telnetWrite, (void *)ioerr,
      (void *)telnetGetc, (void *)telnetPutc, (void *)telnetControl,
      (void *)0x0, (void *)ioerr, 0 },

/* TELNET2 is telnet */
    { 26, 2, "TELNET2",
      (void *)telnetInit, (void *)telnetOpen, (void *)telnetClose,
      (void *)telnetRead, (void *)telnetWrite, (void *)ioerr,
      (void *)telnetGetc, (void *)telnetPutc, (void *)telnetControl,
      (void *)0x0, (void *)ioerr, 0 }
};

LdB
Posts: 903
Joined: Wed Dec 07, 2016 2:29 pm

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Thu Jun 21, 2018 3:33 am

Thanks for that .. I don't get why they don't just leave it with all the function pointers zeroed and in PlatformInit which is called basically after you have processor up fill them in from a configuration file. Much more sensible that having a scripted code change. I know that is what I will be doing and you just gave me all the device pointers :-)

For the Pi3 code there are a number of problems that need to be fixed, I have a running list and some will currently stop multicore use beyond just doing the core tasking changes. I have notes on the following.

1.) The system clock unit (clock.h which says it is documented???) and needs a platform specific recipe which is actually in timer.c in the Pi3 implementation and it reads the lower counter of the 1Mhz clock. The problem is there is a define in clock.h (#define CLKTICKS_PER_SEC 1000) which currently says it's 1000 ticks per second it's currently 1000000 on the Pi3 system. It's obviously in use for some timings I tried to correct it to 1M but it crashes the system. I am guessing there is an upper limit, which if I could find the documentation is probably described.
It probably as simple as read high/low and right shift them to get 32 bits in the right frequency range. Besides my objection to the wrong filename, it is symptomatic of what is going to drive me crazy trying to do multicore .... hardware access is not controlled which leads to point 2.

2.) Files like above just go for hardware with no consideration the access needs to be marshalled in some way for semaphore/spinlock and no concept of critical sections. There are many places in which hardware device access is timing critical (the USB has a couple of small ones) and can not be interrupted yet currently the switcher may well do a pre-empted context switch at that point. So that leads to point 3.

3.) I knew in the task system itself they would need critical sections concept so I went for the obvious killing a running thread (kill.c). You can see in that they turn off the interrupts (disable();) and then they turn them on again with (restore(im);) to stop the switcher interrupting so that is the only way to do a critical section I can see. On the Pi there is a big one that needs control which leads to point 4

4.) The VC mailbox system on the Pi has two parts to it you write to it then you wait for a response. The problem is most of us when we started our basic baremetal access had a read loop that if it didn't have the channel you wanted threw the message away. Side issue a couple of the mailbox implementations also have the status bug, the framebuffer device for example. Now getting back to the mailbox access problem consider this

Task 1 sends mailbox message write to VC ... Task 2 gets prempted and it writes to to VC and then reads Task1 response throws it away and then gets it's reponse and moves on .. Task 1 gets pre-empted back but it's response message has gone AWOL task 2 ate it.

It is a low probability but it must happen because in the framebuffer device you get funny bits of code labelled like this

Code: Select all

/* screenInit(): Calls framebufferInit() several times to ensure we successfully initialize, just in case. */
It struck me as odd when I first saw that as your communication with the VC is guaranteed, but you can see why they have to do it because look at the mailbox read code it has it just throws wrong messages away and it can be pre-empted between the read and the write. I can imagine it was not fun having the screen fail to initialize when you asked it.

So to take the Pi code any further all the PI mailbox access needs to be regulated, there are 3 choices I can see
1.) Bring all access to the mailbox to one unit and lock/unlock access
2.) Any access to the mailbox must turn off interrupts at start of write to VC and turn them on again when then get response back from VC
3.) Virtualize the mailbox access so you are actually not accessing the real mailbox and organize the behind the scene virtualization to do the marshalling.

There are probably other choices and each comes with pros and cons.

5.) The illustration of the lack of co-ordination of hardware access is evident in that there are 3 defines running around that basically all define the base address 0x3F000000. There are at least 3 places that have an implementation of there own Pi mailbox code and Pi system timer access. There is also a lot of code which roll on a define _XINU_PLATFORM_ARM_RPI_3_ anything done like that needs to be re-thought how to do it back to a platform specific way. The obvious way is put a function pointer in the device file and exported in the header which is initialized to null. In PlatformInit initialize the device pointer to the code you require to run so in your case it will be non zero. Now in the device code where you need to do something specific for your platform test the function pointer if it is none zero call it. So for all other platforms nothing changes but you get the callback when you need it. If you look at conf.h and conf.c that is what devtab is a struct called dentry that is an array of function pointers mostly.

With the device I don't get things like why the frameBufferInit/screenInit is not connected to the init function in it's driver block so the system could autokick it like it does the keyboard etc. Someone starded to do it there is an fbtab in the framebuffer header file but it doesn't connect anywhere. I was considering the control function ptr to run mailbox controls down for all the devices but it is already used by the USB and you still need to run the Pi USB to the mailbox to turn power on/off so in the end I added a new function called "callSpecial" to the device block and zeroed it on all the other devices. I am using that for all the devices that use the Pi mailbox and they all queue up on a semaphore to get access to the mailbox.

I have a couple of real basic objections with the Xinu base code the most annoying is they have butchered "stdint.h", it's a published standard just of definitions and macros how do you get it wrong. Try using a uintptr_t or any of the standard macros and see what happens.

I think if it starts at that the Pi3 version will at least start to take on some stability and start working like the Xinu does on other platforms.

Unfortunately I am away for a conference and holiday from next week for 4 weeks so won't get back to this until then.

rlatinov
Posts: 22
Joined: Mon Jun 26, 2017 7:35 pm

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Fri Jun 22, 2018 5:24 pm

LdB,

I figured out what was causing the slow attachment times for the USB.

In system/platforms/arm-rpi3/platforminit.c (in method platforminit()) you need to change the line

Code: Select all

platform.clkfrq = 1200000000;
to

Code: Select all

platform.clkfrq = 1000000;
That solved it for me.

LdB
Posts: 903
Joined: Wed Dec 07, 2016 2:29 pm

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Fri Jun 22, 2018 5:45 pm

Nice I will add it.

Is there any better documentation on Xinu specifically now I have the screen 100% working I want to bind the console output to it?

I probably won't get much more time to play as I am away from next week as I said.

I have the initialization bound it dumps out to the debug TTY like all the devices but I can't seem to direct the console to it.
FRAMEBUFFER(): I am here
Defaults Width: 1280, Height: 1024, Depth: 16
Pitch: 2560, FrameBuffer: 3e97a000 Screen font: 3dbc0
FRAMEBUFFER() returning OK
IN ETHERINIT(): I am here
IN ETHERINIT(): returning OK
IN SMSC_BIND_DEVICE(): I am here.
IN SMSC_BIND_DEVICE(): printing out udev struct

rlatinov
Posts: 22
Joined: Mon Jun 26, 2017 7:35 pm

Re: Raspberry Pi 3B+ Bare Metal USB Driver

Fri Jun 22, 2018 9:29 pm

I haven't tested the screen at all..
I can tell you what the Xinu team did for the Pi 1 to connect a keyboard to use with the screen.

They made a device for a usb keyboard driver (in device/usbkbd), and then configured keyboard monitor device in xinu.conf (called kbdmon) which has the read method as the keyboard read, and the output method as the framebuffer print. They labeled it as a hack, but it apparently worked for them.

xinu.conf description for kdbmon

Code: Select all

kbdmon:                      
    on OTHERDEVS -i ionull       -o ionull       -c ionull 
                 -r usbKbdRead   -g usbKbdGetc   -w fbWrite 
                 -p fbPutc       -n ioerr
Also, the binding of the keyboard, screen, and the console should occur in system/main.c

Code: Select all

    /* Set up the second TTY (TTY1) if possible  */                                 
#if defined(TTY1)                                                                                       
#if defined(KBDMON0)                                                  
    /* Associate TTY1 with keyboard and use framebuffer output  */           
    if (OK == open(TTY1, KBDMON0))                                             
    {                                                                               
#if HAVE_SHELL                                                               
        shelldevs[nshells][0] = TTY1;           
        shelldevs[nshells][1] = TTY1;                                    
        shelldevs[nshells][2] = TTY1;                                                     
        nshells++;                                                         
#endif              
as you can see, it uses the KDBMON0 "device" and binds it to TTY1.

Return to “Bare metal, Assembly language”