jayben
Posts: 38
Joined: Mon Aug 19, 2019 9:56 pm

Re: Bare metal BCM43438 Driver

Tue Mar 10, 2020 4:15 pm

Yes, creating a bare-metal driver for the BCM / CYW43438 is really hard work.
I've got the CPU running and IOCTL calls working, am currently grappling with asynchronous events.
See https://iosoft.blog/zerowi/

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

Re: Bare metal BCM43438 Driver

Tue Mar 10, 2020 6:09 pm

@9pi has written driver for wifi. Check his reply on this thread. I was not even able to read sd card using sd host driver so that i could relieve the emmc for wifi. I will need his help. If someone is ready to help and guide I am willing to take all the efforts. I am just stuck on sd host.

@9pi or @Ldb?
Let there be some light .../\...

jayben
Posts: 38
Joined: Mon Aug 19, 2019 9:56 pm

Re: Bare metal BCM43438 Driver

Tue Mar 10, 2020 7:42 pm

Yes, I'm familiar with the Plan9 driver, and did expend some effort trying to get it working. The single file looks relatively simple, but there are a *lot* of dependencies, and just getting it to compile under GCC took quite a time.

It'd be really interesting to see ether4330.c adapted as a standalone driver; it was just too complex for me, as I'm not keen on (re-) publishing code that I didn't write and don't understand.

[..and incidentally, to answer your earlier question about the cfgw function, it generates an SDIO command 52, and is being used to set the backplane window, as described in part4 of my blog https://iosoft.blog/zerowi-part4/]

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

Re: Bare metal BCM43438 Driver

Wed Mar 11, 2020 2:38 am

I am stuck at sdhost driver. I am referring to uboot's code. Do you have working sdhost?
Let there be some light .../\...

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

Re: Bare metal BCM43438 Driver

Wed Mar 11, 2020 7:05 am

I am happy to have a look, just throw up a link to code. If you have it setup as a driver I just need the driver code don't worry about the rest of whatever you are running it on.

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

Re: Bare metal BCM43438 Driver

Wed Mar 11, 2020 7:13 am

I have setup separate repo.

https://github.com/zeoneo/rpi-3b-wifi/b ... c/sdhost.c

If you have docker desktop then you can easily build it. No setup required.

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

jayben
Posts: 38
Joined: Mon Aug 19, 2019 9:56 pm

Re: Bare metal BCM43438 Driver

Wed Mar 11, 2020 9:19 am

Yes, but I decided not to use the Broadcom (Arasan) SD controller, and to bit-bash the SDIO interface instead. The idea was to start with the simplest option, and add complication later, but this turned out much better than I expected; the bit-bashed 4-bit data interface is surprisingly fast, booting the chip from scratch (including loading 300K of firmware) in under a second.

Looking at your development plan, I have the chip running, so I'm effectively at the 'send packets' step, but currently I'm working on scanning the wireless network, which involves handling asynchronous events. These are quite complicated - with the Broadcom / Cypress wireless chips, nothing is ever simple. When this works, I'll release the code so far.

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

Re: Bare metal BCM43438 Driver

Wed Mar 11, 2020 7:04 pm

zeoneo I had a number of issues with your code .. the uart wasn't working (I just switched to my code) and the timer code failed dismally because you left a volatile off the timer_register which stopped msleep working

It is supposed to look like this

Code: Select all

static volatile timer_registers_t* timer_regs; 
I notice you did all sorts of volatile hacks on code above so you clearly worked out it was being optimized away so why didn't you just realize you needed the volatile on the pointer?

There are a pile of other issues which I will get back to later, for now I threw out your printf and just hooked up the stock standard
#include <stdio.h> via semihosting to the uart.

So is this what you are seeing and I am supposed to fix from?
The timer reg value may differ I did the value at the pointer but now I think about your issue above you may have been after the pointer value.

Code: Select all

-----------------Kernel Started Dude........................
timer_regs:277dca
 Kernel End: 0x18a000 
f_max 2500000, f_min 1221
=========== REGISTER DUMP ===========
SDCMD  0x00000000
SDARG  0x00000900
SDTOUT 0x00000000
SDCDIV 0x00000000
SDRSP0 0x00000000
SDRSP1 0x00000000
SDRSP2 0x00000000
SDRSP3 0x00000000
SDHSTS 0x00000000
SDVDD  0x00000000
SDEDM  0x00000000
SDHCFG 0x00000000
SDHBCT 0x00000000
SDHBLC 0x00000000
============================
bcm2835_probe -> OK
received command : 0 
 Previous command  0 
Command Index 0 
=========== REGISTER DUMP ===========
SDCMD  0x00000000
SDARG  0x00000900
SDTOUT 0x00000000
SDCDIV 0x00000003
SDRSP0 0x00000000
SDRSP1 0x00000000
SDRSP2 0x00000000
SDRSP3 0x00000000
SDHSTS 0x00000000
SDVDD  0x00000000
SDEDM  0x00000000
SDHCFG 0x00000000
SDHBCT 0x00000000
SDHBLC 0x00000000
============================
preparing data 
 Starting command execution arg: 0 
bcm2835_read_wait_sdcmd: timeout (100000 us)
command never completed.
=========== REGISTER DUMP ===========
SDCMD  0x00008400
SDARG  0x00000900
SDTOUT 0x00000000
SDCDIV 0x00000003
SDRSP0 0x00000000
SDRSP1 0x00000000
SDRSP2 0x00000000
SDRSP3 0x00000000
SDHSTS 0x00000000
SDVDD  0x00000000
SDEDM  0x00000000
SDHCFG 0x00000000
SDHBCT 0x00000000
SDHBLC 0x00000000
============================
Response :ffffffff 
If you do want to hook up the normal printf here is the semi-host code ... stick it down the bottom of kernel.c
I notice you have a kernel malloc but i wasn't sure if it worked so I just hooked a static block to the _s_brk to semi-host for now

Code: Select all

/* There's currently no implementation of a file system because there's no
file system! */
int __attribute__((weak)) _close(int file)
{
	return -1;
}

/* Set position in a file. Minimal implementation: */
int __attribute__((weak)) _lseek(int file, int ptr, int dir)
{
	return 0;
}

/* Read from a file. Minimal implementation: */
int __attribute__((weak)) _read(int file, char* ptr, int len)
{
	return 0;
}

/* Query whether output stream is a terminal. For consistency with the other
minimal implementations, which only support output to stdout, this minimal
implementation is suggested: */
int __attribute__((weak)) _isatty(int file)
{
	return 1;
}

int __attribute__((weak)) _fstat(int file, int* p)
{
	return 0;
}

static uint8_t MemoryBlock[16384];
static uint8_t* Heap_End = 0;

int __attribute__((weak)) _sbrk(int incr)
{
	if (Heap_End == 0)
		Heap_End = &MemoryBlock[0];

	uint8_t* prev_heap_end = Heap_End;
	Heap_End += incr;

	return (int)prev_heap_end;
}

int __attribute__((weak)) _write(int file, char* ptr, int len) {

	char Ch;
	for (int todo = 0; todo < len; todo++) {
		Ch = *ptr++;
		uart_putc(Ch);
	}
	return len;
} 

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

Re: Bare metal BCM43438 Driver

Wed Mar 11, 2020 7:41 pm

First of whatever output you got I am getting the same without changing anything. I don't why the uart doesn't work for you and timer as well. This code works correctly for me, even printf.

I used the same uart code to upload my kernel every time it changed. I think may be the difference is in config.txt, I have hard coded enable_uart=1 and some core freq too.

Bottom line we are getting same output so I need to make this work.
Let there be some light .../\...

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

Re: Bare metal BCM43438 Driver

Thu Mar 12, 2020 1:27 am

Ok it's the uart clock frequency that is different for me, the baud rate is skewed. Reading your comments it thinks the uart clock is 3Mhz on my Pi3 it's not your config doesn't set that up for me (Obviously a different production version). The reason my UART code works is I actually just set the UART clock using tag message 0x00038002 using clk_id 0x2. I can use your code now I worked that out and just patched it in. I am using a Keil 5.0 compiler and it is throwing a pile of warnings with printf and mismatch of sizes to variadics but it does work now with your printf re-installed if I fix the messages (I also cant pass uint32_t to variadic %d .. one is signed one is unsigned throws an immediate error).

So the take away is I am obviously on a different compiler and board to you. On my compiler uint32_t is a long not an int which seems to be what most of the printf warnings are about I had to fix the uint32_t going into %d. My compiler int is only 16 bits not 32 bits and both situations are allowed that is compiler defined. I think from memory Keil does that because the half word instructions are faster on an ARM8, I know on ARM7 it changes int to 32Bit because there are no half word instructions.

Anyhow got it running so leave me with it but I just need to keep in back of my head those two slight differences.

Update: I looked up the different models of the Pi3 there appears to be two the obvious giveaway is the metal lid on the CPU.
The early one marked as Rev B 1.2 .. 2015 and it runs at 1.2Ghz
https://www.raspberrypi.org/app/uploads ... 9x1080.jpg
The later one marked as Rev B+ ... 2017 and it runs at 1.4Ghz
https://www.raspberrypi.org/app/uploads ... 2x1080.jpg

I am running on the later one with a metal lid which are you using?

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

Re: Bare metal BCM43438 Driver

Thu Mar 12, 2020 11:58 am

The early one marked as Rev B 1.2 .. 2015 and it runs at 1.2Ghz
https://www.raspberrypi.org/app/uploads ... 9x1080.jpg
This one (2015 model with NO metal lid).

Btw which host operating system do you use for development? Does it support docker? My code didn't have any warnings as per arm-none-eabi-gcc .
Let there be some light .../\...

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

Re: Bare metal BCM43438 Driver

Thu Mar 12, 2020 2:37 pm

I am cross compiling off Windows 10 and no never use docker on it.

Now we might have an issue if I am reading the brcmfmac driver right
Your model the Pi3 B uses a CYW43438
My model the Pi3B+ uses a CYW43455

Not sure if it is significant but I am just writing stuff down as I crawl thru the driver.

Now the first thing it looks like both the plan9 driver and the linux driver do is set the speed to 400Khz, you don't ever seem to actually set the speed.

Both the Plan9 driver and the the Linux driver call it initfreq and it is defined as such

Code: Select all

Initfreq	= 400000,	/* initialisation frequency for MMC */
Am I missing something with your code but I don't see you do that?
They engage high speed after they do some initialize negotiations.

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

Re: Bare metal BCM43438 Driver

Thu Mar 12, 2020 3:02 pm

Are you looking at plan9 driver here: https://9p.io/sources/contrib/miller/9/bcm/sdhost.c

Set Clock

Code: Select all

static void
emmcclk(uint freq)
{
	u32int *r;
	uint div;
	int i;

	r = (u32int*)EMMCREGS;
	div = emmc.extclk / (freq<<1);
	if(emmc.extclk / (div<<1) > freq)
		div++;
	WR(Control1, clkdiv(div) |
		DTO<<Datatoshift | Clkgendiv | Clken | Clkintlen);
	for(i = 0; i < 1000; i++){
		delay(1);
		if(r[Control1] & Clkstable)
			break;
	}
	if(i == 1000)
		print("sdhc: can't set clock to %ud\n", freq);
}


In my code

bcm2835_probe -> bcm2835_add_host -> . bcm2835_set_ios -> bcm2835_set_clock

Code: Select all

int bcm2835_set_ios(struct sdhost_state *host)
{
	struct mmc *mmc = host->mmc;

	if (!mmc->clock || mmc->clock != host->clock) {
		bcm2835_set_clock(host, mmc->clock); // I should check if this is getting called.
		host->clock = mmc->clock;
	}

	/* set bus width */
	host->hcfg &= ~SDHCFG_WIDE_EXT_BUS;
	if (mmc->bus_width == 4)
		host->hcfg |= SDHCFG_WIDE_EXT_BUS;

	host->hcfg |= SDHCFG_WIDE_INT_BUS;

	/* Disable clever clock switching, to cope with fast core clocks */
	host->hcfg |= SDHCFG_SLOW_CARD;

	writel(host->hcfg, SDHCFG);

	return 0;
}
I am following uboots sdhost driver as it didn't have any interrupt handler code. I thought it should be easy to migrate.

https://github.com/u-boot/u-boot/blob/m ... 5_sdhost.c


-----Update-----
If you install docker desktop from here: https://hub.docker.com/editions/communi ... op-windows
You will need to sign up on docker hub that you can do using email/gmail/github credentials.
Once you start docker desktop daemon then no more cross-compiling.
Let there be some light .../\...

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

Re: Bare metal BCM43438 Driver

Thu Mar 12, 2020 3:52 pm

But it's after you call the internal reset and that sets up the host commands ??????

Code: Select all

bcm2835_reset_internal(host);
bcm2835_set_ios(host);
That is why I hadn't run across it yet.

Ok if U-boot works you must be able to do it that way ... so leave it for now I was just confused following the other two drivers.

Remember I have no documentation on order of stuff, so I have to question if different.

UPDATE:
Okay found your first definite bug which is C pointer arithmetic fail 101

You use register r a pointer to a uint32_t but you pass in reg as proper index offsets aka 0,4,8,0xc etc
Get the error r[reg] will multiply reg * 4 as per standard C pointer arthmetic.
I am also saying they should be volatile pointers just to be safe so the optimizer doesn't inline and remove them

Code: Select all

static void writel(uint32_t val, uint32_t reg)
{
	uint32_t *r = (uint32_t *)SDHOSTREGS;
	r[reg] = val;
}

static uint32_t readl(uint32_t reg)
{
	uint32_t *r = (uint32_t *)SDHOSTREGS;
	return r[reg];
}
You need to divid your register index offset by 4 like so as you pass it in as reg :-)

Code: Select all

#define SDCMD  (0x00 >> 2)/* Command to SD card              - 16 R/W */   ARRAY INDEX 0
#define SDARG  (0x04 >> 2)/* Argument to SD card             - 32 R/W */       ARRAY INDEX 1
#define SDTOUT (0x08 >> 2)/* Start value for timeout counter - 32 R/W */ ARRAY INDEX 2
#define SDCDIV (0x0c >> 2)/* Start value for clock divider   - 11 R/W */      
#define SDRSP0 (0x10 >> 2)/* SD card response (31:0)         - 32 R   */
#define SDRSP1 (0x14 >> 2)/* SD card response (63:32)        - 32 R   */
#define SDRSP2 (0x18 >> 2)/* SD card response (95:64)        - 32 R   */
#define SDRSP3 (0x1c >> 2)/* SD card response (127:96)       - 32 R   */
#define SDHSTS (0x20 >> 2)/* SD host status                  - 11 R/W */
#define SDVDD  (0x30 >> 2)/* SD card power control           -  1 R/W */
#define SDEDM  (0x34 >> 2)/* Emergency Debug Mode            - 13 R/W */
#define SDHCFG (0x38 >> 2)/* Host configuration              -  2 R/W */
#define SDHBCT (0x3c >> 2)/* Host byte count (debug)         - 32 R/W */
#define SDDATA (0x40 >> 2)/* Data to/from SD card            - 32 R/W */
#define SDHBLC (0x50 >> 2)/* Host block count (SDIO/SDHC)    -  9 R/W */
Possible second bug ... this makes no sense to what comments say that does not equal 250 Million

Code: Select all

	host_ptr->max_clk  = 250 * 100 * 100; // 250 Mhz

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

Re: Bare metal BCM43438 Driver

Thu Mar 12, 2020 7:13 pm

Hmm made sense to me. Now I could actually see the values written in registers.
I should have checked if the register values after write and read are same.
I changed the frequency to 250 * 1000 * 1000.

Still getting the same timeout error.
Let there be some light .../\...

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

Re: Bare metal BCM43438 Driver

Fri Mar 13, 2020 12:02 am

Yeah that was all I got thru last night, and ran out of time and didn't work for me either.

Now if you get time before I get a chance to look at it tonight can you look at the readl_poll_timeout macro.

All I can see is if you set cond to any value other than zero it reads the register and immediately exits with 0
If you set cond to zero it reads the register then continues reading the register until it times out and exist with -1

I simply don't get what that is doing ... it seems very wrong. From the name what I was expecting it to do was read a register until it matched the cond or if cond was a mask until any of the bits in cond where met. The final option was it timed out.

Beyond the what the hell is that macro supposed to do is what is cond?

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

Re: Bare metal BCM43438 Driver

Fri Mar 13, 2020 2:04 am

LdB wrote:
Fri Mar 13, 2020 12:02 am
Yeah that was all I got thru last night, and ran out of time and didn't work for me either.

Now if you get time before I get a chance to look at it tonight can you look at the readl_poll_timeout macro.

All I can see is if you set cond to any value other than zero it reads the register and immediately exits with 0
If you set cond to zero it reads the register then continues reading the register until it times out and exist with -1

I simply don't get what that is doing ... it seems very wrong. From the name what I was expecting it to do was read a register until it matched the cond or if cond was a mask until any of the bits in cond where met. The final option was it timed out.

Beyond the what the hell is that macro supposed to do is what is cond?
I spent some time last night checking that macro. I don't understand the SDCMD_NEWFLAG mask. Why is that being used as mask? And are we expecting SDCMD register to change the value when command finishes? If send command writes 0x400 to register and then the code expects it should have 15th bit set i.e. 0x8xxx. If we could find any doc or need to check more sources
Let there be some light .../\...

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

Re: Bare metal BCM43438 Driver

Fri Mar 13, 2020 12:06 pm

In for the evening .. so where did this macro come from I assumed you wrote it?

Update: ok I found readx_poll_timeout on the u-boot source tree I assume that is source ... I am struggling it doesn't do anything like what it says it does on the header unless cond is a function pointer? I will look at it's use in u-boot.

Then it sort of makes sense you call the function if it meets what you want then it exits if not it runs to completion and reads the port, but the function has to be feed val as well. It really is a stupid macro I don't get why they didn't just make an inline function.

update1: Ok looks like I got it right
https://elixir.bootlin.com/linux/v4.3/s ... poll.h#L26
@cond: Break condition (usually involving @val)
So cond is a function pointer or another macro that usually involves val

Ok that won't work with your code you are passing in a value

So when you do this it's all wrong

Code: Select all

ret = readl_poll_timeout(SDCMD, value, !(value & SDCMD_NEW_FLAG), timeout_us);
You need a function and value has to be accessible by both the function and that call
So something like this

Code: Select all

in value = 0;
int TestVal (void)
{
    return (!value & SDCMD_NEW_FLAG);
} 
Then you setup the line above as

Code: Select all

ret = readl_poll_timeout(SDCMD, value, TestVal(), timeout_us);
So now in the macro cond = TestVal() and it returns a value
So each loop it calls TestVal which does and AND on !value and SDCMD_NEW_FLAG and return 0 (false) or some other value (true).
Now this line makes sense and it does what macro header says

Code: Select all

if (cond) break; 
Welcome to macro madness :-)

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

Re: Bare metal BCM43438 Driver

Fri Mar 13, 2020 12:33 pm

Ok. Did it work for you? and I am not sure I understood it well. Why wouldn't it work? Is it not working in u-boot code :D ?

I see you have changed the condition itself.

https://github.com/u-boot/u-boot/blob/m ... ost.c#L399

Code: Select all


	ret = readl_poll_timeout(host->ioaddr + SDCMD, value,
				 !(value & SDCMD_NEW_FLAG), timeout_us);
Let there be some light .../\...

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

Re: Bare metal BCM43438 Driver

Fri Mar 13, 2020 1:15 pm

I don't know U-boot at all (like you can put what I know about it on a postage stamp). All I am saying is based on that code I can't see how they get it to work I am totally lost, I understand the linux code in iopoll.h and the u-boot code looks like a failed translation
https://elixir.bootlin.com/linux/v4.3/s ... poll.h#L26.

I sort of need answers
Are you sure the u-boot code runs the Pi3 wifi?
Why did you choose to follow the U-boot wifi code?
Do I just start following the linux code or plan9 if that runs the wifi?

It is a lot of crawling thru and fixing code and if at the end of day if there is other issues like this it is a waste of time. I really want to be following working code :-)

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

Re: Bare metal BCM43438 Driver

Fri Mar 13, 2020 1:28 pm

LdB wrote:
Fri Mar 13, 2020 1:15 pm
Are you sure the u-boot code runs the Pi3 wifi?
I am not sure if it runs Pi3 Wifi (Probably not). I don't know if uboot's sdhost code work. I assumed it's present in master branch of their repo so it must have gone through some testing.

Why did you choose to follow the U-boot wifi code?
>> It's sdhost driver code (I mentioned I was stuck on sdhost driver first). It's not wifi code. It is dependency for me. I wanted sdhost to read sd card and emmc controller to driver the wifi.
>> Now it's the simplest code I have seen for sdhost. Again I assumed it must be working.


Do I just start following the linux code or plan9 if that runs the wifi?
>> After these kinda issues, I feel we should follow linux or Plan9.
Let there be some light .../\...

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

Re: Bare metal BCM43438 Driver

Fri Mar 13, 2020 1:30 pm

Yep I am going to try a quick patch and if that fails I follow one of the others ... can you check plan9 drives the wifi while I try this

Ok so this is my suggested replacement I am going to try for the macro which is a function

Code: Select all

int readl_poll_timeout(uint32_t addr, uint32_t val, int (*cond) (void), uint64_t timeout_us)
{
	uint64_t timeout = timer_getTickCount64() + timeout_us; 
	for (;;) {
		val = readl(addr);
		if (cond)
			break;
		if (timeout_us && tick_difference(timer_getTickCount64(), timeout)) {
			(val) = readl(addr);
			break;
		}
	}
	if (cond)  return 0;
	return -1;
}
I will have to fix up each call to it ... hang on to your hat and lets see how this goes.

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

Re: Bare metal BCM43438 Driver

Fri Mar 13, 2020 1:57 pm

Okay there is only one use of that macro .. so here is code I used

Code: Select all

int readl_poll_timeout(uint32_t addr, uint32_t val, int (*cond) (void), uint64_t timeout_us)
{
	uint64_t timeout = timer_getTickCount64() + timeout_us; 
	for (;;) {
		val = readl(addr);
		if (cond)
			break;
		if (timeout_us && tick_difference(timer_getTickCount64(), timeout)) {
			(val) = readl(addr);
			break;
		}
	}
	if (cond) return 0;
	return -1;
}

int value = 0;
static int Test1(void)
{
	return !(value & SDCMD_NEW_FLAG);
}

static int bcm2835_read_wait_sdcmd()
{
	int ret;
	int timeout_us = SDHST_TIMEOUT_MAX_USEC;

	ret = readl_poll_timeout(SDCMD, value, Test1, timeout_us);
	if (ret == -1) {
        LOG_DEBUG("%s: timeout (%d us)\n", __func__, timeout_us);
    }
	return value;
}
It seems to get thru init_sdcard correctly in that response is 0, do you want to try whatever happens next
I have reached while (1){} in kernel.c and I need more code :-)
-----------------Kernel Started Dude........................
timer_regs:0x3f003000
Kernel End: 0x18a000
f_max 250000000, f_min 122129
=========== REGISTER DUMP ===========
SDCMD 0x00000000
SDARG 0x00000000
SDTOUT 0x00f00000
SDCDIV 0x00000000
SDRSP0 0x00000000
SDRSP1 0x00000000
SDRSP2 0x00000000
SDRSP3 0x00000000
SDHSTS 0x00000000
SDVDD 0x00000001
SDEDM 0x00010800
SDHCFG 0x00000400
SDHBCT 0x00000000
SDHBLC 0x00000000
============================
bcm2835_probe -> OK
received command : 0
Previous command 0
Command Index 0
=========== REGISTER DUMP ===========
SDCMD 0x00000000
SDARG 0x00000000
SDTOUT 0x00f00000
SDCDIV 0x000007ff
SDRSP0 0x00000000
SDRSP1 0x00000000
SDRSP2 0x00000000
SDRSP3 0x00000000
SDHSTS 0x00000000
SDVDD 0x00000001
SDEDM 0x00010800
SDHCFG 0x0000040a
SDHBCT 0x00000000
SDHBLC 0x00000000
============================
preparing data
Starting command execution arg: 0
Response :0

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

Re: Bare metal BCM43438 Driver

Fri Mar 13, 2020 2:19 pm

UPDATE: So I sort of followed this
https://iosoft.blog/2020/03/08/zerowi-part3/

Sent cmd 0
sent cmd 8 arg 0x1AA
sent cmd 5 arg 0x0
send cmd 5 arg 0x200000

All seems to work to there ... I don't get how the response works yet
Now I send cmd3 arg 0x0 but I need a response type so I tried MMC_RSP_R2
I made a uint8_t buffer and passed that to command .. just guessing atm

So here is code

Code: Select all

    struct mmc_cmd cmd = { 0 };
    int x = 0;
    cmd.cmdidx = MMC_CMD_GO_IDLE_STATE;
	cmd.cmdarg = 0;
	cmd.resp_type = MMC_RSP_NONE;
    x  = bcm2835_send_cmd(sd_host, &cmd, (void *)0);
    printf("Response :%x \n",x);

    cmd.cmdidx = 8;
    cmd.cmdarg = 0x000001AA;
    cmd.resp_type = MMC_RSP_NONE;
    x = bcm2835_send_cmd(sd_host, &cmd, (void*)0x0);
    printf("Response :%x \n", x);

    cmd.cmdidx = 5; 
    cmd.cmdarg = 0;
    cmd.resp_type = MMC_RSP_NONE;
    x = bcm2835_send_cmd(sd_host, &cmd, (void*)0x0);
    printf("Response :%x \n", x);

    cmd.cmdidx = 5;
    cmd.cmdarg = 0x200000;
    cmd.resp_type = MMC_RSP_NONE;
    x = bcm2835_send_cmd(sd_host, &cmd, (void*)0x0);
    printf("Response :%x \n", x);

    cmd.cmdidx = 3;
    cmd.cmdarg = 0x0;
    cmd.resp_type = MMC_RSP_R2;
    uint8_t resp[1024];
    x = bcm2835_send_cmd(sd_host, &cmd, (void*)&resp[0]);
    printf("Response :%x \n", x);
Here is what is outputs ... so it seems to work until cmd3 which I dont understand
Pretty sure it's working given it gets thru to cmd 3.

Code: Select all

-----------------Kernel Started Dude........................
timer_regs:0x3f003000
 Kernel End: 0x18a000 
f_max 250000000, f_min 122129
=========== REGISTER DUMP ===========
SDCMD  0x00000000
SDARG  0x00000000
SDTOUT 0x00f00000
SDCDIV 0x00000000
SDRSP0 0x00000000
SDRSP1 0x00000000
SDRSP2 0x00000000
SDRSP3 0x00000000
SDHSTS 0x00000000
SDVDD  0x00000001
SDEDM  0x00010800
SDHCFG 0x00000400
SDHBCT 0x00000000
SDHBLC 0x00000000
============================
bcm2835_probe -> OK
received command : 0 
 Previous command  0 
Command Index 0 
=========== REGISTER DUMP ===========
SDCMD  0x00000000
SDARG  0x00000000
SDTOUT 0x00f00000
SDCDIV 0x000007ff
SDRSP0 0x00000000
SDRSP1 0x00000000
SDRSP2 0x00000000
SDRSP3 0x00000000
SDHSTS 0x00000000
SDVDD  0x00000001
SDEDM  0x00010800
SDHCFG 0x0000040a
SDHBCT 0x00000000
SDHBLC 0x00000000
============================
preparing data 
 Starting command execution arg: 0 
Response :0 
received command : 8 
 Previous command  400 
Command Index 0 
=========== REGISTER DUMP ===========
SDCMD  0x00000400
SDARG  0x00000000
SDTOUT 0x00f00000
SDCDIV 0x000007ff
SDRSP0 0xffffffff
SDRSP1 0x00003f7f
SDRSP2 0x00000000
SDRSP3 0x00000000
SDHSTS 0x00000000
SDVDD  0x00000001
SDEDM  0x00010800
SDHCFG 0x0000040a
SDHBCT 0x00000000
SDHBLC 0x00000000
============================
preparing data 
 Starting command execution arg: 0 
Response :0 
received command : 5 
 Previous command  400 
Command Index 0 
=========== REGISTER DUMP ===========
SDCMD  0x00000400
SDARG  0x00000000
SDTOUT 0x00f00000
SDCDIV 0x000007ff
SDRSP0 0xffffffff
SDRSP1 0x0000ff7f
SDRSP2 0x0fffffff
SDRSP3 0x00000000
SDHSTS 0x00000000
SDVDD  0x00000001
SDEDM  0x00010800
SDHCFG 0x0000040a
SDHBCT 0x00000000
SDHBLC 0x00000000
============================
preparing data 
 Starting command execution arg: 0 
Response :0 
received command : 5 
 Previous command  400 
Command Index 0 
=========== REGISTER DUMP ===========
SDCMD  0x00000400
SDARG  0x00000000
SDTOUT 0x00f00000
SDCDIV 0x000007ff
SDRSP0 0xffffffff
SDRSP1 0x0000ff7f
SDRSP2 0xffffffff
SDRSP3 0xffffffff
SDHSTS 0x00000000
SDVDD  0x00000001
SDEDM  0x00010800
SDHCFG 0x0000040a
SDHBCT 0x00000000
SDHBLC 0x00000000
============================
preparing data 
 Starting command execution arg: 0 
Response :0 
received command : 3 
 unsupported block size (1431655765 bytes)
Response :ffffffff 

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

Re: Bare metal BCM43438 Driver

Fri Mar 13, 2020 3:21 pm

LdB wrote:
Fri Mar 13, 2020 1:30 pm
can you check plan9 drives the wifi while I try this
I tried plan9 on my Pi3. I see boot screen but it gets stuck at due to some error. May be some config mismatch. I have seen a lot of cmdline.txt files which suggest it does have ethe4330 as wifi. 9fans mailing list suggests wifi works on pi3.


LdB wrote: Sent cmd 0
sent cmd 8 arg 0x1AA
sent cmd 5 arg 0x0
send cmd 5 arg 0x200000
Are you trying to use wifi using sdhost controller? I thought sdhost is used only for reading sd card and emmc should be used for WIFI.
Let there be some light .../\...

Return to “Bare metal, Assembly language”