 So last time I made a complete dog's breakfast for getting the interrupt system up and running But I did eventually end up with a working system timer While I was offline I did a little bit of cleaning up So it now correctly calculates the clock frequency released probably correctly calculates the clock frequency from the PLL configuration then Calculates the prescale and comparator value, and it all does seem to work I have just restarted the system. We got the mysterious splash screen again. I Believe this is because the system is just powered on and it doesn't contain the various magic numbers that detect a warm boot So I think that's normal and we won't get the splash screen again until I power the machine off But now we've reached the point where Given that we have interrupts working and we can't yet like interact with the thing so I'm going to have to get the Serial port interrupt working because emu tosses interrupt system is entirely Sorry, see emu tosses serial system is entirely interrupted This should Hopefully crossing fingers not be that bad At least not as bad as the timer so Looking up the data sheet at the you art registers We want to enable The you are to create to generate an interrupt on on the appropriate conditions and then we want to enable the interrupt in the Interrupt mask and We also and we want to do this one first Add the interrupt handler vector so to enable the interrupt the You are on this thing actually has a reasonable size FIFO. I think it's 16 bytes could be eight bytes So we could deal with data in batches There are a number of Conditions you can enable We are there is the receiver enable bits Receiver full sends an interrupt when the FIFO is full and any more characters will be dropped that indicates something bad's happened half enable Enables an interrupt when the FIFO is more than half full so if I use this then I Would not get an interrupt until Four or eight characters show up and then I would I would process them all in the chunk I Don't really want to do that because that raises nasty edge cases where if a single Character arrives is it just going to sit around in the FIFO until more show up However, if we do implement this it you end up with much more efficient handling of high bandwidth data however, the Simplest one is this one rx re receiver ready enable Which generates an interrupt when they're the FIFO is not empty. That is it's got at least one byte So that is bits three so Ust couldn't one or equals Enable bit three Okay The next thing is the IMR So let's find the IMR register interrupt mask We want you art one Which is bit two So to enable this We need to Clear the bit Okay, and I will actually just go down to the status register again and check the sense of this bit Yes, that wants to be a one Now back to the interrupt stuff. I did eventually figure out where the documentation for the The interrupt levels for the various hardware which is Inside the documentation for the interrupt status register nowhere else just here So you are one bit to you want one interrupt request when set either you are one module need service This is a level four interrupt so level four We're just gonna do that user four equals Dana and four in fact In fact, I think we can use o x 1 8 for this But let's make this work first And I believe this is all the setup that needs to happen so the next thing is to implement our Dana for interrupt handler, so That should go here So there is an interrupt handler however This is not actually going to read anything from the you are and therefore The interrupt will continue to be asserted forever So we actually need to do some work Now for a normal interrupt handler. We need to Save some registers Let's take a look at the Amiga interrupt handlers Here we go. Amiga interrupt keyboard interrupt is You know that initializing the interrupt here we go So this is saving these registers so let's just do that to D2 a naught a 1 SP and Reading everything Back again is in fact Given that you can use this addressing mode Why have we bothered with an lea here? I don't think we don't need that so we should be able to do that instead Okay, so this should save enough registers to let us do see stuff so the next thing we want to do is To hang on we don't want keyboard. We want serial CIA CIA a serial interrupt Now this point we could call out to see to do the rest of it But I think we don't Need to that is in fact all way too complicated because the the Amiga CIA Serial interrupt is also emulating a keyboard as well as just a serial port So you can see this stuff here about Converting it to a scan code Okay Here we go No, no, that's these again the keyboard handler Okay, then I have to figure out what this is that what we actually need to call Presumably one of the routines in here What we need to do is to read the value from the serial port which actually we can do easily With this let me think so we could just read at the The bytes like this However, I think we do want to check to make sure there is in fact a valid byte available, so if we read the whole thing and then we check bit 13 of it and If it is zero we skip to the end This means that if any stray interrupts show up we won't end up producing garbage serial data and now we want to Is this it I think it is you know But we are going to no wait. That's a static function. Ah, what am I doing? Let's just go look at the cold fire code. It's probably more straightforward. Here we go Right. This is much more straightforward. This is more along the lines of what we want. Ah I know why this code is using an explicit lea and Multi register read and write it's because the cold fire is a cut down 68,000 and doesn't have those addressing modes. So yes, we can do this But this will work too right So this is effectively the same code that we've got here So now we want to go look at the interrupt handler Enable interrupts here we go so While there are no pending data bytes get the byte and This is for the keyboard and this one is for the serial So all we want to do is to push D zero call Push serial iorek. Do I need to pop that value off? I think I probably do So that's going to be Add ql 4 to sp and then branch back to here so that any more data continues to get pushed That should be our serial interrupt handler. Of course, it doesn't work because we need to Prototype it here. We will eventually probably have to deal with multiple different types of Interrupt on the same interrupt vector but We don't have to go there yet, which is nice UST control one is a word I believe 902 909 oh, oh it's Yep, I know what I did there's platform prepend C symbols with an underscore and I just think I should check one thing Do any of these functions? Don't don't think that is used. I just want to make sure I've got the calling convention, right? let's just Enable this because I want to know what size of value gets pushed onto the stack when you pass bytes and the answer is it's a Word which is what I thought okay So build reset Right and let's see what happens rights Execute Okay, apparently if I do control Z, I should get something Maybe not Yeah, I would kind of expect more than this So let's See if there's some tracing we should turn on apparently it's already on there So this is where data actually shows up So let's just make sure that happens okay execute and Bah nothing's showing up Okay That means something somewhere is wrong. It's not really a surprise to anybody. So I Would guess that this interrupt is not being Called for some reason So we're probably setting it up incorrectly, okay USD control one Bit three is rx re receiver ready enable Enables an interrupt when the receiver has at least one data byte in the FIFO Okay, do I need to enable the receiver? Probably not because the download process Process has that and we don't want to fiddle with that configuration as if we Can help it anything else we need don't believe so All right. I am our mask register Bit to is you are one And it needs to be set to a zero which I believe that is doing Vec user for should be the right vector if an interrupt has been generated on the wrong vector as we know before we will probably end up with a Crash or a hang depending what's going on is Bit to you want one interrupt request level four level four So is Dana RS to see to in it being called Well, if in its serial port then yes Don't think I've made any typos there. So that will tell us if anything is being If it's being set up correctly one other thing that might have happened is that There are no drives and therefore it's failed to reach the command prompt due to Being confused because there are no drives Let's just see where that string shows up. Yeah, is it no surprises its routine that Turns an error code into a string. Yeah, I think it is plausible that that has Failed There was a There was a setting I made Which is Which is not there It's it's this So I This might be the thing that causes it to go straight to the Console rather than going to the splash screen. So let's try taking that out and seeing what happens It may be that that value is now no longer initialized So we'll still get the old value if that happens if we get the same thing again, then I Will reset it to zero and see what happens and We write and see what happens Okay, that is Interesting Because we have not actually Did I remember to build? Yeah, I did because we haven't received any more tracing Because I didn't enable it there. That's why But it also hasn't Produce that splash screen. So let's try changing Let's set this to zero and I will actually yeah, we do need to enable this Let's actually figure out where boot flags is used. What's this? Right. This is the splash screen this is This happens after all the init sequence unit sequences there Okay, so we should be able to set it to something in Dana dot c Splash screen. Yeah, it's a thing called init info Which is called from here Based on this flag Do we want to show that possibly? your first boot is It looks at magic numbers in memory So Yeah, let's do this luckily. It's a nice quick build Okay Let's write that and see what happens and when we run it Huh, that's not what I was expecting to happen. However, I do see that it's called our RS 2 through 2 init function So we have As far as I can tell Enabled interrupts So Why hasn't anything happened? Have I got this the wrong way round? That is entirely plausible I spent a lot of time fiddling with this when I was writing DBZ tool. So I've got some handy code Here we want this one Let's try that then shall we Yeah, what that was doing is Skipping the read completely if there was any data So that would have the side effect of clearing the interrupt because the Pfeiffer was being read But then discarding it so we run it and now Still nothing happens That's annoying Also, this was right the first time Because So what this code is doing is? We want it wants to wait until Data is available so it reads the register Checks to see if data is available if it's not available it jumps up to the loop What we want to do here is to see if data is available and if it's not available We break out of the loop and stop fetching data So the only thing I can think of is that this speed test is Assembling to the wrong thing. So let's just check that Doesn't say what size it is let's put that L in Okay, that is in fact the same instruction. So it was right the first time so If for some reason this is not actually reading any data let us do our time on a trick of Just dumping something to the console when The interrupt fires That will give us a little bit more information what's going on. Okay, so what does this do? Nothing interesting so one thing that you can't see is that The serial converter module I'm using for this does actually have a light on it that Blinks whenever data transferred so I can see that Data is actually arriving at the converter module and therefore going to the board so Don't know why that is not firing one thing I should do is Figure out where the serial port is initialized Is it before or after the vectors? I think it is after Because remember the last time the problem I was having with the timer. Yeah Here is where the vectors are initialized. Here is where we were doing our machine Initialization and the serial port is way down here so We know that the vectors aren't going to be fiddled with I wonder if this might have halted disabling Interrupts entirely as it I would expect to get a message if it was panicking like that Because of course if the interrupts are turned off then we won't don't get any interrupts. I want to get that splash screen up and running So why isn't it appearing? So this should be being set to true. Oh It's not this will be because This Command line setting is not being passed through to a hash to find Okay, right, so let's stick that in our config Okay, it's hitting the error Okay, we should get the splash screen now So let's try that So if we run it we now get the splash screen typing. Aha Right that worked And I just accidentally told it to boot from drive a So if I reset the board, I mean everything is still in memory now, so I don't need to run it again I don't need to download it again. Now I can press escape interesting very interesting We get one bite and it dies That a is coming from our tracing here. So let's chop that out we get our So the got 27 comes from push serial iorek. I Am still not convinced about This I Want to double check that I need to find a nice simple Example of passing a single parameter this might do it. Ah, yes Yeah, I So this is is passing a is pushing a word onto the stack It then calls the subroutine and then retracts over the word. It just pushed onto the stack but what I am doing wrong is I Am expecting that everything is a four byte integer Which it's not So what that is doing is moving the stack too far. This then jumps into garbage and the system crashes So we build yep, that's done reset Right and with luck it should now be Closer to the state of nearly working Right, so what do we got? Sprout screen escaped to run the console. Nothing's happened, but at least now we are getting oh I Yes, so we got serial input until I told it to boot and then it died good Serial stuff is I believe working It's a shame that we're not actually Getting to a prompt Probably because we don't have to drive well, I Think I'm going to call the serial stuff done and I think we now need to start looking at drives This I was not really looking forward to We need to Get the MMC and SD card module Working, I'm just going to just remove the tracing Actually, let me I Want to check stuff in now? so So that's just to turn off the various bits of tracing We can leave that one Leave that one. All right and Now let's move on to the SD card stuff So I did a bit of pre-work for this. So the first thing we want to do is to actually enable the SD module I believe is called SD SD MMC comp with SD MMC really so When we build this It fails because the low-level SBI code that actually Sends and receives data Have not been implemented. This is not actually particularly complicated. So we can look at Look for an example You go This is the cold fire version of the code Which is just setting a few registers Sets up the Sets the clock speeds to various values. There's three different speeds. We want to use a Certain unassert the chip select line Send and receive bytes. That's it 155 lines quite a lot of which is boilerplate However, the SD card stuff on this device is a bit of a mystery. It's not the The actual module Because that is well enough documented This system on a chip has got two SBI interfaces one and two Two is much simpler than one It's the fact that we don't know what else is wired up to where so over here, I have Ghidra again with the palm off Rom in it and I Did some poking around To make an SD card work There are three things you need you need to power it and this could be as simple as just connecting the power line up to the 34 of the power pin on the SD card up to the 3.3 volt line You need to select it which is done by asserting a chip select pin Which there is code here for doing and then you need to read and write data This device has hardware for doing the reading and writing of data But the chip select stuff I think is done by just setting and un-setting Various bits on various ports. So this is the chip select code decompiled and We can see here that that parameter appears to be the What drive you you want? this parameter appears to be as far as I can tell what drive is currently asserted No, it's not That parameter appears to be whether you want it selected or not and then it just Sets or unsets particular bits and I think that the first SD card slot is on PJ here And the second is on PF here So there's not actually very much of this code Can I change the type of this something more? useful retype to So what's this doing drive times 380? Where are these registers? Nowhere near 380. Yeah, I think that's not relevant. So it should just be a matter of Configuring the unit setting the appropriate bits, and then it works however The parmos SPI code is absurdly complicated It also sports SD IO and it's got stuff in it like this, which is doing a whole pile of things So I don't know what else is going on. It also appears the second SPI interface is In use as well for something else So I think we're just going to have to suck it and see so Hmm Anyway, as there's not a lot of code. Let's just stick it in here So what have we got in the way of functions we need to implement SPI initialize at least it's not interrupt based which is nice And the other thing is the emu task does actually have all the SD card driver Hi, yeah a high-level stuff. So all we need to worry about is sending and receiving bytes on the interface It's worth pointing out that emu task seems to only support a single SD card interface, and we have two So I'm just going to make the first one work now. Hopefully and I'll try to add support for the second one later that will involve some core changes So I don't want to get that mixed up with the rest of this code Okay, so we now have Stubbed versions of all the SPI stuff Okay, I think the easiest part is actually the send byte and receive byte things Because this is just a matter of writing to the appropriate register. So this should just be Only a little bit more than this but Receiving register is rxd Like you know that simple Again, this has a pretty big FIFO so we can keep receiving bytes without We can send and receive bytes and chunks but again I am going to avoid doing any of that because that seems like work So we also want to check to see whether Data is actually available This doesn't appear to be in the control register. This is the interrupt stuff. Here we go Rx FIFO data ready bit 3 so SPI in CS When set one data word is ready. So while this is not set spin Likewise sending bytes While the FIFO is not so while the FIFO is full which is bit to Spin so this will wait until there's space in the outgoing FIFO for a byte and This will wait until There is data in the incoming FIFO Right and this will fail to build because we haven't set the register values up here SPI in CS is a word at 706 SPI Rxd is a byte that's 700 and SPI Txd is a byte at 702 Okay, and if we look at the Code that there should be very little of it receive byte read register That's interesting. I didn't know you could do that test for zero branch That's that's quite cunning These two bits happen to correspond to particular bits in the condition code so It's managing So it's loading the entire value into the condition code register and then using the branch that Branches on the particular bit So bit two here is the Z bit so it does a branch if equal bit three here is the P bit so it does a branch if A positive I think that's what it means Parity I don't know it doesn't really matter Okay, interesting right next CS a certain unassert well we have code Here for doing it So assuming that the first parameter here is the actual drive Then the bit we want is in PJ So we should just be able to copy this piece of code intact Although we can do better than eight and this will therefore be that now I'm hoping that Yes, we need to Figure out what PJ is PJ data is For three nine and it's a bite, okay, and Now this is interesting PJ is associated with various hardware modules on board so This is in fact where the SPI one is wired up and by the looks of it you are to so the Our bit here is SS However, the fact that we are setting that bit indicates it's being configured as a GPIO general purpose Pin rather than SS But it's not to three of controls signals associated with SPI one SPI one signals SS Uh slave select bi-directional signal Output in master mode input in slave mode That is in fact the chip select line But this seems to be doing it manually So the second drive is on PF so What's PF is PF associated with any specific hardware? Yes, it is That's bit to Clock oh Yeah, that that is obviously not being used by this so it is set to a data bit so I Let's take a look at PJ again because I need to make sure that PJ is correctly set as a As An output pin As an output GPIO pin so PJ dear and PJ cell are the ones we want and possibly PJ UN and for the pull-up Register now I did copy a lot of initialization code into my Dana init script here So we can see here that PJ cell is being set to Cf Which we go C is 1100 f is one one one one So most of these being used as IO port function pins But I don't know whether they get reassigned elsewhere in the ROM. So let's go and look at that okay, so PJ cell is this register and it is being Written here. This is the init code that I copied so here you can see Being set to CF and then it's been read and written in quite a lot of other places. So What is this routine? Ah ha? Hardware SPI open That's yes, I did name it, but these trap instructions are confusing Gidra. So Here it's fiddling with PD and Here pf and PJ You see one of the things I'm a little bit concerned about is power If the SD cards power pin is connected directly to the 3.3 volt rail then everything's fine insert card card goes on But it's possible that this being a battery operated device. It's actually Connected to a transistor somewhere and that transistor is controlled by a IO pin So this could be powering on the card. So this is Clearing the bottom 4-bit PD and If I remember correctly zero means Our internal dedicated function pins. So what are the bottom 4 4 bits do? Interrupts so this is setting an interrupt on for GPIO pins, I wonder if that's supposed to generate a Wait, I think I know what this is This thing supports SDIO cards and I believe SDIO cards have an interrupt line So I think that the those interrupt lines are then routed on to the Processor probably through here. I don't think we need to care about them, but this is setting a Register I haven't looked up yet f3o e 3o D F3o e is not a Yeah F3o C is I is ISR Which is here. So in fact if I tell this this is a 32 bit value then I said a 32 bit value right and then that then produces the right thing So I am going to guess what's this doing 314? I LCR She's a 16 bit register So I'm going to guess I don't need to touch any of that. So I think that this is my initialization code So let's copy that and Splat that in here So This is clearing the bottom two bits. What do the bottom two pits do? It also helps if I click on the appropriate thing Here we go Mozi and my so right those are the data lines for the SPI interface Master out slave in and master in slave out. I would also expect it to be wanting to set Data bit to is the clock line I would expect that to be cleared to be honest and I would then expect it to be explicitly setting the Top bit so where else is this being used? What's this? This also looks like Initialization code Proof SPI bus awake There seem to be in in the power master on several different things Several bit different bits of codes that do the same thing, but honestly this looks clearer and more correct So you see this is clear no, I'm on PJ cell. This is Setting the bottom four bits Turning them into GPIOs PJ data or equals eight is then setting the top bit which is chip select That is actually Unasserting the chip select line. Oh wait, there's more here So this is setting the bottom three bits Then it sets the top the bottom four bits Yes, I am not I don't know what that's doing. I think what I'm gonna do is make some Slightly educated guesses This is looks like very similar code It is in fact the same code. It's this one yet more initialization code Proof SPI bus asleep So I think this is power up and power down code and It's turning off the SPI system. I think what we need to do is to Basically try it and see make some educated guesses about how things are supposed to work So I think that these need to be these three bits here need to be set to A dedicated IO which is in the select register. It's a zero and SS here needs to be a GPIO so so this We want to make sure the SPI clock is Zero so we want to be sure that the chip select line is zero before we do this to avoid accidentally enabling the device You want to make sure that the Direction of this is Out that's a one and that is resetting the Resetting the pull-up register on our three SPI pins and now we need to define these things PJ D cell is There is no PJ D cell PJ dear is 438 PJ data is 439 PJ Pughan is 438 and PJ cell is 4 3b Okay So that should be the pins initialize now we need to initialize the SPI system itself So that is the control register So let's go back to here find SPI cont one Which as you can see There's a lot of stuff going on sadly a lot of this seems to be because This is pretty complex That their SPI code is pretty complex so This is this is our sleep function so The this will actually be turning off the SPI system. What's this? Hardware SPI exchange safe synchronous 8 by RX Now one of the things that concerns me a little is I looked up the errata for this chip and There's quite a lot of SPI errata So this is writing ffs to the Transmit FIFO Yeah And then it reads in eight values from the receive FIFO I know what's going on here. This is because in order to do an SPI receive You have to write an FF. These are all as convert these are all Ffs and The device will respond With its return parameter, so I bet that's what's going on there. Oh, what's this one? Hardware SPI clock. They haven't even started working on the clock yet So I think we'll need this code. All right, and oh, there's there's lots Fabulous. Okay. What's this one? Hardware SPI exchange size Okay, this is good. These are all configuring various parts of the SPI system Yeah Okay, let's go back to here and take a look at that clock code. So that's what we're going to have to do next So the SPI clock is a line that Alternates and one bit is transferred every time it pulses there are three different clock rates that it can operate at which is represented here in Identification mode which is dead slow and all SPI devices support that and then MMC and SD card modes which are faster different speeds the idea is you set it to the ident mode which I think is 25 kilohertz and Then you can talk to the device and figure out what it is and whether it is in fact a SD card And then you crank the clock speed up if we look at the this So here are here. It's defining all the timings for the different speeds So that's going to be you know fun Yeah, it looks like the cold fires SPI stuff. You can set various configurations, which it's doing here and Then tell it which one you want to use but I don't think ours does that So this is the data rate and you know Let's move this stuff up here So that's now going to set it's going to calculate the clock frequency on startup and then we can use it elsewhere so 33 mega 25 kilohertz is Slower than that Okay, well, we can set lots of this stuff anyway because they're obvious. So Let's do that here Clock we're going to ignore for the time being Data ready. I don't know about SPI mode we want to turn it. We want it to be in master mode because it's controlling the transfer So that is bit 10 SPI enable we want to be on bit 9 exchange Incept while the exchange is in progress or SPI one So this appears to tell the SPI system in order to actually transfer data. It doesn't happen automatically when you put stuff into the FIFO so On startup it's going to be idle, but I think that here We need to set that bit It's bit 8 Polarity select. I don't know about waveform select I believe is ignored because the the SS signal is not being used phase I don't know about Polarity actually these both come from the SD card standard So we can look this up and bit count as the number of bits per Transfer which is 8 so Should be able to Look at this code This is actually disabling the five foes and not using them. Ah, here are the speeds Right 400 kilohertz for identification mode not 25. That's better so So we want to Mask off the top three bits so that's one And or in the appropriate clock rate so for 400 kilohertz we want 80 80 is not a Valid value here, so the closest I think is 64 which gives us 500 kilohertz Likewise MMC speed is 20 megahertz 26 is 1.6 Right the fastest we can go is divided by 4 Which is 8 megahertz so that's straightforward 8 megahertz like that and again the same thing for the SD card Because we can't go up to 25 megahertz Right and we need to define We need to rename sys-cont1 To svi-cont1 Because that was a typo Then we need to define the register 704 okay But we're still not ready because we need to set the other parameters What's the polarity stuff does not actually appear to be here? Okay, so let's take a look at The vampire version to see if it says anything in here Nope, nothing there. Ah here are the speeds used for the vampire, so All these speeds are kind of variable Okay, I'm going to have to go look this up However, there is one more thing we need to do which is that in order to receive a bite we need to Send an FF bite Which we're just going to do like this and then the Then assuming this works reasonably sanely The result will be clocked into the receive FIFO as this goes out. Let me just take a look at the Overview doesn't say much to be honest Okay, I am going to look up the bang on a second So this should be being set Somewhere in here like here This is supposed to be setting the clock speed And it's one of these loops that we saw to Presumably determine what the appropriate value should be And this is basically the same code that I've got. What's about here? Right, this is setting This is setting the uh the transfer bit to tell it to actually start an exchange Yeah, here you can see it it it writes a ff to the transmit FIFO It Engages the transfer Then it keeps testing Until the exchange stops And then it reads the data out of the FIFO. I think that's similar to our code here And we will try it and see Uh I'm looking for the unit code again. So this is clearing D is 1 1 0 1 So that's 1 1 0 1 That is Disabling the spi unit Because the system's going to sleep. So I would expect the next function to be hardware wake to be honest Yeah, but it hasn't been disassembled. I still haven't figured out what all these traps actually do which is annoying And also it doesn't appear to have touched the SPI registers This appears to be power off which is useful to know about Yeah, I am going to have to go look that up. So for SD cards, you want the uh the clocked idle low which is polarity zero And the output sampled on the leading edge, which is phase zero So in fact setting these two bits to zero does the right thing. So that's all we need So I think we're probably good to go I've also plugged cards into Both slots Let's actually Turn on tracing in The SD card module and Yeah, okay. Yeah, so reset the board. Let me do a write. Let me run it and see what happens Okay, so we run it. I'm going to be honest. I fully expect this not to work so We did indeed see uh Tracing appear in that it was failing to talk to the card slots I actually think I now want to Disable this thing because it's clearing the screen and that's meaning that I can't see the tracing And let's fix those warnings See operator precedence is weird And honestly not worth learning Instead you just put parentheses everywhere where it's not completely clear Okay, let's try that again Right What have we seen? Uh lots of failures See, I can't quite tell from the tracing whether it's actually successfully identified the card There's not a lot of tracing here This command naught failed does Look like it's bailed out immediately Command naught doesn't cause a switch Probably no card. Yeah, okay Uh Right it should show it should tell me that the card's been detected SD receive data Is here right So this is just plainly not working. It's not contacting the card. Um Now this could be wrong Like backwards, uh the chip select line See I did think that was active low So Enabling it does on least on the arduino enable it enabling it does appear to be clearing that bit Wait a minute. I think that is backwards. Okay, right Okay, so now what happens? Well, that's annoying hope that would be an easy fix So So I am now wondering about power Really the next thing to do is to hook up the SD card pins to a logic analyzer Um, and that will show precisely what's going on Also, that number is wrong It's 15 to 13. This should be a 13 So that won't have been That will have been setting way too fast to clock speed for identification mode the It's possible that the card will still respond to that speed, but I have found that they kind they're kind of picky It may even want this to Be even slower 64 masquerading that's wrong That should be four That didn't help for a start So now when we run it what happens Still nothing That's annoying. I'm also I also don't know whether this is the this chip select line is connected up directly or whether it's via a inverter so drives the output signal is high when Oh, right. Yeah, this is both input and output. So the yes the a bit of one produces a high value so So this appears to be disabling the charger Which is also on port j. Although it's not a bit we care about Now I get the charge. Oh, this is something we're going to want to get the battery percentage There's a quite a lot of code there actually It goes maths charger off read battery level Initialized battery. Yeah, there's all battery stuff So this is where the this is one of the functions that claims to initialize the spi stuff So we can see it clearing the bottom three bits setting The top bit of the bottom word to an ioport enabling it disabling the you are the Pull up registers We should probably I think clear the Wait a minute f7 Uh, that is only clearing the chip select line So that's in fact setting it to off not on So let's try that And again, this is yeah, I was I was getting my seven confused with a three here seven means all but the top bit three mean I'm getting my seven and my eight mixed up seven is all about the top bit eight is the top bit only and when there's a an and in the mix where this is specifying which bits to preserve And or is specifying which bits to set It's easy to get them mixed up I think this code down here is more to do with the second spi interface. What function is this? Proof set poll zero prove spi set poll zero pd poll The polarity register Set the input signal polarity of the interrupts. All right This was the this is more to do with the interrupt handling and I remember saying that Some of the bits of port d are I think to do with the Sdio interrupt handling So this is the code as I thought was Doing the chip select stuff so pj if The second parameter is false Then set the bit Otherwise clear the bit Yeah, so clearing the bit is unasserting it assuming. This is any sensible way around. So I think that this is correct Uh, where has this been called from? This function is mislabeled hardware sb and cs set tunnel h Okay, this thinks it's a thunk, which means a function that calls another function Can I persuade it? It's not. Well, I can change the name there, which is just as good. Okay And it appears to be called from Well, spi close is probably going to D assert The Drive so That is indeed It's pushing a zero and Then pushing these three See, I wonder if that second parameter is not in fact a bool. So let's change that To a word that is clearly garbage It does it feel better if it's a bite Maybe Uh, so this means that there's a parameter being passed into Hardware sbi close that it doesn't know about It's this d3 value that comes from Ah, it's this zero here Why is this setting zero to d3 twice? And why does this think it's coming off the stack? Ah, right. This is writing the value onto the stack So we know it's a word because of this. Okay So that is in fact a word so Yeah, but this code down here Is Assuming it's a bite. It's just interested in the bottom bite of it So, yeah, I think that is a bite after all And there's something Not quite right here You see this is not taking any parameters Who's calling sbi close? Unknown it's going through a jump table Blast so We are pushing A bite value and a word value in that order So the word value is in fact the lower of the two In memory It'd be this and this either one is Uh, it's clearly a block of data that describes the drive status and it It's probably checking to see if it's already been asserted And then it's returning Something Okay, that's not getting anywhere Um, I have made some changes So let's just try this again I doubt it will make a difference Okay, so we execute it and yeah, it is failing in the same way as before interesting Do we have something wrong in this code? Are we failing to send data correctly? Let's double check that sbi in cs so bit two Is tf tx-pho full With bit when set indicates there are eight data words in the pfifo. We want to wait until it is empty So while that bit is set do nothing and then set the transmit register value and Tell it to begin an exchange that seems Reasonable when we receive We send the byte And then we wait until bit three data ready Is one And then return the value. All right I think I am going to have to take the lid off this thing to expose the pcb And hook up the logic analyzer Because the parmos rom doesn't contain Uh enough easily copyable pieces of code There is a test register that tells you how much is in How full the pfifos are have I correctly told it? It's an 8-bit device from tx-pho to the shift register the the The transmit register is an 8-bit register Data returns the register can meet 8 bit or 16 bit size the number of bits to be shifted out It's determined by the bit count setting in the spi status control register in slave mode if no data is loaded writes are ignored while spi enable is clear I think this documentation could be wrong and this is actually a 16-bit register So should I be writing to Red address 703 You know I'm just going to try this because the This code They're always reading and writing using word Accessors So let's just try that Okay And again nothing All right I am going to pause and take this thing apart So unfortunately, I seem to have lost my logic analyzer It is tiny and looks like a usb key So it's probably some under something on my desk. So That's not helpful. However, I did take the opportunity since the lid was open to do some Trace following and I discovered a number of interesting things one of which is That the power lines are not connected directly to the 3.3 power rail In fact, they appear to go to a transistor which is then connected to Additional ports on the system. So as I thought it does appear to be explicitly powering on the card and Looking at the pinout. This seems to be connected to PB5 That is Bit 5 of port b and if I Find that that is this one and over here In the disassembly in the private spi bus awake Function I can indeed see it fiddling with Port b So I think this is powering on the card. So let us simply copy this over To our spi initialize like so and of course this won't build because I need to add all the various ports PB data is 409 Dear is 408 PB Ewan is 408 PB cell is 408 B Okay, so with luck that should power on the card and PB P Port b P Ewan So we'll see what this does and of course now the lids off. I can actually check the voltages That's interesting My terminal up here has Failed, okay That is plugged in. Oh, I actually forgot to plug in the Dana itself be right back Okay, I have uploaded the binary and run And of course, it's not working And because I powered off the machine we now get this So let's try and boot from okay, it booted automatically All right, uh, I'm going to check the various power voltages and see if the card is powered up Yes, it is. Uh, the correct card is well one of the cards is powered up and Let me think I think that is in fact the incorrect card is powered up Because of course, I have flipped the I flipped the machine over to get at the bottom So the card on the left is powered up But I think my chip select line is pointing at the card on the right. That was So I think pj is the one on the left And pf was the well pj was Okay, I am completely got my cards mixed up, but I think Surely I do not need to know which card is which I just need to make sure that my Power on bits and my chip select bits are the right ones and this is indeed Here are all the pj bits and here are the pb bits So I think that's right Is the chip select the right way round? Well when we assert it to be bring it low and when we unassert it to be bring it high And I can indeed see that it is high Is there anything more that needs to be set in the Control register Well, let's have a quick look so data rate Is set here Data ready. I don't believe we care mode select Is master enable No exchange Polarity low Well, that's polarity of ss that we're not using so we don't care Waveform select ss. We don't care We could connect this up to the chip select line That I believe is what it's for But of course it will only connect it to one of the cards phase and polarity Zero active high polarity zero is idle Is that correct? clock polarity The clock idles low And the output is sampled in the leading edge. Yeah, okay. So the clock is active high And the only other thing remaining is the bit count which should be Eight over here. I have yet to find anybody who's actually Setting sbi con't outright That's the wrong control register that is con't two we want con't one as I suspect That's interesting. I did did I define sbi con't one? Have I been looking at sbi con't two the whole time? Why is pb data here at 703? con't one is at 704, which is here Okay odd I must have accidentally overwritten that somewhere Okay, that looks more like it This is the code that Modifies the clock So you can see it read the old value mask it Or in the new value And write it back again With interrupts off we should probably be doing that This one that starts a command That starts a command Starts a command All starting of commands that when we looked at this one Start to command you all start commands This is Unsetting some bits. What is this? This is the wake up. No, it's the sleep routine. So Yeah, I looked at this before 1101 it's unsetting the enable bit Again, I would expect that hardware awake Which Is less easily found Should be setting that but it doesn't be But I remember that doesn't seem to be hardware wake Is that That is Incorrectly named Ah, no, no this function starts here This is correctly named prove wake up in handler This is Hardware wake So Are there any references as I can see to The spi stuff. Well, unless it's in here That looks spi-ish This also doesn't have any um Symbol names So I think that means it's all logically part of This I think these names refer to modules. So I think this is doing something Like that But that setting up the second spi device, which we don't care about I think that's it really Somebody should be initializing this And one thing I can do is to grope through memory and look for f704 And it will be aligned. So Here's a reference I don't think this might not be code That's does not look like code Fortunately because instructions on the 68 000 variable length Finding the beginning of instruction isn't entirely obvious That does look like code So This looks like lots of spi code Let's see if I can find the top here it is That was my multimeter turning itself off Here is quite a lot of this function. I have to say I think that's data It does look like code It is referred to as Data labels and still there's no sign of a symbol at the end A jump table I think this could be a complicated sdio driver of some description Because that that would explain why it's all seems to be compiled into a single module This is a lot of different sub-routines all Glumped together and they should eventually Be a name that Describes it. I did spend some time going through looking for The trap handler and it's all indirected through Stuff that's not code Which makes it here we go That's a that's not a symbol name It's all indirected through vectors that make it very hard to trace So I haven't been able to figure out what any of these system calls actually do I think this is all ebook reader stuff to be honest um But we can see that it is What's this Doing uh load the interrupt handler Shift it left and write it back again That makes No earthly sense It's possible that what I have here is not code and it's just Very code like garbage Yeah, this is doing the same thing but spi can't Uh, it could be that the uh That gidra has it tries to infer the values of registers. So it thinks that this is A It thinks that a five has the right value to be Uh referring to that register and if it's got that wrong for some reason which it might do A five has been used in a lot of places Yeah, I think a five is actually the global's pointer for the workspace for this particular module and that is a completely spurious Uh, and that's not actually valid likewise there likewise there. Yeah, that hasn't helped Okay, I am Well, we've powered on the card And I think I'm doing the chip select stuff, right? so I really am going to need the logic analyzer for this bit So I suppose I'll just go and have to have another look It was on my desk the whole time Anyway, I found it. I plugged it in. I've wired it up. I have an image downloaded and ready to go So let's Hit the run button and execute And stop and what do we have? Well I'm just trying to remember what everything is hooked up as So d zero is me so Master in slave out. This is the response from the Card So we are getting something Not quite sure why d1 is the clock. Let's Rename some of these So this is when the The machine is trying to talk to the card it Runs the clock obviously enough Right d2 is Right the orange wire is connected to c s Which shows up as red in this of course That is wrong c s should be Is that wrong? So c s starts its life as low We see it go high Uh, we then see it go low again, which should enable the card The card is then and then this one of course is Mozi master out slave in so this is the Machine talking to the card and this is the response coming back So it does look like We're getting something out of the card so for a start I think we want This I think we want c s to be high to to begin with Then it will be brought low when the When we want to talk to the card And then brought high again once we finished Uh, if I zoom out you can see Here it gives up brings it high Uh, and then has another go now I will Turn off some of the things I'm not using to make the screen a bit more clean And let's try and add a decoder sd card spi mode And it will auto detect things because of the names I gave it So here we should be able to see what's actually happening as windows too small so Right card select goes high And then we see Mozi data uh Really See I would expect 7f 928000 Oh, too That looks like garbage to be honest Now it might be a low resolution in the capture, but We've got Reasonable We've got a number of data points per clock tick It's detected all the lines properly Chip select is active low So if we go and look at the sd card code So this is Where it's initializing the sd card You can see here it unasserts the chip select line And then we spam bytes and then assert it That will Reset the Card we then send a command With Not sure what that is we should see it in the data stream So it could be this It's unasserted But then nothing happens for a bit and then it's asserted and then things start happening 74 dummy clocks with cs high You see this does not look like 74 clocks to be honest We are seeing that the Clock rate Is Is that anything resembling? Oh, no, that's not the clock rate. That's the length of the Area I have selected So Let's add another decoder. We should be able to do Frequency Hello, how do I add it? Oh, it's showing up Okay, so I need to assign s clock and we can see 250 kilohertz Which is eventually what I ended up with so the clock looks right So I wonder whether these transfers are Garbage I think I'm going to rerun it Now that I've changed the sense of this So I have set this I have set gpio 3 to be A gpio not the internal clock so that should be okay Okay, well Let's try this again at a higher frequency And at a higher sample rate rather and see what comes out Okay, so Execute we'll prepare for execution run Hang on two megahertz Run go right. What did we get? cs goes high That doesn't look like a good waveform. I have actually had problems with with this before With trying to signal analyze sd card traffic And I was seeing very much the same sort of thing. So I wonder if my incredibly cheap and nasty uh Signal analyzer is in fact doing bad job So it's it has decoded a command, but the card is is clearly Garbage and the card is Oh, that that's bad that looks that looks like it's replying, but it really isn't so This reminds me very much of the problems I was having with Trying to get the sd card to work on phusics with the pico ESP 8266 And I can't remember what the actual solution was it was all a little while ago This doesn't look at all Right, I mean what we should be seeing is Uh a command zero followed by Let me see command zero does not have the value zero Now this is the ghastly state machine for initializing sd cards So command zero is in fact zero The argument is zero and the crc is 94. So we should see zeros in the 94 Are we nope? So it's failing. It's refusing to decode that at all. I turned ship select off to Make it a bit more promiscuous, but not working Flipping the bit order doesn't Do anything useful Okay, well honestly, I think I've done enough for today and I need to go and do some research by which I mean I need to go and go through my old videos to figure out How I got round the similar looking problem last time Because I think it might be the same problem this time If all else fails, we could just bit bang the sd card interface all these things are Showing up on pins that we can convert to GPIOs, but that shouldn't be necessary Yeah, I am puzzled So we can get rid of that because we don't need it anymore Okay, uh, I'm going to go do some more research and then Come back next time with hopefully a solution. Yeah, these two Sessions have not been that productive to be honest Anyway, I hope you've enjoyed this video and please let me know in what you think in the comments