Jump to content
  • 0

PMOD SD


927465

Question

I have a PMOD SD card and have been trying to follow the tutorial https://reference.digilentinc.com/learn/programmable-logic/tutorials/pmod-ips/start to run the example code.

I'm using a ZEDboard. I'm reasonably proficient with Vivado and SDK but I'm struggling to see why I get an error that stops me building/running the code.

So I have a zynq based design but the BSP creates code that has "microblaze_sleep.h" included, SDK then complains that it doesn't know what this is?

Can anyone provide some advice?

Link to comment
Share on other sites

25 answers to this question

Recommended Posts

Yes, the PS SD ports are turned off. I'm not touching the Pmod SD IP core sdk code (never have).

Yes I'm using the board files from your link.

I attach the sdk code I'm using.

I'm primarily using Vivado 2018.1, but have been trying 2015.4 and 2016.4 all without succesfully debugging.

I also attach a dropbox link of a zip of my vivado project. https://www.dropbox.com/sh/atcvogm7peyglg3/AAB9FrSY9YtRn8tL1HVuzcfTa?dl=0

I do have a variety of other viado sd card projects(ie using the xilffs on the PS to drive the digilent sd pmod card) on different PC's that are all seeming to have this debugging problem? But it seems this isn't a common problem (based on there being very little on the internet about this). Also note I'm running on Windows 10.

Also note I have been using the Avnet minized board - So I have been wondering about whether the FTDI drivers for the JTAG debugger/Serial port on the minized are messing everything up.

I'm reaching breaking point on this, so would be extremely grateful for your help on this problem.

 

 

main.cc

Link to comment
Share on other sites

Just another note.

1) I setup my minized to run my code on the onboard emmc using SDIO1 this worked fine.

2) I then used the emio to connect the pmod sd card to PMOD 1. Using the pmod board pullups, and just the pmod pins and iostandard of 3V3 setup in the xdc. It falls over, although interestingly the code fails later i.e it gets the bus speed fine, it then changes the bus speed(CMD6) of the card- (Not sure about this bit of the code), then it updates the block size Status = XSdPs_CmdTransfer(InstancePtr, CMD16, BlkSize, 0U); - 512 bytes and it comes back with a status of 2??? It should come back with a status of 0.

Does anyone know what effect if any the config.HasEMIO value has? I haven't quite figured out the mechanism of how it gets from the xparameters.h to the xsdps.c but I'm sure this was correctly set to 1 for the zedboard design? It doesn't appear to matter??? all knowledge and help greatly received.

So know I'm in the process of tabulating all the stages for various incarnation of design to see if I can figure out why I still can't get it to work.

Link to comment
Share on other sites

just a further update:

Going through 1) above I realised the CMD line communication is vastly different. I also noted device ID gets set a specific number when working as opposed to zero when not working.

2) I tried a different pmod and got exactly the same behaviour. Also tried a variety of options of pullups and the behaviour did change slightly but still wouldn't work.

So now I have changed tack a little and will use my minized to run my design to the eMMC on board using the PS SDIO1, then I will run it on the SD card using EMIO and see what behaviour I get.

Link to comment
Share on other sites

I have tried with and without pullups(both physically on the board or on the fpga via the xdc) Although I didn't have my simplified code so I can't be sure it was failing in the same manner. Also the PS SDIO doesn't use pullups and I had read on other forums that they shouldn't be pulled up. The latest incarnation has the cmd line pulled up only via the xdc. Largely because nothing happened on that line when it wasn't pulled up and also on the zedboard there is a resistor pullup on the cmd line between the card socket and the level translator for the PS connected SD card(which works).

I have seen that spec before, which in my opinion isn't that easy to read or in a sensible order, so I was hoping there was something clearer. (Having said that after reading your document and your comments on this thread/post I understand the whole process better) I was assuming that the full spec, that you pay for, might be better. p.s. "CMD6 mode 0 is used to query which functions the card supports, and to identify the maximum current/power..." - It looks like it can be used to read the card bus speed.

 

So I think my plan going forward is:

1) Go through my simplified code with the PS SDIO and see where I get different behaviour. Then see if that points to anything.

2) Change the design to use a different pmod. See what that shows.

3) Create and ILA design for both the pmod version and the PS SDIO version and compare them.

Link to comment
Share on other sites

@927465,

You shouldn't need to constrain any clock outputs, unless the design uses them in an always @(posedge o_SCK) statement or so such.

As I recall, the pull-ups are *REQUIRED*.  That may well be why you are failing when you are.  You might be able to enable them in your FPGA.  That might help.

A quick google search turned up this specification.  Looks like an updated version of what I'm using, so I'll start using it myself.

Dan

Link to comment
Share on other sites

Thanks so much for your prompt response!! Just numbering things so that I can keep track.

1)No I don't have a SD Card spec, can you point me in the right direction of using the simplified specs or getting the full spec?

2) "Shouldn't there be a CMD1 issued between steps 10 and 11?  (I'm following my own script from here, p6.)" - I don't really know what should happen but the code in the xilinx xsdps.c just goes from CMD0 then CMD8??

3) Thanks for confirming all interaction is on the cmd line prior to reading and writing.

4) "CMD6 is not a valid command.  ACMD6 is.  However, the ACMD commands need to be preceeded by a CMD55 in order to get access to them" - Again all the initialisation code comes directly from xilinx xsdps.c and xsdps_options.c??

5) After the CMD6 the StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET); is 0x00008000. XSDPS_INTR_ERR_MASK is also 0x00008000 hence not 0x00000000 so it returns XST_FAILURE.

6) I've attached my xdc file as it is at the moment, its not how I started but just my latest attempt. zedbrd_sdio_ps_pmod.xdc.

7) I have no pullups on my pmod card(I desoldered them to initially see if that helped, it didn't)

8. I will run it on another pmod port to see if that helps(I should have tried that before)

9) It will probably be tomorrow before I get back to you. I had started an ILA design and was struggling to figure out how to get the IO buffers on the 3 state pins e.g. CMD_O, CMD_T and CMD_I? - I'll put this to the side to try things at this level.

10) I haven't constrained the SDIO0 clock which is connected directly to SDIO_CLK_FB.

 

Link to comment
Share on other sites

Some notes from reading through this ..

You do have a copy of the SD card spec, right?  It'll help to understand all of those CMD's.

Ok, looking through the spec, if DAT1 isn't otherwise being used, it can be used as an interrupt output in SDIO, so DAT1 low can make sense.  DAT2 when unused can be used as a "Read Wait" signal in SDIO mode.

Shouldn't there be a CMD1 issued between steps 10 and 11?  (I'm following my own script from here, p6.)

There's a loop around your steps 12 (CMD55) and 13 (CMD41).  This is appropriate--to wait for the card to initialize.

CMD2 is useful for reading the CID register, something I skip in my sequence but okay.  You should be able to plug your card into any Linux O/S device and read the CID register as well--I think you can get it from the sysfs filesystem.  This becomes a nice check that you've read the right value.

Ok, got to the end.  Some observations:

  • Up until you start reading or writing, all interaction will take place (for SDIO that is) on the CMD line.  This includes both transmit to the device as well as receive from it.  It is a bi-directional inout wire from that standpoint.
  • CMD6 is not a valid command.  ACMD6 is.  However, the ACMD commands need to be preceeded by a CMD55 in order to get access to them
  • Can you read the error response coming back from the card at all?

Sounds like a pin might not be acting like it should be.  (This is a very wild guess)  Can you double check your XDC file?  Or try a different PMod port and see if anything changes?

Dan

 

 

Link to comment
Share on other sites

Hi Dan,

Really thankful for your offer of help, I'm in the UK and I guess you're in the US. I then ran out of time before I was away for the weekend.

I'm running bare metal(mainly for real time control - I'm sure I could get suitable real time  control via an RTOS or linux incarnation but I haven't gone there yet). I had been using the bare metal example from the xilffs library. However, I have gone to a minimalist code that I got from a xilinx forum.

I've attached my code. helloworld.c

I haven't gone through line by line, just (what I believe) are the relevant bits(everytime there is a cmd transfer though). Also note I was going through with the debugger(very slowly) for creating this reply, I have found that when in the debugger going very slowly through, it sometimes completes the card initialisation(although then still doesn't write correctly) but most times it does what I have defined here. Really hoping you can provide some inspiration! Also note I will go through in exactly the same manner on the PS SDIO interface and see if I can see a difference.(using the fpga internal logic analyser)

My code goes as follows:

  1.  into xilSdInit -
  2. Checks the card is inserted [isCardInTheSocket()] - This  works correctly.
  3. Checks the card is write protected [isCardWriteProtected()] - This works correctly.
  4. Lookup Config [ConfigPtr = XSdPs_LookupConfig(SD_DEVICE_ID)] - This works correctly.
  5. Initialise the controller [status = XSdPs_CfgInitialize(sdInstPtr, ConfigPtr, ConfigPtr->BaseAddress);] - This works correctly. It also starts the 400KHz SDIO0_CLK
  6. It then goes into [status = XSdPs_CardInitialize(sdInstPtr);]. This function sits within xsdps.c.
  7. So it goes to [Status = XSdPs_IdentifyCard(InstancePtr);] This is the first time there is command line transmission. It correctly identifies as XSDPS_CARD_SD(I've changed the defaults previously to be sure). Note DAT1 & DAT0 are constantly LOW. when [Status = XSdPs_CmdTransfer(InstancePtr, CMD0, 0U, 0U);] is run. When [Status XSdPs_CmdTransfer(InstancePtr, CMD1, XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0U);] runs DAT0 transitions to HIGH after command line transmission.
  8. It then goes into [Status = XSdPs_SdCardInitialize(InstancePtr);]
  9. Then into PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_PRES_STATE_OFFSET); It moves on i.e. the present status indicates the card is detected.
  10. Next it goes into [Status = XSdPs_CmdTransfer(InstancePtr, (u32)CMD0, 0U, 0U);]. It appears DAT0 is constantly High and DAT1 is constantly LOW and there is command line transmission and it moves on.
  11. Next is [Status = XSdPs_CmdTransfer(InstancePtr, CMD8, XSDPS_CMD8_VOL_PATTERN, 0U);] Again command line transmission but DAT0 is constantly High and DAT1 is constantly LOW.
  12. Then the debugger moves around a bit(not sure why) but it ends up at [Status = XSdPs_CmdTransfer(InstancePtr, CMD55, 0U, 0U);] and moves on.
  13. Next is [Status = XSdPs_CmdTransfer(InstancePtr, ACMD41, Arg, 0U);] Again command line transmission but DAT0 is constantly High and DAT1 is constantly LOW.
  14. It then jumps back to 12. above. then back to 13. then moves on.
  15. Next is [Status = XSdPs_CmdTransfer(InstancePtr, CMD2, 0U, 0U);], Again command line transmission but DAT0 is constantly High and DAT1 is constantly LOW. The debugger moves around again?? but ends up in the do while loop.
  16. [Status = XSdPs_CmdTransfer(InstancePtr, CMD3, 0U, 0U); Again command line transmission but DAT0 is constantly High and DAT1 is constantly LOW.
  17. Then [Status = XSdPs_CmdTransfer(InstancePtr, CMD9, (InstancePtr->RelCardAddr), 0U);] Again command line transmission but DAT0 is constantly High and DAT1 is constantly LOW.
  18. The debugger jumps around and up returning from [Status = XSdPs_SdCardInitialize(InstancePtr);] and moves on. i.e. it was a success.
  19. Next Change the clock speed [Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);] , the 25MHz option from the if/elseThis function is in xsdps_options.c. This function doesn't appear to wiggle the data lines or cmd line, however the clock and every cmd after this is at 25MHz.
  20. Next [Status = XSdPs_Select_Card(InstancePtr);] and does [Status = XSdPs_CmdTransfer(InstancePtr, CMD7, InstancePtr->RelCardAddr, 0U); Again command line transmission but DAT0 is constantly High and DAT1 is constantly LOW.
  21. Next is [Status = XSdPs_Pullup(InstancePtr);] and does [Status = XSdPs_CmdTransfer(InstancePtr, CMD55, InstancePtr->RelCardAddr, 0U); Again command line transmission but DAT0 is constantly High and DAT1 is constantly LOW. Then Status = XSdPs_CmdTransfer(InstancePtr, ACMD42, 0U, 0U); Again command line transmission but DAT0 is constantly High and DAT1 is constantly LOW. then moves on.
  22. Next is [Status = XSdPs_Get_BusWidth(InstancePtr, SCR);] and does [Status = XSdPs_CmdTransfer(InstancePtr, CMD55, InstancePtr->RelCardAddr, 0U); Again command line transmission but DAT0 is constantly High and DAT1 is constantly LOW. It sets up the  ADMA2 descriptor table with [XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, SCR);] and moves onto Status = XSdPs_CmdTransfer(InstancePtr, ACMD51, 0U, BlkCnt);  Again command line transmission but DAT0 is constantly High and DAT1 is constantly LOW. then moves on.
  23. Next [Status = XSdPs_Get_BusSpeed(InstancePtr, ReadBuff);] and then XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff); and moves onto [Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U);] Again command line transmission but DAT0 is constantly High and DAT1 goes HIGH half way through the cmd transmission.????????? It then moves onto Check for transfer complete, Polling for response for now and reads the StatusReg [StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET);] the error bit is high it clears the error bit [goto RETURN PATH] therefore returns from XSdPs_Get_BusSpeed with a XST_FAILURE.

 

Link to comment
Share on other sites

@927465,

I don't have any code I can share, but I have done this before.  Can you go through the startup sequence you are sending together with what you are receiving from the card?  Perhaps we can debug this.

Alternatively, why not monitor the MIO pins when the SD card is started up from the Linux driver in the PS, and use that as the guide that you need to emulate?

Dan

Link to comment
Share on other sites

Thankyou so much for your prior help, I got the Pmod SD via SPI working. Unfortunately I have an application that requires more speed than I can get from the SPI.

I know Digilent only support the Pmod SD via SPI.

However, do you have a vivado design that is known to work with your Pmod SD card using SDIO via EMIO from the PS? I have tried so many ways to make it happen and I can't get it to work. It falls over in the initialisation, where I request the bus speed. If I skip over this, it will then just not respond(there is some command line wiggling but I don't know what it means) . Note during card initialisation(when it runs at 400KHz) it is fine, when it goes faster I will need to run analyser within the zynq - but I don't really know what it should or shouldn't be doing.

Note I can make it work via SPI and I can make it work via the MIO pins on the PS directly to the SD card on the Zedboard.

Link to comment
Share on other sites

Hi @927465,

Here is the Vivado library I used in my previous project. I updated the vivado library and re-did the project here without issue in vivado 2018.1. When you load the project make sure to go into setting-> ip->repository and remove the path to my vivado library and add the path to your vivado library.  I was able to complete the project and use the debugger with the current version of the Pmod SD IP Core.

thank you,

Jon

zed_sd.jpg

zed_sd_2.jpg

Link to comment
Share on other sites

I'm having problems getting your project to work. Your version of the PmodSD IP is 1.0(Rev. 10) from the project you sent me. The project I sent you was using your latest vivado library https://github.com/Digilent/vivado-library. i.e. 1.0(Rev.11)

So I tried your 2016.4 library release from https://github.com/Digilent/vivado-library/releases/tag/v2016.4-1 and found that it had the PModSD IP 1.0(Rev. 8).

Where can I get PModSD IP 1.0(Rev. 10) from?

Link to comment
Share on other sites

Hi @927465,

I have not see this issue with the RAM size.  In your block design are you turning off the SD in the Zynq processor or are you editing the Pmod SD IP core sdk code for the Pmod SD to be a different SD device? Are you using the digilent board files here? Could you attach your SDK code? What version of Vivado are you primarily using?

thank you,

Jon

Link to comment
Share on other sites

Hi Jon,

I have been using the digilent PmodSD IP core with the digilent PmodSD card only so I'm not sure why you are asking?

I attach a screen shot of where I change the linker script to be able to debug. This enables your demo example to be debugged, but doesn't help me going forward as I can't put the code in ram if my application is any bigger?

I have googled far and wide for this and I can't really come up with a solution. Again all help greatly received.

 

2018-07-23 11_45_49-Window.png

Link to comment
Share on other sites

Thanks JColvin!!!!!!

That was a problem, it was created as a 'C' project(which is nearly always the case when I setup a project and is the default), although this should have crossed my mind - as I knew the bit of code it was complaining about was C++. - It just never dawned on me.

Can I please ask, that you update your instructions for pmod tutorials so that other people don't fall into the same trap?!

I do have another problem, which may or may not be related - I can't debug the code for some reason.

When I attempt to debug it goes into dissasembly, I found a partial solution by placing Code, Data, Heap and Stack into ps7_ram_0 in the linker script - I have no idea why this then enables me to debug normally. However as the ram size is 192Kb it doesn't build if I have a bigger application. - So this isn't really a full solution.

Do you have any suggestions?

Link to comment
Share on other sites

Hi @927465,

I apologize for the delay; we are taking a look into this. Do you know what language you built the application in (C or C++)? If you're not sure, I believe you can see what you used by going into the application project's settings where you'll be able to see what language you used; you should be using C++. If you are not, you should be able to fix it by creating a new application project and choosing C++ as the language.

Let me know how this goes.

Thanks,
JColvin

Link to comment
Share on other sites

OK now I'm really needing some help. I can't get this to work. I have tried with multiple versions of Vivado/SDK(2015.4, 2016.4 and 2018.1) and I get different problems with all. To be honest I think most of them are related to Vivado/SDK but I just want to get your example project running. I'm using digilent's board file for the zedboard(which has a few more features than avnets). So here is a list of questions:

1) Is there a version of Vivado/SDK/digilent library to use that is known to work. Is it possible to get a zip file of a complete project? - I'm very aware it could be something I do that makes everything fall over.

2) When I run through the tutorial https://reference.digilentinc.com/learn/programmable-logic/tutorials/pmod-ips/start to run the example code. It complains "Executables selected for download on the following processors does'nt exist or incorrectly specified". Therefore I then create a hello world application and copy the code from the example\main.cc into helloworld.c, but then I get build errors(from includingPmodSd.h, which includesDXSPISDVOL.h(uppdated by TommyK 8/8/16)

I attach the Vivado Block Diagram

image.thumb.png.9b628bf18f4cb347e415bd7aa048f584.png

 

and I attach the build error

image.thumb.png.7b0dfb9e2038994efaeb84ea45906862.png

Really hoping you can help.

Many thanks in advance.

image.png

image.png

Link to comment
Share on other sites

I have moved on a bit, it appears to me that your Vivado library for 2015.4 doesn't have zynq drivers. I have now been using your latest vivado library and I don't get this problem. However, I am getting other problems that I may come back to you on.

Link to comment
Share on other sites

Hi @927465,

Please attach a screen shot of your block design as well as your SDK errors. Are you trying to use two SD cards? Why are you not using the Pmod SD instead of the built in SD card reader? Do you have the digilent board files installed and are using them?

thank you,

Jon

zedboard_board_files.jpg

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...