zeoneo
Posts: 67
Joined: Sun Sep 30, 2018 6:54 am

Bare metal BCM43438 Driver

Sat May 11, 2019 4:09 am

Hi,

I aim to port bare metal wifi driver for bcm43438. I did search in raspberrypi/linux repository but couldn't find any mention of bcm43438. Can any one point me to the correct source? I checked net/wireless/broadcom/ directory.
Let there be some light .../\...

jamesh
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 23874
Joined: Sat Jul 30, 2011 7:41 pm

Re: Bare metal BCM43438 Driver

Sat May 11, 2019 8:10 am

Brcmfmac is the driver used for all the Cypress chips. The particular chip type is handled by the firmware that is loaded onto them at boot.
Principal Software Engineer at Raspberry Pi (Trading) Ltd.
Contrary to popular belief, humorous signatures are allowed. Here's an example...
“I think it’s wrong that only one company makes the game Monopoly.” – Steven Wright

User avatar
Gavinmc42
Posts: 3885
Joined: Wed Aug 28, 2013 3:31 am

Re: Bare metal BCM43438 Driver

Sat May 11, 2019 9:45 am

The Ultibo guys have managed to get Bluetooth working by loading the Cypress binary blobs.
Two versions, one for the older chip, one for the new P3A/B+ RF combo chip.
WiFi is harder to do, something about crypto?

The fun part was getting a Microbit talking to the PI vi BT.
https://ultibo.org/forum/viewtopic.php? ... ooth#p8638

The priority is high to get WiFi working and Garry and co may be able to do it but it is not simple
https://ultibo.org/wiki/Current_Status

I am unaware if anyone has got WiFi working in baremetal, apart from some USB dongles or UART versions.
I'm dancing on Rainbows.
Raspberries are not Apples or Oranges

jamesh
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 23874
Joined: Sat Jul 30, 2011 7:41 pm

Re: Bare metal BCM43438 Driver

Sat May 11, 2019 10:34 am

Gavinmc42 wrote:
Sat May 11, 2019 9:45 am
The Ultibo guys have managed to get Bluetooth working by loading the Cypress binary blobs.
Two versions, one for the older chip, one for the new P3A/B+ RF combo chip.
WiFi is harder to do, something about crypto?
I suspect that porting brcmfmac was just too much, it's a lot of spagetti code. Not aware of any crypto in there that might be problematic.
Principal Software Engineer at Raspberry Pi (Trading) Ltd.
Contrary to popular belief, humorous signatures are allowed. Here's an example...
“I think it’s wrong that only one company makes the game Monopoly.” – Steven Wright

hippy
Posts: 6074
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: Bare metal BCM43438 Driver

Sat May 11, 2019 11:19 am

Gavinmc42 wrote:
Sat May 11, 2019 9:45 am
WiFi is harder to do, something about crypto?
jamesh wrote:
Sat May 11, 2019 10:34 am
Not aware of any crypto in there that might be problematic.
I understand it to be the handling of WEP/WPA/WPA2 in establishing a connection which is the challenge as it's a lot of work with few resources to do that. So an issue within the protocol stack rather than with the firmware or chip.

Ultibo took the decision that WiFi will be 'all or nothing' and do not intend to provide an implementation which would work but only with unsecured access points.

Ultibo is wired ethernet only for now. If one wants WiFi that has to be through a mini-router or similar, or via an ESP add-on. Unfortunately that means the Zero W and the 3A+ can't be used how it would be desirable to use them; standalone using WiFi.

zeoneo
Posts: 67
Joined: Sun Sep 30, 2018 6:54 am

Re: Bare metal BCM43438 Driver

Sat May 11, 2019 2:36 pm

Thanks all for the replies. I will at least read the code and understand how it works.
Let there be some light .../\...

zeoneo
Posts: 67
Joined: Sun Sep 30, 2018 6:54 am

Re: Bare metal BCM43438 Driver

Wed Jul 31, 2019 11:38 am

Guys is it feasible to copy all the object files related to wifi driver from linux build and create static library and use it in bare metal projects?

We can provide implementations of functions which are called from linux WiFi driver.
Let there be some light .../\...

Thalhammer
Posts: 15
Joined: Fri Aug 03, 2012 6:34 pm

Re: Bare metal BCM43438 Driver

Wed Jul 31, 2019 12:09 pm

Its probably a lot easier to just reimplement the driver to fit your OS.
However there is very little documentation about the module and despite my driver for the arasan controller working fine and the commands being transmitted on the wire, for some reason the chip does not respond to any SDIO command I send it.

Does it need some other clock or so?

PS: I am working on the BCM43430A1 on the Pi Zero W but I assume Rpi3+ will be similar.

zeoneo
Posts: 67
Joined: Sun Sep 30, 2018 6:54 am

Re: Bare metal BCM43438 Driver

Wed Jul 31, 2019 1:00 pm

Thalhammer wrote:
Wed Jul 31, 2019 12:09 pm
despite my driver for the arasan controller working fine
Is it the same driver as implemented by LdB here https://github.com/LdB-ECM/Raspberry-Pi ... r/SD_FAT32.


Do you have any reference documentation to start with Wifi driver?

EDIT:
I am very much interested in reimplantation but I fear I do not have understanding of wifi stack. I think it needs WPA implementations as well.
Let there be some light .../\...

Thalhammer
Posts: 15
Joined: Fri Aug 03, 2012 6:34 pm

Re: Bare metal BCM43438 Driver

Wed Jul 31, 2019 4:32 pm

No its a custom implementation to fit my OS (I write a C++ RTOS, so no userspace etc and class oriented) but his code was one of the references I used.

The only things I currently have is the datasheet of the chip (very little usefull information), the official brcmfmac source of the linux driver and a dump of the traffic between module and kernel on boot.
However I didn't find a clk line, so the official saleae sdio analyser does not work and my attempts at a custom analyser which uses the edges on the commandline to detect clockspeed were not really successful, so that dump is not really that useful.

I never implemented WPA and so on but I did some work with injecting wifi frames from linux in the past so I know the basics.
Also I think there is a chance that you won't even have to deal with it (I.e. it is handled by the broadcom chip, I read that there is more or less a complete wifi stack in the firmware but I dont know if it is used by linux).

I tried to copy the init sequence used by linux but for some reason the card does not respond to any sdio command I send (they all timeout).

The basics is the following:
WL_ON needs to be high (gpio41 on pizerow).
Arasan is configured on pin 34-39 and uses 4 bit mode with 400kHz Operation during init and 25MHz during actual transmission.

I did not get anything working (yet) and moved on to some other projects with more information (Videocore and Bluetooth stack) to get my head free.
if you manage to get anything working feel free to share code or if you need help I am happy to help.

zeoneo
Posts: 67
Joined: Sun Sep 30, 2018 6:54 am

Re: Bare metal BCM43438 Driver

Thu Aug 01, 2019 11:18 am

Thalhammer wrote:
Wed Jul 31, 2019 4:32 pm
No its a custom implementation to fit my OS (I write a C++ RTOS, so no userspace etc and class oriented) but his code was one of the references I used.

The only things I currently have is the datasheet of the chip (very little usefull information), the official brcmfmac source of the linux driver and a dump of the traffic between module and kernel on boot.
However I didn't find a clk line, so the official saleae sdio analyser does not work and my attempts at a custom analyser which uses the edges on the commandline to detect clockspeed were not really successful, so that dump is not really that useful.

I never implemented WPA and so on but I did some work with injecting wifi frames from linux in the past so I know the basics.
Also I think there is a chance that you won't even have to deal with it (I.e. it is handled by the broadcom chip, I read that there is more or less a complete wifi stack in the firmware but I dont know if it is used by linux).

I tried to copy the init sequence used by linux but for some reason the card does not respond to any sdio command I send (they all timeout).

The basics is the following:
WL_ON needs to be high (gpio41 on pizerow).
Arasan is configured on pin 34-39 and uses 4 bit mode with 400kHz Operation during init and 25MHz during actual transmission.

I did not get anything working (yet) and moved on to some other projects with more information (Videocore and Bluetooth stack) to get my head free.
if you manage to get anything working feel free to share code or if you need help I am happy to help.

Can you post the link of linux code and chip datasheet?

Where did you find information regarding broadcomm chip firmware for WiFi?

It will be super easy if we can leverage that
Let there be some light .../\...

Thalhammer
Posts: 15
Joined: Fri Aug 03, 2012 6:34 pm

Re: Bare metal BCM43438 Driver

Thu Aug 01, 2019 8:15 pm

Broadcoms WIFI division was bought by Cypress and the provide some of the documentation. You can find the datasheet here:
https://www.cypress.com/file/298706/download

Linux driver is called brcmfmac and its source is here:
https://github.com/torvalds/linux/tree/ ... 1/brcmfmac

zeoneo
Posts: 67
Joined: Sun Sep 30, 2018 6:54 am

Re: Bare metal BCM43438 Driver

Sat Aug 03, 2019 4:13 am

Thalhammer wrote:
Thu Aug 01, 2019 8:15 pm
Broadcoms WIFI division was bought by Cypress and the provide some of the documentation. You can find the datasheet here:
https://www.cypress.com/file/298706/download

Linux driver is called brcmfmac and its source is here:
https://github.com/torvalds/linux/tree/ ... 1/brcmfmac

I see this post https://www.raspberrypi.org/forums/view ... 4#p1306878 which says RPI3B uses CYW43438 chip not CYW4334X.

Edit:

Github issues which mention RPI3 WiFi chip:
https://github.com/raspberrypi/firmware/issues/784 ==> CYW43438 indentifies itself as CYW43430 hence no mention of BCM43438 in any of the driver source code.
https://github.com/raspberrypi/linux/issues/2485
Binary closed source firmware is loaded in chip to provide low level functionality.

Does anyone know how is this binary firmware loaded to Wifi chip? I don;t see any SDIO start up sequence in brcmfmac driver source code.
Let there be some light .../\...

rst
Posts: 410
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: Bare metal BCM43438 Driver

Sat Aug 03, 2019 9:20 am

zeoneo wrote:
Sat Aug 03, 2019 4:13 am
Does anyone know how is this binary firmware loaded to Wifi chip? I don;t see any SDIO start up sequence in brcmfmac driver source code.
The SDIO code is separated in Linux from the Wi-Fi driver code in the MMC subsystem.

zeoneo
Posts: 67
Joined: Sun Sep 30, 2018 6:54 am

Re: Bare metal BCM43438 Driver

Sun Aug 04, 2019 4:11 am

@Thalhammer

Do you know how to load firmware in the chip? Is there any documentation on how to use wifi over SDIO? Datasheet talks about boot up sequence for gSPI interface in detail but none for SDIO.

https://github.com/torvalds/linux/blob/ ... dio.c#L592 Is the the command sequence are you trying to start wifi 3v3 mode?

If you could post the code you were trying it will be helpful.

Thanks
Let there be some light .../\...

Thalhammer
Posts: 15
Joined: Fri Aug 03, 2012 6:34 pm

Re: Bare metal BCM43438 Driver

Tue Aug 13, 2019 10:03 am

Sorry for the late reply.
I only tracked it in digital mode, but as far as I know the 1.8v mode on the rpi is broken so I assume its 3.3v.
BCM43430 = CYW43430 because Cypress bought Broadcom's wifi division and changed the names.
I mostly have a proof of concept/testbed I use to toy around with it, but no real code.
I only try to replicate the commands sent by the linux driver.

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

Re: Bare metal BCM43438 Driver

Tue Aug 13, 2019 1:39 pm

I had forgotten about this thread but by weird events I ran across this yesterday which may be of some help
https://blog.quarkslab.com/reverse-engi ... psets.html

Thalhammer
Posts: 15
Joined: Fri Aug 03, 2012 6:34 pm

Re: Bare metal BCM43438 Driver

Fri Aug 16, 2019 10:03 pm

While its a pretty interesting read, I don't think its of much use for us, as there is no information in the sdio communication with the host.
Maybe we could instrument the linux driver with more logging and check it using this way ?
Or is there some kernel option to dump all sdio traffic ?

eggmansan
Posts: 3
Joined: Tue May 22, 2018 3:27 am

Re: Bare metal BCM43438 Driver

Fri Aug 23, 2019 2:32 pm

Thalhammer wrote:
Fri Aug 16, 2019 10:03 pm
Maybe we could instrument the linux driver with more logging and check it using this way ?
Or is there some kernel option to dump all sdio traffic ?
I dumped 2 types of bcm43438 sdio traffic .

1. add some debug print to drivers/mmc/core/sdio_ops.c and core.c.
https://github.com/eggman/raspberrypi/b ... io_log.txt

2. brcmfmac driver have trace option. enable BRCM_TRACING in kernel config file.
https://github.com/eggman/raspberrypi/b ... ce_log.txt

And I write some baremetal sdio code. but not test on real hardware. I only tested my modified qemu.
https://github.com/eggman/raspberrypi/t ... pi3/sdio03

zeoneo
Posts: 67
Joined: Sun Sep 30, 2018 6:54 am

Re: Bare metal BCM43438 Driver

Sat Aug 24, 2019 6:42 am

eggmansan wrote: Sat Aug 17, 2019 3:33 am
Maybe we could instrument the linux driver with more logging and check it using this way ?
Or is there some kernel option to dump all sdio traffic ?
I dumped 2 types of bcm43438 sdio traffic .

1. add some debug print to drivers/mmc/core/sdio_ops.c and core.c.
https://github.com/eggman/raspberrypi/b ... io_log.txt

2. brcmfmac driver have trace option. enable BRCM_TRACING in kernel config file.
https://github.com/eggman/raspberrypi/b ... ce_log.txt

And I write some baremetal sdio code. but not test on real hardware. I only tested my modified qemu.
https://github.com/eggman/raspberrypi/t ... pi3/sdio03
Hey can you share your steps. I built brcmfmac kernel module, but if failed while loading .ko file using insmod with error "invalid symbol found".

Code: Select all

uname -r 

4.19.66-v7l+
I cloned linux source using

Code: Select all

git clone --depth=1 --branch rpi-4.19.y https://github.com/raspberrypi/linux

I tried compiling using

Code: Select all

make -j4 modules 
Let there be some light .../\...

9pi
Posts: 46
Joined: Sat Aug 11, 2012 6:14 pm

Re: Bare metal BCM43438 Driver

Tue Aug 27, 2019 1:12 pm

Not bare metal strictly speaking, but the Plan 9 driver is another alternative example you might want to look at for information. It's under 2400 lines of C, so it should be a bit easier to follow than the Linux brcmfmac driver. To write the Plan 9 driver without a device spec, I had to read all the brcmfmac code which is a 32,000+ line spaghetti of support for multiple chips and interface methods: not an experience I would recommend for pleasure.

Plan 9 driver source is at https://9p.io/sources/contrib/miller/9/bcm/ether4330.c, depends on the emmc driver (another 529 lines) in https://9p.io/sources/contrib/miller/9/bcm/emmc.c for sdio support.

zeoneo
Posts: 67
Joined: Sun Sep 30, 2018 6:54 am

Re: Bare metal BCM43438 Driver

Thu Aug 29, 2019 10:41 am

9pi wrote:
Tue Aug 27, 2019 1:12 pm
Not bare metal strictly speaking, but the Plan 9 driver is another alternative example you might want to look at for information. It's under 2400 lines of C, so it should be a bit easier to follow than the Linux brcmfmac driver. To write the Plan 9 driver without a device spec, I had to read all the brcmfmac code which is a 32,000+ line spaghetti of support for multiple chips and interface methods: not an experience I would recommend for pleasure.

Plan 9 driver source is at https://9p.io/sources/contrib/miller/9/bcm/ether4330.c, depends on the emmc driver (another 529 lines) in https://9p.io/sources/contrib/miller/9/bcm/emmc.c for sdio support.
Thank you sir. I think it will help me writing small driver for this sdio wifi chip.
eggmansan wrote:
Thalhammer wrote:
Fri Aug 16, 2019 10:03 pm
Maybe we could instrument the linux driver with more logging and check it using this way ?
Or is there some kernel option to dump all sdio traffic ?
I dumped 2 types of bcm43438 sdio traffic .

1. add some debug print to drivers/mmc/core/sdio_ops.c and core.c.
https://github.com/eggman/raspberrypi/b ... io_log.txt

2. brcmfmac driver have trace option. enable BRCM_TRACING in kernel config file.
https://github.com/eggman/raspberrypi/b ... ce_log.txt

And I write some baremetal sdio code. but not test on real hardware. I only tested my modified qemu.
https://github.com/eggman/raspberrypi/t ... pi3/sdio03
Thanks for this l, now I can trace the source code.
Let there be some light .../\...

zeoneo
Posts: 67
Joined: Sun Sep 30, 2018 6:54 am

Re: Bare metal BCM43438 Driver

Sun Sep 01, 2019 1:11 pm

9pi wrote:
Tue Aug 27, 2019 1:12 pm
Not bare metal strictly speaking, but the Plan 9 driver is another alternative example you might want to look at for information. It's under 2400 lines of C, so it should be a bit easier to follow than the Linux brcmfmac driver. To write the Plan 9 driver without a device spec, I had to read all the brcmfmac code which is a 32,000+ line spaghetti of support for multiple chips and interface methods: not an experience I would recommend for pleasure.

Plan 9 driver source is at https://9p.io/sources/contrib/miller/9/bcm/ether4330.c, depends on the emmc driver (another 529 lines) in https://9p.io/sources/contrib/miller/9/bcm/emmc.c for sdio support.
I tried this code in steps It didn't work for me in first step itself.

I have LdB's code which reads SD card using EMMC (sdhci controller), so I tried first decoupling SD card from EMMC using following code

Code: Select all

    uint32_t i;
	for(i = 48; i <= 53; i++)
		select_alt_func(i, Alt0);
	for(i = 34; i <= 39; i++){
		select_alt_func(i, Alt3);
		if(i == 34)
			disable_pulling(i); // Pull off
		else
			pullup_pin(i);
	}

// ----- Pull up Pull Down code

#define PERIPHERAL_BASE     0x3F000000UL

#define  GPIO_BASE ((volatile __attribute__((aligned(4))) uint32_t*)(uintptr_t)(PERIPHERAL_BASE + 0x200000))

#define SET_GPIO_ALT(g,a) *(GPIO_BASE + (((g)/10))) |= (((a)<=3?(a) + 4:(a)==4?3:2)<<(((g)%10)*3))

typedef enum {
    Alt0	= 0x4,
    Alt1	= 0x5,
    Alt2	= 0x6,
    Alt3	= 0x7,
    Alt4	= 0x3,
    Alt5	= 0x2,
} alt_func;

/* GPIO regs */
enum {
    Set0	= 0x1c>>2,
    Clr0	= 0x28>>2,
    Lev0	= 0x34>>2,
    PUD	= 0x94>>2,
    Off	= 0x0,
    Pulldown= 0x1,
    Pullup	= 0x2,
    PUDclk0	= 0x98>>2,
    PUDclk1	= 0x9c>>2,
};

void select_alt_func(uint32_t bcm_pin, alt_func alt_fun) {
    SET_GPIO_ALT(bcm_pin, alt_fun);
}


void pullup_pin(uint32_t bcm_pin) {
    volatile uint32_t *gp, *reg;
    uint32_t mask;

    gp = GPIO_BASE;
    reg = &gp[PUDclk0 + bcm_pin/32];
    mask = 1 << (bcm_pin % 32);
    gp[PUD] = Pullup;
    delay(150);
    *reg = mask;
    delay(150);
    *reg = 0;
}

void pulldown_pin(uint32_t bcm_pin) 
{
    volatile uint32_t *gp, *reg;
    uint32_t mask;

    gp = GPIO_BASE;
    reg = &gp[PUDclk0 + bcm_pin/32];
    mask = 1 << (bcm_pin % 32);
    gp[PUD] = Pulldown;
    delay(150);
    *reg = mask;
    delay(150);
    *reg = 0;
}

void disable_pulling(uint32_t bcm_pin) 
{
    volatile uint32_t *gp, *reg;
    uint32_t mask;

    gp = GPIO_BASE;
    reg = &gp[PUDclk0 + bcm_pin/32];
    mask = 1 << (bcm_pin % 32);
    gp[PUD] = Off;
    delay(150);
    *reg = mask;
    delay(150);
    *reg = 0;
}

After this I tried to print ROOT directory content of FAT32 formatted SD card, it worked. I concluded that this code doesn't work or am I missing something?


I tried to send

Code: Select all

(CMD5)IO_SEND_OP_COND, CMD52(RESET) by writing CIA(function = 00h) register (02h) wifi(bit 7) = 1 
I got 0 in response.

@9pi Am I missing something?


------------_Edit I found the Issue -----


in select_alt_func I am passing actual Alt func values as per datasheet, this MACRO takes 0 for Alt0.

I am able to select the card and read write using CMD52.

I am wondering where are the definition for these function calls like below

Code: Select all

	cfgw(Sbaddr+1, addr>>16);
	cfgw(Sbaddr+2, addr>>24);
I tried searching there is no way I could clone your sources repository. Please let me know if you can help me with that.

PS: I tried using plan9 on virtual box to clone the sources, I couldn't use it properly.

Thanks,
zeo
Let there be some light .../\...

9pi
Posts: 46
Joined: Sat Aug 11, 2012 6:14 pm

Re: Bare metal BCM43438 Driver

Sat Sep 07, 2019 1:54 pm

zeoneo wrote:
Sun Sep 01, 2019 1:11 pm

I am wondering where are the definition for these function calls like below

Code: Select all

	cfgw(Sbaddr+1, addr>>16);
	cfgw(Sbaddr+2, addr>>24);
I tried searching there is no way I could clone your sources repository. Please let me know if you can help me with that.
Those are static functions defined earlier in the same file, ether4330.c

Plan 9 convention is always to align the name of functions being defined in column 1, so should be easy to find in any editor. cfgw ultimately calls sdio.cmd which is defined in emmc.c sdio table as emmccmd().

cmarrin
Posts: 23
Joined: Sat Sep 15, 2018 7:19 pm

Re: Bare metal BCM43438 Driver

Thu Sep 19, 2019 11:17 pm

I'm really happy to see people taking an interest in this again. I looked into doing this 6 months ago or more and got stuck with the inscrutable code for the WiFi chip. So I said screw it and I started on a different approach. I'm building a little hat with an ESP8266 on it, talking to the RPi over SPI. Still in process, but it's promising. I've leveraged some code to let 2 ESP's talk over SPI and have gotten the RPi speaking the same dialect of SPI as the ESP after some hours with the logic analyzer.

It's still very much a work in progress, but you can see how far I've gotten here:

https://github.com/cmarrin/placid

In particular look at:

https://github.com/cmarrin/placid/tree/ ... ESPRPiWifi

For the ESP code and:

https://github.com/cmarrin/placid/blob/ ... iFiSPI.cpp

for the RPi side of the SPI interface

One issue is that the very best you can hope for out of an SPI channel is a few Mbps. So it will never be gigabit ethernet! But it would be a hard system to beat at $5 for a RPi Zero without WiFi, and $2 for an ESP.

Return to “Bare metal, Assembly language”