MOSI not doing anything on pi pico on bare metal (no sdk)

I am trying to set up SPI to use a SD card module with my pi pico, but no matter what i do it seems like the mosi pin does nothing, the internal loopback works fine but not if i physically bridge the pins.
17 Replies
Maverick
Maverick3mo ago
Why no SDK, no Arduino framework? Is this for a school assignment?
VaporGame
VaporGameOP3mo ago
is there a problem with me doing it this way? i just thought this would be an interesting project
Maverick
Maverick3mo ago
We're not allowed to help with school assignments. The most common reason for someone approaching a task this way is because they were required to for a school assignment. Have you looked at the SDK or Arduino framework's source code for SPI? That could be helpful.
VaporGame
VaporGameOP3mo ago
it's not a school assignment, i just wanted to do something to pass time so far its been working since overall ive been working on this for a week, and 4 days trying to get spi working i have cross referenced with the sdk, another spi implementation, and even a sd card library i havent found any other mention of my problem online, and i find it weird that the internal loopback works, but not normal, even though i set the pin as output
Maverick
Maverick3mo ago
Is the loopback test your only method of verifying whether or not it's working? Can you post the code here?
VaporGame
VaporGameOP3mo ago
i tried using another MCU and a sd card module aswell. The mcu confirmed that it was making transfers, but no data was actually transferred. It's 2:32 am for me, but I'll post the code here tomorrow when i can. here is my initialization function
void spi_init(void) {
//SPI0_SSPCR1 |= (1 << 0);
SPI0_SSPCR0 = (0x7 << 0); //set data size to 8bit
//frame format is motorola SPI by default
//assume SPI mode 0
//SPI0_SSPCR0 = ((1 << 6) | (1 << 7)); //SPO = 0, SPH = 0
SPI0_SSCPSR = 64;
//we will want to change this afterwards to 2 to get a 6mhz clock
//device is master by default
SPI0_SSPCR1 &= ~(1 << 2);
//SPI0_SSPDR = 0xFFFF; //prime
SPI0_SSPCR1 |= (1 << 1); //enable SSP
//SOD is only relevant in slave mode

//setup pins
IO_BANK0_GPIO04_CTRL = 1; //function 1 SPI MISO
//IO_BANK0_GPIO05_CTRL = 1; //CS, doing software CS
IO_BANK0_GPIO06_CTRL = 1; //SCK
IO_BANK0_GPIO07_CTRL = 1; //MOSI
//set direction for pins 6 and 7
SIO_GPIO_OE_SET = (1 << 6);
SIO_GPIO_OE_SET = (1 << 7);

SIO_GPIO_OE_SET = (1 << 9); //gp9 is gonna be cs

PADS_BANK0_GPIO06 = (0x1 << 4); //disable input and drive strenght, output disable is 0 by default
PADS_BANK0_GPIO07 = (0x1 << 4);

PADS_BANK0_GPIO09 = (0x1 << 4);

IO_BANK0_GPIO09_CTRL = 5;
SIO_GPIO_OE_SET |= 1 << 9;
}
void spi_init(void) {
//SPI0_SSPCR1 |= (1 << 0);
SPI0_SSPCR0 = (0x7 << 0); //set data size to 8bit
//frame format is motorola SPI by default
//assume SPI mode 0
//SPI0_SSPCR0 = ((1 << 6) | (1 << 7)); //SPO = 0, SPH = 0
SPI0_SSCPSR = 64;
//we will want to change this afterwards to 2 to get a 6mhz clock
//device is master by default
SPI0_SSPCR1 &= ~(1 << 2);
//SPI0_SSPDR = 0xFFFF; //prime
SPI0_SSPCR1 |= (1 << 1); //enable SSP
//SOD is only relevant in slave mode

//setup pins
IO_BANK0_GPIO04_CTRL = 1; //function 1 SPI MISO
//IO_BANK0_GPIO05_CTRL = 1; //CS, doing software CS
IO_BANK0_GPIO06_CTRL = 1; //SCK
IO_BANK0_GPIO07_CTRL = 1; //MOSI
//set direction for pins 6 and 7
SIO_GPIO_OE_SET = (1 << 6);
SIO_GPIO_OE_SET = (1 << 7);

SIO_GPIO_OE_SET = (1 << 9); //gp9 is gonna be cs

PADS_BANK0_GPIO06 = (0x1 << 4); //disable input and drive strenght, output disable is 0 by default
PADS_BANK0_GPIO07 = (0x1 << 4);

PADS_BANK0_GPIO09 = (0x1 << 4);

IO_BANK0_GPIO09_CTRL = 5;
SIO_GPIO_OE_SET |= 1 << 9;
}
and here is my rw function
void spi_rw_blocking(char *data, unsigned int len) {
unsigned int i;
char str[3];
//spi_send_byte(0xFF);
for (i = 0; i < len; i++) {
while (!(SPI0_SSPSR & (1 << 1))); //wait untill FIFO is not full
SPI0_SSPDR = data[i];
//SPI0_SSPDR = 0xFFFF;


while (SPI0_SSPSR & (1 << 4)); //wait untill its not busy

while (!(SPI0_SSPSR & (1 << 2))) {} //if receive FIFO is not empty
data[i] = SPI0_SSPDR;
}
}
void spi_rw_blocking(char *data, unsigned int len) {
unsigned int i;
char str[3];
//spi_send_byte(0xFF);
for (i = 0; i < len; i++) {
while (!(SPI0_SSPSR & (1 << 1))); //wait untill FIFO is not full
SPI0_SSPDR = data[i];
//SPI0_SSPDR = 0xFFFF;


while (SPI0_SSPSR & (1 << 4)); //wait untill its not busy

while (!(SPI0_SSPSR & (1 << 2))) {} //if receive FIFO is not empty
data[i] = SPI0_SSPDR;
}
}
i also have variations that only write or read i also have this for my SD card initialization function if it helps, but im pretty sure the problem isnt here
bool sdInit(void) {
usSleep(10000); //10ms, let sd card stabilize

SIO_GPIO_OUT_SET |= 1 << 9;

for(int i = 0; i < 10; i++) {
spi_send_byte(0xFF);
}

//spi_rw_blocking(buff, 80);

buff[0] = 0x40;
buff[1] = 0x00;
buff[2] = 0x00;
buff[3] = 0x00;
buff[4] = 0x00;
buff[5] = 0x95;

SIO_GPIO_OUT_CLR |= 1 << 9;

for(int i = 0; i < 6; i++) {
spi_send_byte(buff[i]);
}

char str[3];
//spi_rw_blocking(buff, 5);
int res = 0;

for(int i = 0; i < 10; i++) {
//while (res = 0xFF) {
res = spi_read_byte();
if(res == 0x01) {
uartTxStr("initialized");
return true;
}
byteToStr(str, res);
uartTxStr(str);
spi_send_byte(0xFF);
}
SIO_GPIO_OUT_SET |= 1 << 9;

// for (int i = 0; i < 8; i++) {
// spi_send_byte(0xFF);
// }
return false;
}
bool sdInit(void) {
usSleep(10000); //10ms, let sd card stabilize

SIO_GPIO_OUT_SET |= 1 << 9;

for(int i = 0; i < 10; i++) {
spi_send_byte(0xFF);
}

//spi_rw_blocking(buff, 80);

buff[0] = 0x40;
buff[1] = 0x00;
buff[2] = 0x00;
buff[3] = 0x00;
buff[4] = 0x00;
buff[5] = 0x95;

SIO_GPIO_OUT_CLR |= 1 << 9;

for(int i = 0; i < 6; i++) {
spi_send_byte(buff[i]);
}

char str[3];
//spi_rw_blocking(buff, 5);
int res = 0;

for(int i = 0; i < 10; i++) {
//while (res = 0xFF) {
res = spi_read_byte();
if(res == 0x01) {
uartTxStr("initialized");
return true;
}
byteToStr(str, res);
uartTxStr(str);
spi_send_byte(0xFF);
}
SIO_GPIO_OUT_SET |= 1 << 9;

// for (int i = 0; i < 8; i++) {
// spi_send_byte(0xFF);
// }
return false;
}
the "str" is a leftover from some debugging i have also added a pullup resistor to MISO since it kept floating with the sd card module
Maverick
Maverick3mo ago
Where do these definitions come from? PADS_BANK0_GPIO09
VaporGame
VaporGameOP3mo ago
i dont have registers set up as structs yet, but its jusdt the pads base + gpio9 offset
#define PADS_BANK0_BASE 0x4001c000
#define PADS_BANK0_GPIO06 *(volatile uint32_t *) (PADS_BANK0_BASE + 0x1c)
#define PADS_BANK0_GPIO07 *(volatile uint32_t *) (PADS_BANK0_BASE + 0x20)
#define PADS_BANK0_GPIO09 *(volatile uint32_t *) (PADS_BANK0_BASE + 0x28)
#define PADS_BANK0_BASE 0x4001c000
#define PADS_BANK0_GPIO06 *(volatile uint32_t *) (PADS_BANK0_BASE + 0x1c)
#define PADS_BANK0_GPIO07 *(volatile uint32_t *) (PADS_BANK0_BASE + 0x20)
#define PADS_BANK0_GPIO09 *(volatile uint32_t *) (PADS_BANK0_BASE + 0x28)
Maverick
Maverick3mo ago
This is in your code somewhere? Can you post the whole thing?
VaporGame
VaporGameOP3mo ago
i can post the c file with most stuff, it doesnt have clock initialization, but i do switch the peripheral clock to XOSC there
VaporGame
VaporGameOP3mo ago
please ignore how messy it is, i thought that SPI wouldnt be much of a hurdle and was putting off cleaning it up after it
Maverick
Maverick3mo ago
This is a lot to look at. Won't have time until later. One question just glancing at it, for example, Is there a definition in the pico SDK that you would consider equivalent to PADS_BANK0_GPIO09?
VaporGame
VaporGameOP3mo ago
the sdk has structs defined for everything, i'd have to go over it again but im pretty sure there was one iirc also that is my software CS pin, which appears to work fine i wanna get it working before i clean up, so i dont accidentally break something in the process
pseud0
pseud03mo ago
No GPIO is selected for MISO? Should be GPIO8.
VaporGame
VaporGameOP3mo ago
IO_BANK0_GPIO04_CTRL = 1; //function 1 SPI MISO
//IO_BANK0_GPIO05_CTRL = 1; //CS, doing software CS
IO_BANK0_GPIO06_CTRL = 1; //SCK
IO_BANK0_GPIO07_CTRL = 1; //MOSI
IO_BANK0_GPIO04_CTRL = 1; //function 1 SPI MISO
//IO_BANK0_GPIO05_CTRL = 1; //CS, doing software CS
IO_BANK0_GPIO06_CTRL = 1; //SCK
IO_BANK0_GPIO07_CTRL = 1; //MOSI
MISO is the pin i actually confirmed works since tying it to 3.3v makes it read 0xFF i've also tried the pico SDK "default" configuration, but still miso seems to work but not mosi while testing with a LED, ive noticed that SCK might also not be doing anything which the test with another mcu confirms i set up the chip select pin the same way i do the rest, and it works fine its 2 am, but i have discovered, that it works on the default pin configuration even though the one i was using before should have been supported i cant resolder the pin headers atm since its so late, but ill test with another mcu tommorow ive seen someone on reddit describe a similar issue, where they couldnt get MOSI working on GP2 or 3 Im so close, i can tie the pins together physically, and get a loopback, but trying with another MCU, it sees the transfers now, but its all 0x00 i set it to transmit 0xFF in a loop atm
Maverick
Maverick3mo ago
Sorry, I thought you had it working here https://discord.com/channels/420594746990526466/1390110941890351155/1390483048880930926 Is it just using different pins that isn't working now?
VaporGame
VaporGameOP3mo ago
no, using different pins made it work, but i seem to have a problem with reading now im testing with another mcu, which should loop back all the 0xFF, but im getting more 0x00 with 0x0FF at seemingly set offsets the original issue is solved, its probably my code that is faulty now i tweaked it a bit, but something is still weird since it seems like im sending 4 bytes of nothing at the end of my transmission this could very well also be a bug in my slave loopback code ill try initializing a SD card and see if it works im pretty sure it works, i can get the SD card to respond with0x01 to CMD0! i think the issue can be marked as solved

Did you find this page helpful?