 The story so far. I am attempting to port Alan Cox's physics operating system to the ESP 8266 last time I in a long rather boring video managed to get the build system and All the source code actually compiling so I do you now have a Binary that I can flash and run on the device which I shall demonstrate oops, that's Get that on the screen And run the serial terminal and hit the reset button and it starts and immediately hangs there are some obvious stuff wrong But since the last video was basically me adding stuff to a make file This one is where we actually start problem solving Okay, so the first thing that comes up is I spent some time last time Where is it? Getting the interrupt system for this processor Working being able to turn interrupts on and off. This is as we say in the trade all complete bollocks I Found out that this is not how you do it at all Over here. I have the Arduino source code for the ESP 8266 Which is really useful as a reference and it turns out that this CPU actually has an instruction to do exactly what I want to in fact So all we need to do is To turn interrupts on Use the arsill instruction like this This will set the interrupt status to zero meaning no interrupts masked and return the old status in a to to Disable them we do arsill a to 15 and This will return the old status in a to which will then be passed back to the system to restore a previously saved Interrupt state we do Like this So what you do is you call hard DI this returns the old interrupt status to turn them back to what they were before you call IRQ restore pass it in the value in a to and It will set the interrupt status to that That's some comments so This system uses a different comment character Okay, so let's try burning that and seeing what happens. See if anything's any different. Yep. It is actually now better It's interesting that we get a different result this time. So What this probably means is that it is actually hang on a second That's a flash address two one three six F a this is Trying to set up This is trying to set up a process. I'm not sure it should be doing that at this point Also, I'm a little surprised by the fact that immediately after burning we got the reboot panic Which actually needs some work in main. See where is where is panic? Oh Panics a panic is a core functions in process to see What it does is the kernel has detected an error. Therefore it holds here we go Right the reason why we were getting that infinite loop is it's tried to call platform monitor to return to the monitor Which calls platform reboot which calls panic So what we're going to do is just replace this with Oh, actually, we don't need to it's going to do that anyway. This becomes a no op and This can actually be the same. Okay So what's this going to do? Okay, this So it is trying to Yeah, it's about the same address. It's trying to create a process. Let's add some tracing and see where it's going So you'll start to see Fusics main is the startup code and it prints the banner which we are seeing It does some stuff. It does some more stuff. I don't recall seeing this message, but let's try that again Shall we okay? It's printed dev boot, but nothing else. Where does dev boot happen? Do I see in it? Oh? No, it's up here and the it's up here Okay, let's stick some tracing in This is a useful trick with C uh underscore underscore line returns the current line number so we can just go through like that And we hit the reset button prepared to pause trace and what's that done? 391 Okay right so That has failed at create init which is creating the The init process. Oh, it is in start to see So this will mean that part of our process setup isn't working which is really No one is going to be surprised at that so the way physics and old-fashioned unix was work is There is no kernel process or kernel stack after system startup when the system boots It sets up all the hardware then it creates a init process and Hands control over to that process which is happening here and then none of this code is used anymore So what create init is doing is it's setting up that first process This is loaded off disk. It's in fact the init binary You can see here it's setting up the command line tracing in This will no doubt be because You data stuff isn't set up correctly. Yeah make proc has failed process Okay. All right. Here is a line where it's actually turning interrupts off and Returning the old interrupt state so down the bottom it calls IRQ restored and back in again So let's stick some tracing in Just tell us what the various process pointers are to make sure they look reasonable the reset pause right now That doesn't look right if we look at our memory map we can see that all the user data lives at 3ffe 8.00 and The way our process is going to be laid out is the user data block which is 512 bytes Lives at the beginning of that So you can see that the user data pointer is correct about the process pointer is not now Why is that? not right dot-dot-c In it. So this is creating it in it process p-tab Alloc I Wonder So kernel data is going this is where all the kernel variables live is going into Do you am not not seg? Which is here? Yeah, that is the right address not what I wanted to do. I wanted to do this So this is listing all the symbols in the process So here I can see the user-based address is at e eight oh While actual data starts later. Where is the process tab? Let me just run that again Because I think I may have misread it. Yeah, I misread it. This is 3ffe. This is 3fff eight. That's correct So it is dying at two one three seven oh e It's trying to increase the reference count of the Current working directory. I node. So why is that problematic? That's here Okay, so what is current working directory I node Should be zeroed actually Be much it'd be really useful if I had a debugger I believe that this platform does support JTAG, but I don't have a JTAG adapter so That is an address in Flash four or two one oh three eight five Three eight five wasn't it four or two one oh three eight five four or two one oh three eight five Not there. Okay. That's garbage Why is that garbage well the Udata block? Is right the Udata block is at the beginning of our user data It should have been initialized to zero I Assume it should be initialized to zero. So why hasn't it been Because the system is it because the way this is written. It's expecting Udata here to be in the kernels BSS area Do you want to put it in the kernels BSS area? I think we actually have the RAM to do so It will make swapping stuff in and out more complex But we'll actually simplify a bunch of stuff. Yeah, let's do that. So Don't remember where that was actually set up. What does config split user data do again? In fact, it is no No, no, no, yeah, it is no more additional complexity for us because the codes already been written. Oh But we have to enable config split user data Okay, so in fact the setup we've got here is wrong we do need to put it in our BSS right where is Udata set up it's in Tricks dot s. Let's get rid of this Let's find out how Dragon platform does it it's defined in Common mem dot s and it does need to be 512 bytes because the kernel stacks there So we do still need this here, but we can just say common Udata 512 so now if you look at the symbol table We can see it is at a 770 Top of the kernel data area is at a 978 and The end of our segment is at c00. So that leaves 8k free that's loads Okay, let's see what this does Still no luck, but that's a different address 2138 CF Interesting this is actually crashing earlier, which is Intriguing it's trying to allocate a new Process so it's failed here so exception 28 over here I have the Manual try and find where the list of exceptions are. I hope 28 is in decimal a list somewhere I'm gonna have to understand here we go. I'm gonna have to understand the exception Huh Okay, that's right. That's a bad address Probably a null point of your reference I'm going to have to understand the exception system at some point because I need to add support for those And I believe this is the address that failed so it's trying to load this Right that's going to be null plus an offset of 4c and I bet 4c is the offset of p-group so p-tab here is No, but this piece of code is actually allocating the process table slot So it fine it go it iterates through the process table it finds an empty slot It zeroes it It calculates a new PID it does not initialize you p-tab at this point. So where does that get set up in? dark.c in Creating it. Okay, so Oh, does this ever work because if it's in if it's setting up the u p-tab variable after it creates the after it allocates the p-tab slot Does it happen in make proc here? Yes, I think it must Do Here no Yeah, so So p-tab alloc which is called from start.c and Make proc happens after all this so it can't be make proc that's setting it up Okay, the other place it could be happening is in platform code. So Let's look for references Yeah, it could be there Okay, this is from machine code. So That's reading it. That's only reading it Not writing to it anywhere So this could be a kernel bug in that it shouldn't be trying to dereference this without Looking at it first On most 8-bit platforms null does not actually De-referencing null doesn't cause a exception So it's possible that this is just a bug that is Hasn't been fixed So we could change the code in Processor.c Processor.c No, it wasn't it was in Wasn't Processor.c I am forgetting what I'm doing And that was in p-tab alloc as well. So this could just be No, because then it's it's dereferencing It's doing this as well. So I believe this is creating a child process So the child process is the In the same process group as the parent Let's just So this feels kind of wrong to be honest, but I think that's right Unless there's supposed to be some code somewhere Which initializes this stuff in the kernels Udata, but of course the stuff that does that is right here in start.c Yeah, I think it is actually this Okay So what does it do? Okay, that's a little better It has It has set up the It's set up the init process And then has failed at boot dev. I think at this point it's actually asking for a boot device But either it doesn't either it's hung or else I haven't implemented Uh tcy getchar But this is wrong for a start So let's go back to Start.c to figure out where that comes from So I believe it's got to Yeah, it's called get root dev Right, this is where the Uh ram size and proc mem are set up. So where does that get set in the platform code? There's nothing exciting here So that's just going to be this is kilobytes. So ram size is always going to be 80 for us proc mem is the user process size Is it well Given that we have one process. I think that's going to be 64 although Things are made more complicated by the fact that we have separate banks for data and code But I believe that these values are a merely advisory so I don't think it matters what we set them to All right, uh Failed with an error proc mem undeclared It's a scramble. Okay, that's better. Okay 80 k total ram 64 k available to processors 15 processors max That seems kind of okay Right, I think we are going to have to tackle the tcy next which is going to be exciting ish so We're looking for Get root dev Which is here um, yeah, this is Yeah, the way this happens is the Uh, the platform code can supply a kernel command line which contains the boot configuration if The boot configuration isn't on that Then it prompts the user using CD read so that is obviously where it's currently hanging So what we want to do is to set up the command line which appears in platform code Where is it actually defined? Or it calls set boot line So what we probably want to do is Why is it calling that from inside dev nbr? uh dev nbr is the code that Uh Handles dos style master boot records Uh, you give it a block device and this stuff knows how to divide it into partitions Okay, uh, what it's doing is it's looking for a boot command line Uh on the hard drive If there is one And we don't have one So what we're going to do is just call it Set boot line to be I don't actually know what this is supposed to be So we want to boot off Uh partition hd a2 This is the first hard drive second partition So that is going to Be I think this is just going to be hd a2 And this will probably fail. I mean if it works it will fail If that makes sense What's that doing? Oh hang on a second Boot device is a kernel configuration option Which we've set I think we've set I think what this is is Uh Right we can set boot device here And it will emit all this code And hard code the boot device Or it will I don't think that's right Or it will use the code here to try and decide whether to Uh Whether to read it from some command line. Okay, so let's not do that and just do boot device Oh to hd a2 that was from the prompt that will make our code slightly smaller Still 37k. So what's this doing? Exactly the same Because we need to clean and rebuild And define reference to get root dev That I saw that as defined right here Here even Or even here So this is the code you get if you Define boot device So is this actually being compiled? Yes It still can't find get root dev. Is this inline wrong? Yeah, the inline was wrong Uh c support for inline is a bit weird That should probably be static inline. Yeah, that's better Uh, if you just put inline on its own then the c compiler Well, it's not really defined very well that behavior But clearly what's happening is the c compiler is not emitting any code for this Because it's expecting it to inline it why it didn't inline it down here. I don't know But let's try this and see what it does Right good This is getting somewhere It's attempted to mount the root file system and has failed because there is no root file system Our devices are Defined here So there is no file system because we haven't defined config ide Which means our block our Hard drive device is defined as nothing So it tries to access it it fails and it panics So we're going to have to have a file system Now this is actually a little bit more complex than it might seem We could put our file system on flash On the internal flash But for that we need a ware leveling system Because the flash On this device does not have any automatic ware leveling So we can't just put an ordinary file system on it or else we'll ruin the flash in no time Because normal file systems keep writing to the same blocks over and over again And flash only has a limited lifetime another option Is to use an sd card. I do have a spi sd card adapter On my desk somewhere Which I was planning to use for this it should just plug in and work The only Potential issue with that is that then involves lots of fiddling around with hardware registers and wires The other option is to use a Read only file system. That's just been bodged into a char array That would probably work But I don't think I want to go that route Because all that work would be wasted We'd have to implement the block device Functions for our fake file system so Let us just turn on config ide This will fail to build. Okay. We want the block dev layer Which is defined in Dev So we want to add So why hasn't that Built it So this should be the block device layer. Hmm interesting Is a optional add-on It provides most of the work involved in doing block devices The boilerplate so it lives in its own separate Library Okay, we need to reference it from Here it's built as part of the platform That should have built Yeah, it's actually has in fact called the The compiler here There should be a block dev. Oh somewhere. Oh, it's there. That's an odd Place to put it Hmm, okay uh So apparently if you don't tell it specifically where to put the object file it puts in the current directory rather than in the directory that belongs to the Rather than the same directory as the source file, which is odd. Anyway, we now have this uh Building we need to add the mbr library. I mentioned earlier. Is that one of those? No, it's one of these No, it's dev Silly me Okay And that actually links I thought it wouldn't Well, let's run that and see what happens. Okay, that's exactly as expected uh We need So it's looked up the device here Uh, it's called block dev open to open it. Uh, it's Try to find it in the block device table and has failed So we need We need to decide how we're going to do this. I think what I want to do is to actually use the sd card Because we're going to want to do that anyway. So I will need to hook it up with wires And also go and find out how to actually access sd cards from a esp8266 Um, I know it's got hardware to do this. I mean sd cards speak spi And the flash on this device is spi But I don't think we can use the same spi interface that used for the flash for the sd card So we may have to bit bang it through gpi opens But I believe there's better ways to do it than that. So I'll have to go look that up For now, I think There's a big advantage of sd cards is that they're already supported Here So I think all we need to do is just put this in Turn this on Yeah, we also need This and we need to define some Symbols to actually do the low level sd card access Yeah, so sd drive count One dev sd transfer sector is a Platform thing Yeah, this is the low level routine to access Uh the sd card. So if you take a look at msx2 Should be in there. You can see that it defines dev sd transfer sector In machine code now, I've actually done this before so This is the msp430 version this is This is using the msp430 ignore that comment Uh internal routines for accessing the sd card by It's own s it's own spi interface. So you can see it's actually really simple. There's not a lot to it All you do is Set it up that actually happens in the discard version here So hardware initialization Then you implement One or two functions to send and receive data It's on low level stuff So like to send a byte To Oh, yeah, uh on spi in order to receive a byte you have to send a byte you clock a byte out on the bus and the slave device In response clocks bits back in again So in order to read a byte from the slave device the master writes a zero and Reads the result back that way So we then have yeah, well all right writes a writes ox ff So we just wait until it's ready and then Send uh, no, we don't what we do is we write the byte to the output buffer We then wait until the output buffer is empty And we return the value of the input buffer The hardware does everything for us. It's so What am I going to do at this point? Nothing. I think Are nothing code wise. I I'm actually going to therefore take a break and attempt to hook up the hardware and a sacrificial sd card And I'll also do some reading up and look at the The arduino code see how it's doing sd cards because I'm sure it is Okay Back in a bit All right, then I've wired it up and done some reading It turns out that the esp a 266 has two spi interfaces called Uh, originally enough spi and hspi spi is used for reading flash Code so we don't want to touch that. So the one we're going to use is hspi Luckily it is completely independent Uh Whereas the piece of code here we go The arduino's got a library for talking to it. So I've wired it up Uh, according to these instructions So we have the clock We have my so master in slave out That is data from the sd card to the esp 8266 We have mozzi master out slave in which is the reverse And we have chip select The way you work spi is that all your spi devices are connected to these three wires However, the each device has its own chip select line. So you can talk to any one particular device By setting the appropriate chip select line and Then that device listens and the others do not So Over here I have let's just get rid of that comment This is a copy of the msp430 file Which I've added to the esp8266 source And we're going to have to initialize things So the first thing we're going to need to do from looking at the Arduino code which is here Is we need to tell the uh The system that the four pins that our sd card is connected to should be connected up to the hspi device The low-level functions for doing this are a little bit clunky. They really want you to use the The esp8266 client library, which of course we're not So Our device is connected to these gpios So that is in epio 13 okay, so This is just this line was just cut and pasted from existing code. So I know the format Is that a reference? You need to find the name of the pins They're all labeled something reasonably Sensible Okay, here we go HSPI in default mode Here are the spi pins Here are the names used by the system. So mtdo is the chip select line Anyway, do we have a mtdo we do So max mtdo you get set to Something to tell it that this needs to be connected to the hspi system See I was expecting to see a funk here I'm not a great fan of this Library to be honest. It's Extremely clunky. Anyway, let's just do the next one Is mtck And that wants to be wired up to the spi clock mtdi. No, sorry mtck is mozzie m Tdi is This formatting is a bit weird mtdi is my so mtms Or mtck you mtdi you and mtms you Okay, and these pins described here are for the other SPI interface I also believe that the sp8266 has a high-speed sd card slave interface that allows it to Pretend to be an sd card. This will be presumably so you can implement stio Devices Okay This complicated macro here does the Function setting Hmm Okay, well, let's go look at the The arduino code the arduino code's got its own way of doing things its own library Which is rather easier to read so that here we can see that Uh The pins used for s clock myso and mozzie are being set to The special function that will hook it up to the hspi device uh the what this is all about is there's a Uh A multiplexer inside the device Which allows the various pins to be connected to different things A one option is gpio pins where you manually turn them on and off uh the There'll be other bits of hardware which can be connected to the same pins We want to make sure that this is actually connected to the Uh hspi device Uh and this bit this stuff here is all about setting up the hspi device itself. So let's actually just Cut and paste that So i'll have to figure out how to do that using expressive headers hspi overlap mode Allows you to Connect a hspi device up to the spi pins But i don't want to do that. I don't want to touch the spi pins at all because they're being they're connected to the flash Uh my flash adapter does actually have a small oled screen on it that also speaks spi So we could multiplex the sd card and the screen onto the same Pins we would end up with two chip select lines okay, well pin modes Let me see what spi.h is set to Okay, that's a global Yeah, that's not it This is all places where it's used This looks That doesn't look like the right one uh, honestly I think I should be searching the Oh, this is this is generic So we actually want looking here Can I search this directory? No, okay. Well Rather than using github, which is easier to read. I actually have a checked out version here So let's just search this for pin mode The arduino libraries in c++ I don't want to use c++ Here is where it's Find This looks like code ouch Yeah, this works completely differently to the uh, expressive stuff okay, so Assuming that the pin number is Blows 16 if we're looking for a mode special uh Which appears to set it to whatever hardware is connected to Then gp ffs Okay, well that's a mess Let's take another look at that library So it should everything should be defined in here So I bet that I just need to set it to one of these funk things. I wonder if there are some global ones There's no references to hsbi And let me have a look to see if there's any code in here There's a fair bit But I'm not sure it's much used to us There's lots of stuff about setting up spi overlap this looks plausible aha to really they didn't bother to define a Symbol for it. Okay And in fact, this is the spi configuration stuff This is for a slave when I'm looking for a master So this you see this is setting the pins to gpio mode so I Okay This is the code for setting up the spi device. I wonder if we could Yeah, I don't want to link to this library Because there are a lot of assumptions that we don't want but I think we are going to want this stuff So this is actually going to be doing this code is going to be doing the same logic as this So we should be able to see references to The same registers to refer to up here Now here is some code for writing to an spi device It's all abstracted out so you can tell it which one you want which we're not going to bother doing I believe it takes care of the chip select stuff itself Read peripheral reg This does look like the same sort of logic to be honest We wait for it to be ready We write to the buffer And let me find read There isn't one read Read esp slave interesting Okay, well here in the rather badly written technical reference there is a Appendix down the bottom if I can grab my scroll bar come on. There we go with the raw Or Registers in it Which should describe what they do? Yeah, the msp430s was easier to understand Okay Well sp1c I bet is I bet that's clock. That's user That's user one C might be command Or control 2 This will be a macro that will return the appropriate register for the spi number So if I search that all right, so in fact I suspect that there is Okay, they don't define register names for the the two SPI units individually So we are actually going to have to stick with spi one clock one And I'm so I want the arduino Set frequency Function, I don't think that's it. Oh, that's useful. That tells us what they all are So this is 108 and u is 11c u1 is 120 u2 is 124 So here if we look for All right, so this is spi user Although this is The one c matches Do I actually want? So here are the two spi units So h spi is one actually we can Do that I'm very surprised. There is no read here Hmm So this is supposed to set the spi frequency. That's interesting. This is common code. It's not the sp specific so I'm not sure These are talking directly to registers. Okay. I'm a little bit confused there I know it is sp code. Oh, that's a lot of work to set the clock That's a lot of work Which of course I'm going to have to duplicate. So what's this actually doing? um So we've got a routine up here for calculating The frequency Based on the register value not the other way around Clock-regged-freak. Yeah Oh, it's searching for a Oh, I agree. Uh, you this is this all this code is there to allow you to Tell it what frequency you want and then it will search for the closest register setting Hmm. Okay. Well set the clock divider is The routine that does the work by Just setting a value in clock div, which is this So what this will be is Some this will be a canned configuration Sets the clock to a particular value, but I don't know what that value is So this sets bits in a register and this clears bits in a register So this is unsetting spi flash mode. What does that do? Don't know. So what is reg spi base? intriguing So this is calculating the actual address of The register Yeah, okay. We don't actually care about that So this is actually setting up the The spi device. I'm going to assume that that's right We've set the pins correctly So the next stage is to try and read and write I'm a little surprised that it's not doing more work to set the clock. There's no mention of clock at all What's this? This is slave initialization, which is not the same thing there's a spi read data in here Use hsbi to read flash data for stability test And the function name here does not match the Function name here at all. This is trying to read from the code flash No, we don't want that at all. Okay. Well, let's take another look at the Arduino code It's possible that the default will work So this seems to be the code that will actually set the The chip select line. This is what we need to put into this function here So what this is doing is the It's using the user one It's using the user one register We've connected the user one register to the hsbi device So this should be set peri reg mask spi user one hsbi two No, that's just my plain user. So these so that has actually set the When we initialize things we do set the Chip select line So then this is going to be clear peri reg mask I Not sure we actually want to set this here, but it was doing it to let's stick with that So is this doing anything else? No Begin transaction here Right, this is the place where it's setting the clock and set data mode here has got to do with Setting the various sd and spi communication modes Which I think I don't want to play with too much right transfer here is the Is our transmit receive routine What we were going to do is Spin until the device is not busy So I assume there's a read peri reg mask routine We want the command Register we want to wait until it's not busy. Then we're going to write to our buffer And then wait again until all our data has been clocked out and then return Whatever that is These just become like so These are common Okay, so we now need to actually do this stuff properly Get peri reg bits is the one we want All right, this will allow us to specify The specific bits we want. So this is going to be here read peri reg bits Whatever spi 1w nought is High low Or we can just use read peri reg which I actually think makes more sense here which I notice A bit further up and that so that will read it as a in 32 And return the bottom eight bits. Okay So this we want to Loop until The busy field is set now It is called spi command Is there a busy flag? There is not So if I were a busy flag, what would I be called? Or I could go look for existing code And he is probably spi user to be honest Here we can see it doing something that looks Very familiar spi interface. I don't recall seeing that one This looks kind of familiar actually Okay, so read peri reg spi command spi num spi user That's just doing it the old-fashioned way, right set command by user This appears to be telling it how many bits are in the Command for us. It's always going to be eight. So Set peri reg spi command uh, sorry spi user to hsbi spi user Command bit len so this is setting Certain bits of the field Okay, I'm gonna have to look up what this does This Is doing something This looks too complicated for just sending an ordinary byte down the wire This looks Much more familiar Right. I think that what this is doing is There's a multi byte buffer Which we need to set up So I think this stuff here Is Artists is doing spi master config command set command value by master mode. Well, that's no use and So is this sending a command to The hsbi unit to tell it to send stuff I don't think it is Well, here's the receive command Yeah, I wonder whether I might be better off just bit banging the interface at least for now I know how to do that more or less I was not expecting it to be quite so badly documented In the master mode. It is the start bit of a single operation self-clear by hardware user this bit enable the command phase operation They will the address phase Yeah, this this is This is set up for sending entire High-level commands to the device uh, the way spi works is you Uh, you tend to send complete packets worth of data And I think that this is supposed to do a complete transaction at the same in one go involving multiple bytes except that's not how our code here works If I go find dev sd.c So like transferring a sector here Uh, we send out a command with a command byte Uh Potentially multiple Address bytes here we go send command We send out the actual Sends out the actual command byte Here we go, uh, then we send the address of the sector we want to receive Uh We set the crc if necessary we send it we Receive the response packet, but what we actually want to do Is just send raw bytes one at a time So I don't think that this code here will help. I think we still need the arduino code And then figure out how to duplicate that Where is it dev sd spc? And spi w naught spi one w naught So now that we know this much I think set data bits here is the one that's actually setting up the simple 8-bit transaction Yeah, this looks familiar Hmm You know I think That I should just copy the arduino's register definitions And not use the Uh, espressives Because honestly, I think they are easier to understand And I will let me cut and paste some of this code which is lgpl So I can't cut and paste it without affecting the license of this Oh, wait, hang on. This is Phusics is GPL so I can use it there I don't think that I'll be using enough of it to matter My own code seems to be MIT or BSD license. I have to think about these things Okay SPI one w zero Is here Okay, so A lot of this stuff we don't want We do still want equal sock because of these because we don't have the arduino's pin mode code But we are going to include this with lots of pain Comment this out for now I want that done Okay transfer this turns into SPI one command and SPI busy set data bits Is uh to say that Oh, we want to we want to send eight bits out and want to read eight bits back U0 equals the byte SPI busy Then wait again to return The red value All right. What's that done? We need to set the chip select line That'll be this SPI one U SPI UCS setup or SPI UCS hold Whereas this is Raise wants to be or Lower wants to be and with the inverse Okay, and What's wrong? Oh links So we now actually have something executing now this stuff not set right So we still need to set the clock frequency And we need to set well lots of things really transaction So we need to set stuff like bit order and data mode as well But that can happen up here Although now I look at it. This is actually setting up eight bit mode Oh, right that is setting I wonder if we actually need this That is this code here has already set up SPI one U1 And this is setting it to exactly the same thing Use of one so This is where it's setting Mozi bits and miso bits and the address bits are zero I don't think we need this I'm going to just comment it out rather than get rid of it Okay. Well, we do need to set the data mode we're going to set it to uh SPI mode three because that's what worked for The this is the msp430 code Which I actually commented reasonably well, which is lucky Yeah, cmo and miso versus miso and mozi I rather prefer mozi, but the msp430 use this of course these terms aren't standardized. Why would they be standardized? Ah, we're using SPI mode zero P that's just for reference We are using SPI mode zero So C pole naught C far naught SPI one U Now we don't want If C far is not we don't want SPI yasmi, which we don't have We don't want SPI one P which we don't have bit order if bit order is I think we do want most significant bit first for of sd Yes, we do So We don't want spi quabo or spi curabo, which we don't have So no configuration there is needed so that Uh data mode and bit order sorted We now need the clock frequency And I think what we're going to do That gets set here because the the sd card code will actually set the clock to fast and slow mode in various points I think we're just going to set it to the minimum possible frequency, which luckily we have a value for so set clock divider spi one clock equals Right I'm gonna get rid of this Okay Well, let's try and see what happens Right. Let's go in the right directory first And it flashes Okay, what happened here? It Failed to Mount the root file system Uh ah There's several things which could possibly be wrong But one important thing is we're never calling sd raw in it Which has to happen from here to initialize the flash divider to initialize the sd card layer Uh So that will cause the entire sbi layer to just not work There's probably other things going on as well, but let's see what this does Okay, that is still failed So we want to put some tracing in You know that's working I'm going to put some tracing in here to see if it's ever actually getting around to calling our code Which I bet it's not It's not Okay, so Up here in dev I Think I need to call dev sd in it To actually add the Uh sd card device to the block device Table Yes, we do So Once that's been added Think about it Okay No, wait, that's scuzzy. I don't want to look at scuzzy Dev sd in it Right. This does not call raw in it So let's see what this does Okay so That's happening because it's Repeatedly hitting line 64, which I bet is received bite, which it is Uh, the sd card layer is pinging the sd card trying to get a response And I suspect not getting one. Let's try that again without the tracing No, yeah time out So This is it's trying to detect the card. So That's this This comment by the way saying initializing sd cards is horrible Is completely true. So I'm Not going to touch this code, but I do want to see what it's doing This is This will let us see the The command flow through the init sequence. So 100 146 sd send command Which lives here Has failed sd spi weight is supposed to wait for the command to be ready it reads Bytes And waits for a particular result So I think it's failing to be ready And now it thinks it is ready. Okay, uh, this I'm actually putting this tracing in the wrong place because the much easier way to do it now that I actually think about it at all is to say So that will trace the entire SPI conversation released it would if uh This bit worked Okay So you can see that it is sending Uh fs as part of the synchronization sequence and spi init Right it's sending 20 fs because it's this What this will do is send bytes to the card to get the card up and running Uh receive byte just it sends a dummy byte and returns the result. So you can see ff going out ff coming back Then it actually sends a command which is this Which is this sequence here And you can see that we're not getting anything sensible back from the sd card So this means that our Our library here is just wrong So the things that could be wrong are we've got the chip select stuff backwards I Okay, let's take a look at this Code This documentation uh you is user So that's this So this is setting Set up bit and a hold bit Don't see anything called set up and hold to be honest We've got that's interesting. Shouldn't we be enabling the mozi and All right, this is user one. I'm thinking about uh Let's say user So there's a my so and a mozi bit that Tell it to enable the read and write phase. So I think we need to set both of those It's going to you me so Duplex There is no duplex duplex could actually be set to both of these at once usse I also don't know about Okay, so here are the user bits Duplex is bit one Which is not defined here. Okay. Well, let's look at It's 27 and 28 Which are Me so and mozi Duplex, I have no idea what it is because it's not described here bite order It's here Both ways around Sio, we don't want. What's usse? Usse Six o'clock edge slave mode Doesn't matter because we're not in slave mode So without the other phase enabled Then either the instructions are reaching the sd card but not coming back Or we're not sending anything. So what's this going to do? Nothing. I want that. We don't want that So what's this s p i m m mozi phase length masks Oh, this is user one again Ah I will say that it's spending an awful lot of time waiting for anything to happen It should be way faster than that if I hit the reset button I can find it See it's taking most of the second to Get through this bit of code That's probably because I set it to the minimum possible clock It's possible the sd card doesn't support that clock And it needs to be faster Uh, but most of the time spent here right that means it's behaving sanely So the buffer is empty or rather the device is not busy when we do the send Which means it prints the dot immediately But it does take a while for this to happen. So Uh, that's why we see a delay Okay, let's go look and see how this clock works this one. So We can set the clock to 80 megahertz by just setting a bit Uh, given that our system clocks at 56 megahertz. I'm not sure that will work. It's worth a try Much faster No difference. So let's put that back Okay, um Now I could have got raised and lower the wrong way around. So let's take a look at the sd card code And see how this works Yes, it's the wrong way around raise is It's The line is active low. So raised means turn it off So that will very much explain why it's not working I keep waiting for the build to finish, but it's really quick to build Nothing try out the fast speed again Still nothing This may be too fast So I could use a logic probe to actually see whether any data is coming in or out That's not really something I can do Here because I have to take it to the workbench The send and receive always transfer a single 512 byte sector So which is why this is kind of simple a byte at the time So let's see in c1 That will be control and control one presumably use control So set to zero is bit order, which we want zero to be most significant bit None of this stuff we care about None of that stuff we care about control two Okay, let's take a look at this SPI 1u that's the user You see Yeah, I was actually looking at this and got distracted by something else But set up and hold Are the things that are supposed to change the chip select line? Where are they? bits 4 and 5 Not documented here intriguing now The way we've done this is that we've connected the chip select line, which is mtdo to gpio 15 which is HSPI mtido HPSICS But this is the chip select line Is that actually referred to anywhere other than here? I think it's not Chrome's pdf viewer is not the greatest but So the other thing we can do is to set this to the gpio value And twiddle it manually. I mean there's absolutely nothing wrong with that So let's so let's set that to funk gpio 15 So raising cs setting it high is going to be uh We need to set the direction as well I've got some code somewhere for doing that Or rather I've got some code from someone else who did that pin dear output So set gpio 15 We should go up here set gpio 15 to output So we can now change the state by using pin out set equals 115 pin out Clear is 115 Which are not defined there so Yeah, the that bit of code is actually not using quite the same Pin library as this is So I'm presuming this I need to do something in the lines of gpio reg write But I need to know which register There are only 16 pins Uh, right. I need to do gpio out address like so I believe out So I think this is a modifier that sets the bits rather than sets them this uh that Or is the underlying register with the value I gave it so that will enable That bit but while leaving the others unchanged while for this I want to do That apparently there is no pin dear output. So I probably want gpio Is there a direction? Okay, let's look these up And that's interesting seems to be That's not what I was expecting at all What I was expecting to see is Is something like this. Okay out. It seems to be the actual direction So this is going to be gpio w1ts Set pin 50 set gpio 15 to output These appear to be additional Um Settings for the pins So do I set the value in gpio enable? I think I do So that's be gpio Enable gpio out w1ts gpio out w1ts address And this is gpio not gpi Let's see what this does Of course, it's nothing Fantastic, uh Always worth swapping these around again I very much doubt this will actually have any effect could be too fast Could be something else entirely. Uh, yeah, I think this is need going to need to go onto the workbench and I use the logic probe on the pins Before doing that, let's just set this back to the ultra slow speed Yeah Could be too slow I'll have to actually figure out what this means And set it to something reasonable But it does feel like it is Writing spi1 w0 That's a write register spi 1w0 Okay, that is the register. It's reading to transfer data. I thought that might be wrong and that should be r0 But you know, let's try that and see what it happens. Right. There is no r0 Hmm Do I need to set the data bit every time? Well, that hasn't helped Yeah, this isn't going to need to go onto the workbench Uh, if I could once I figured out whether data is being sent or received correctly Then I will know where to start looking If data is going out and nothing's coming back then Chances are the clock's not right It might be that the GPIO Chip select line is all wrong It might be that the mappings between the numbers written on the device And the numbers in the documentation is wrong As I said, this is a gray market clone of an existing module So it could be that all the data lines are just in the wrong place Anyway, I think I have been working on this for a while I'm going to call it for this video So the next one should hopefully It might even have some workbench footage in it Actually, no, let's not stop here because I've just remembered a very important fact Which is I own a logic analyzer Which I've hooked up And I've told it to record while the board is doing the thing and this is what I saw Now I should be able to These are the four wires which are in order chip select mozzie clock and miso So This is the This is the The board enabling the sd card to talk to it This is the clock That's not sorry. This is data Going out from the Board to the device and this is the clock The device will sample the data every time the clock toggles Now I should be able to I don't use this very often I should be able to Tell it to decode These four lines by us by telling the sbi decoder. Here we go So clock is d2 master in slave out d3 mozzie is d1 Chip select is d0 So what are we seeing? It can't do much with that here We can see This actually all looks kind of weird to be honest Oh, yes, and we can also add a sd card decoder on top of The spi actually we can get rid of spi because this does it for us So clock is the two Miso is the three mozzie is the one and chip select is d0 So what is this telling us honestly? This is looking kind of like garbage So master out slave in this is where the actual This is where the actual data going out to the card is supposed to be So these are bytes There's nothing here So I sampled this at one megahertz and it was running at its slow clock speed So I should have all the necessary data the fact that this keeps turning on and off is interesting This is the clock so Each of these I would have thought would be a byte If If d0 here is chip select that should not be going on and off at the same speed as the clock So that seemed kind of wrong I wonder whether I actually have the Lines arranged correctly. Let me just double check by looking at the device So in order from top to bottom it should be chip select mozzie s clock And miso but that does not look like Anything sensible this one here d1 This looks like chip select. Well, we can check the pin assignments By doing this So what this will do is it will Toggle GPIO 15 indefinitely. So we should be able to go over here run Stop And what do we see Nothing so either the chip select line is wrong Or our GPIO pins are not hooked up the way we think they are It's quite possible that they are wrong But if I tell this to run How am I going to do this? This is not the most ergonomic position. You can't see any of this which is Nice for me. So if I Touch this to each hope you can hear me if I touch this to each data line in turn Then eventually this is d2 This is d3 Write something on d3 d4 d5 That's gone low. You can see In d0 d7 Again a static low d8 It's high Okay, so this suggests that d2 here d2 d3 d3 D3 is actually the chip select line. This is GPIO 15 Which is not at all what the documentation said it is Yeah The device I've got here is supposed to be a Wemos module with OLED screen uh I think that the expressive ESP module itself is original But the board is not So I think that the data lines are just not hooked up to anything that's sensible So let me let me have a quick look around to see if I can see any better documentation So this appears to be roughly my module and I can see that D3 here is GPIO zero Now I can't remember what pin I said it was Let me try that again hit the run button Right, that's d3 on the board Which is connected to GPIO zero Which is kind of not really what I expect here however, I do kind of notice that This is one shifted left 15 or The last bit of the 16 bit word So if the GPIO pins are in fact labeled backwards So that would be like this Then this might explain what I'm seeing Let's try that Okay, and now we go back to the logic analyzer and we search for activity again. So D8 D7 D6 D5 D4 D3 Lots of noise in D3 D2 D1 D0 So that has actually not changed the What pin the noise came out on so that suggests to me that this is not work anything like the way I think it does Okay, let's go look at once again The Arduino code Now nothing in there. I did actually look at this code before I just can't remember where it is Wiring So we want output or input And you can also set Pull ups and pull downs Yeah So what's a GPF? I believe That this is GPIO flags Yeah, but well pin function So let's so if we're going to use the GPIO stuff rather than the expressive stuff So what we want to do is to say set That bit clear that bit So O is output level which seems to be correct GPIO enable We also got pin control registers So what's the difference between This seems to be setting the mode which Is reasonable This is the pull up our resistor enabling But what we actually want to do is to Figure out how to configure it to be input or output So that's probably a gpc thing. So we see Right that would seem to be enabling the driver. So we say Gpc 15 equals PCI Or Is that going to work okay Now we're over to the logic analyzer and see what's coming out of the pins our old friends d3 we see stuff d2 d1 d0 four five six seven So the chip select line is supposed to be on d8 Which is GPIO 15 Says GPIO 15 And it is the hci chip select line Now there's various different ways of numbering and labeling The pin so it's possible that these GPIO numbers don't match the uh, expressive documentation, but The code here also said that it should be GPIO 15. So I'm wondering if the people who made my board just hooked them up to the wrong place I am curious to know whether I can change the pin So I think if I were to comment these out And try and do GPF pin GPFF bus pin it says I wonder if these are macros at which point we can use them or whether they're not Oops That seems to have worked. No, let's see what happens. Uh, yes p a 266 GPIO to function Is this These are addresses in memory. So we can actually just Copy this And we don't want progmen and oh We should have oh, yeah And we want to include our Peripheral library Okay Okay over to our logic analyzer and look at the pins again one Two three four five seven Eight Okay, well that's doing the same thing which is good Now let's try switching to a different pin uh Let's try pin 14, which should be the clock. So we flash it logic analyzer We still got stuff coming out of d3 five six seven Eight Three okay, so that has not actually changed The pin configuration at all So What's the esp doing to actually set a pin value? So digital write set the value Yeah, there's nothing particularly complex there That's doing exactly what I thought it would be doing. That's what I'm doing So why is this going out to the wrong pin? Is it configuring correctly? Do I need a pull down? Well, it's uh It's an output it shouldn't need a pull down. We might need Open drain mode Or I've got that set Although now I look at it. I do think I got that wrong. So maybe that just needs to be like so Okay Let's see what this does Well, that's pin three and there's noise. That's just me moving the probe around I have to say I do not follow this at all. Well, I don't like to know what these macros do GP ffs bus This is Okay GP ffs here set returns the The appropriate bits for the function. So, uh, if we wanted to hook this up to The To the hsbi unit then we would set it to probably not special Come on. Where is it? For esph 26 wiring digital Then this gets set to Ew interesting. I've got that set to the wrong thing So setting it to bus Actually sets it to the hsbi device We actually want to set it to GPio and that should hook it up to the Uh GPio registers. So now we might see something different. Um, it occurs to me. I am doing this wrong Give me a moment Okay, I remembered that my logic analyzer has actually has eight input channels and the board has eight output Well nine output but not using one of them. So I might as well just hook up all the lines not have to fill with the probes I am seeing that the Noise does seem to be coming out of d4 now 01234 So that could just be because I've hooked them up in the wrong place. It's which is easy to do But it could be because the pin here has changed. So let's just change that to Back to 15 Write it back again and run it and see what's different Nothing So it appears that changing this pin and therefore changing the Which line gets toggled doesn't actually Do anything So my feeling Is that in fact i'm not seeing this Loop toggling the line at all. What's happening is that something else is doing it? Well, that's checkable. See I just changed it again and nothing happened All I need to do is to comment this out Write that back and run it. Yeah Okay, so that was in fact a big red herring But we are seeing that I am not for some reason Setting the state of the output pins tool I just don't know how it works. Let's try This This will toggle all of the pins So we've What does that gpci do? So it is set for both the output modes And the input modes Do I need that? Hang on a second This is Unsetting that field That's just setting it to this. I don't think that did what I wanted No, that did work Nope So I believe that these registers here So gpcd Okay, pin control bits gpcd is Two So that's One Two Four Oh, no, these are bit numbers 012 so that's enabling the driver Setting it to open drain Do they need to be enabled? The output enabled register is plausible gpe set is Turn on that pin Was this different? This is now zero Previously it wasn't You said don't think it was Yes I mean it's not toggling but it's Now Doing something Like what pin 12 supposed to be that should be pin six So if this is One two three four five Uh zero one two three four five six That makes sense But I would expect to see it toggle Which it's not Okay, let's put this in 15 and see if that changes Hmm Gone completely Let's try a different one Well, that one's toggling at a different rate So I think that could be our chip select line So according to This documentation On an ordinary module Uh This should be pin five And I'm seeing that on data line six. Let me see which actual pin that's connected to Okay. Yes, that is connected to pin six Uh The reason why the numbers are wrong is because I actually failed to hook up d0 here. Well the line that should be there So If why did I tell it? No, hang on Pin six is the clock Yes Wait a minute. I said pin six. Didn't I GPIO 14? Pin six No pin seven. Ah, let me look again. Okay. I hooked them up in what hopefully the right order so These should now correspond to actual pin numbers So we see the noise was on d3, which is correct Our new signal is on d5, which is correct So Let's check the other ones we want 12 should be on pin six That's a flash Nothing It's gone. It's gone low, but it's not strobing Pin 13 should be d7 Again Nothing it's gone low chip select should be GPIO 15 15 I said And we're still getting this noise So Honestly, I am very much confused It's just there's still something wrong. Some pins work. Some don't Now I mentioned that the that my board does have a screen attached So it may be that I'm seeing problems because the screen is connected to some of the GPIO pins I don't actually know how the screen is interface. I think it's i2c. It's pretty slow So what pins it's attached to? Let me go and find that bit of source code It is in fact written on the bottom of the board. It's d1 and d2 So none of these should be affected at all So why are we seeing noise on d3? This is peculiar Well, having done some more playing and filling with the logic analyzer I believe that something deeply peculiar is going on So this is the board back in its its old sd writing mode trying to Write to the sd card the sd card's not actually connected, but and I can't help noticing that these here this is the clock And it's in little bursts. I think the bursts are wrong. I think that Each block here is supposed to be a clock signal. If I zoom out here So This is mozzie master out slave in So this is the board trying to send to the sd card and this is it sending an ff It sets this high meaning logic one and then it toggles the clock eight times and then it Resets everything and toggles again toggles back again looking for more data to show up And if we go along here, we can see this change This is the command packet going out so If I find our dev sd sd send command So it sends a Command byte Which is starts out being command zero It then Sends four bytes, which are going to be zero because there's no argument Then it sends a checksum byte And it will in this situation because we're sending command zero So Not sure what this is But this looks like Lots of zeros to me Followed by The checksum byte You see this lines up with this Uh Our byte is nine five followed by Uh attempts to read bytes And then it gives up So i'm not sure why this is Toggling noisily like that Uh actually one thing I should try let's crank up the sample rate Okay, so I need to hit run and then press reset So that's at a much higher sample rate So we can see This is toggling up and down at eight megahertz That's not right. Let's try that again. Shall we? This time it's 16 megahertz increase this Okay, so Okay So this is This looks very odd. This line here d4 would be the chip select line And That's not right And that's not right and uh There's no way that the decoder here can make sense of this given that the clock is so garbled So I wonder is there something wrong with my sd card reader? Well, no, there can't be anything wrong with the sd card reader because the sd card reader is not connected So there must be something not right in the esp itself probably because it's not the pins aren't configured but That seems odd I wonder if what we have here is noise caused by Low voltage or something I wonder if what I should do now is connect it up to an actual oscilloscope to show analog voltages But I'm not surprised it's not working and I have a suspicion wrong file I have a suspicion that initializing all these pins is just not right In some way that I don't really know about this has gone back to the old-fashioned uh System of letting the hsbi unit Own the chip select line Even though it's not documented very well or at all I did go hunting around for more information And mainly what I find is complaints that expressive documentation is terrible and missing huge amounts of stuff Yeah, so I don't know really So I am going to call it here for the day I think there's been quite a lot of work And uh I'll attempt to do some more research before tackling it again Next time and I think that next time unless something shows up I may have to try and use the spi I'm going to use the built-in flash Storage Which is going to be interesting to say the least Oh, well, I hope you enjoyed this video. Please let me know what you think in the comments