Skip to content

Instantly share code, notes, and snippets.

@profi200
Created May 30, 2021 14:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save profi200/55119e74d2439ad87060941eec42c07d to your computer and use it in GitHub Desktop.
Save profi200/55119e74d2439ad87060941eec42c07d to your computer and use it in GitHub Desktop.
//#include "types.h"
#include <stdio.h>
#include <inttypes.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "hardware/spi.h"
#include "pico/bootrom.h"
#define LED_PIN (25u)
#define SPI_PIN_MISO (0u)
#define SPI_PIN_CS (1u)
#define SPI_PIN_CLK (2u)
#define SPI_PIN_MOSI (3u)
// Shamelessly stolen from the button example.
#include "hardware/sync.h" // save_and_disable_interrupts()...
#include "hardware/structs/ioqspi.h"
#include "hardware/structs/sio.h"
bool __no_inline_not_in_flash_func(get_bootsel_button)(void)
{
const uint CS_PIN_INDEX = 1;
// Must disable interrupts, as interrupt handlers may be in flash, and we
// are about to temporarily disable flash access!
uint32_t flags = save_and_disable_interrupts();
// Set chip select to Hi-Z
hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl,
GPIO_OVERRIDE_LOW << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB,
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
// Note we can't call into any sleep functions in flash right now
for (volatile int i = 0; i < 1000; ++i);
// The HI GPIO registers in SIO can observe and control the 6 QSPI pins.
// Note the button pulls the pin *low* when pressed.
bool button_state = !(sio_hw->gpio_hi_in & (1u << CS_PIN_INDEX));
// Need to restore the state of chip select, else we are going to have a
// bad time when we return to code in flash!
hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl,
GPIO_OVERRIDE_NORMAL << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB,
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
restore_interrupts(flags);
return button_state;
}
int main(void)
{
stdio_init_all();
gpio_init(LED_PIN);
gpio_put(LED_PIN, 0);
gpio_set_dir(LED_PIN, GPIO_OUT);
// The 3DS uses 16.756991 MHz.
// The SDK for some reason picks the next lowest (15625000) clock
// instead of the next highest (20833333).
// 15625000 seems to work though.
spi_init(spi0, 16756991);
spi_set_format(spi0, 8, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST);
spi_set_slave(spi0, true);
gpio_set_function(SPI_PIN_MISO, GPIO_FUNC_SPI);
gpio_set_function(SPI_PIN_CS, GPIO_FUNC_SPI);
gpio_set_function(SPI_PIN_CLK, GPIO_FUNC_SPI);
gpio_set_function(SPI_PIN_MOSI, GPIO_FUNC_SPI);
sleep_ms(1);
/*do
{
gpio_put(LED_PIN, 1);
uint8_t rxbuf[2];
const uint8_t resp[2] = {0xBA, 0xBE};
spi_read_blocking(spi0, 0xE1, rxbuf, 2);
spi_write_blocking(spi0, resp, 2);
printf("Hello from 3DS: %02" PRIX8 "%02" PRIX8 "\n", rxbuf[0], rxbuf[1]);
gpio_put(LED_PIN, 0);
sleep_ms(1000);
} while(!get_bootsel_button());*/
// SPICARD autopoll test.
do
{
sleep_ms(1000);
} while(!get_bootsel_button());
gpio_put(LED_PIN, 1);
uint8_t rxbuf;
const uint8_t resp = 0x02;
spi_read_blocking(spi0, 0xE2, &rxbuf, 1);
spi_write_blocking(spi0, &resp, 1);
printf("Hello from 3DS: %02" PRIX8 "\n", rxbuf);
sleep_ms(1000);
gpio_put(LED_PIN, 0);
reset_usb_boot(0, 0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment