sdio_RP2MCU.pio 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. ; ZuluSCSI™ - Copyright (c) 2022-2025 Rabbit Hole Computing™
  2. ;
  3. ; ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
  4. ;
  5. ; https://www.gnu.org/licenses/gpl-3.0.html
  6. ; ----
  7. ; This program is free software: you can redistribute it and/or modify
  8. ; it under the terms of the GNU General Public License as published by
  9. ; the Free Software Foundation, either version 3 of the License, or
  10. ; (at your option) any later version. 
  11. ;
  12. ; This program is distributed in the hope that it will be useful,
  13. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. ; GNU General Public License for more details. 
  16. ;
  17. ; You should have received a copy of the GNU General Public License
  18. ; along with this program.  If not, see <https://www.gnu.org/licenses/>.
  19. ; RP2040 PIO program for implementing SD card access in SDIO mode
  20. ; Run "pioasm rp2040_sdio.pio rp2040_sdio.pio.h" to regenerate the C header from this.
  21. ; The RP2040 official work-in-progress code at
  22. ; https://github.com/raspberrypi/pico-extras/tree/master/src/rp2_common/pico_sd_card
  23. ; may be useful reference, but this is independent implementation.
  24. ;
  25. ; For official SDIO specifications, refer to:
  26. ; https://www.sdcard.org/downloads/pls/
  27. ; "SDIO Physical Layer Simplified Specification Version 8.00"
  28. ; Clock settings
  29. ; For 3.3V communication the available speeds are:
  30. ; - Default speed: max. 25 MHz clock
  31. ; - High speed: max. 50 MHz clock
  32. ;
  33. ; From the default RP2040 clock speed of 125 MHz, the closest dividers
  34. ; are 3 for 41.7 MHz and 5 for 25 MHz. The CPU can apply further divider
  35. ; through state machine registers for the initial handshake.
  36. ;
  37. ; Because data is written on the falling edge and read on the rising
  38. ; edge, it is preferrable to have a long 0 state and short 1 state.
  39. ;.define CLKDIV 3
  40. ; all Dummy values, to be recoded by C pico-sdk functions
  41. .define CLKDIV 5
  42. .define D0 ((CLKDIV + 1) / 2 - 1)
  43. .define D1 (CLKDIV/2 - 1)
  44. .define SDIO_CLK_GPIO 18
  45. ; State machine 0 is used to:
  46. ; - generate continuous clock on SDIO_CLK
  47. ; - send CMD packets
  48. ; - receive response packets
  49. ;
  50. ; Pin mapping for this state machine:
  51. ; - Sideset : CLK
  52. ; - IN/OUT/SET : CMD
  53. ; - JMP_PIN : CMD
  54. ;
  55. ; The commands to send are put on TX fifo and must have two words:
  56. ; Word 0 bits 31-24: Number of bits in command minus one (usually 47)
  57. ; Word 0 bits 23-00: First 24 bits of the command packet, shifted out MSB first
  58. ; Word 1 bits 31-08: Last 24 bits of the command packet, shifted out MSB first
  59. ; Word 1 bits 07-00: Number of bits in response minus one (usually 47), or 0 if no response
  60. ;
  61. ; The response is put on RX fifo, starting with the MSB.
  62. ; Partial last word will be padded with zero bits at the top.
  63. ;
  64. ; The state machine EXECCTRL should be set so that STATUS indicates TX FIFO < 2
  65. ; and that AUTOPULL and AUTOPUSH are enabled.
  66. .program sdio_cmd_clk
  67. .side_set 1
  68. mov OSR, NULL side 1 [0] ;[D1] ; Make sure OSR is full of zeros to prevent autopull
  69. wait_cmd:
  70. mov Y, !STATUS side 0 [0]; [D0] ; Check if TX FIFO has data
  71. jmp !Y wait_cmd side 1 [0]; [D1]
  72. load_cmd:
  73. out NULL, 32 side 0 [0]; [D0] ; Load first word (trigger autopull)
  74. out X, 8 side 1 [0]; [D1] ; Number of bits to send
  75. set pins, 1 side 0 [0]; [D0] ; Initial state of CMD is high
  76. set pindirs, 1 side 1 [0]; [D1] ; Set SDIO_CMD as output
  77. send_cmd:
  78. out pins, 1 side 0 [0]; [D0] ; Write output on falling edge of CLK
  79. jmp X-- send_cmd side 1 [0]; [D1]
  80. prep_resp:
  81. set pindirs, 0 side 0 [0]; [D0] ; Set SDIO_CMD as input
  82. out X, 8 side 1 [0]; [D1] ; Get number of bits in response
  83. nop side 0 [0]; [D0] ; For clock alignment
  84. jmp !X resp_done side 1 [0]; [D1] ; Check if we expect a response
  85. wait_resp:
  86. nop side 0 [0]; [D0]
  87. jmp PIN wait_resp side 1 [0]; [D1] ; Loop until SDIO_CMD = 0
  88. ; Note: input bits are read at the same time as we write CLK=0.
  89. ; Because the host controls the clock, the read happens before
  90. ; the card sees the falling clock edge. This gives maximum time
  91. ; for the data bit to settle.
  92. read_resp:
  93. in PINS, 1 side 0 [0]; [D0] ; Read input data bit
  94. jmp X-- read_resp side 1 [0]; [D1] ; Loop to receive all data bits
  95. resp_done:
  96. push side 0 [0]; [D0] ; Push the remaining part of response
  97. ; State machine 1 is used to send and receive data blocks.
  98. ; Pin mapping for this state machine:
  99. ; - IN / OUT: SDIO_D0-D3
  100. ; - GPIO defined at beginning of this file: SDIO_CLK
  101. ; Data reception program
  102. ; This program will wait for initial start of block token and then
  103. ; receive a data block. The application must set number of nibbles
  104. ; to receive minus 1 to Y register before running this program.
  105. .program sdio_data_rx
  106. wait_start:
  107. mov X, Y ; Reinitialize number of nibbles to receive
  108. wait 0 pin 0 ; Wait for zero state on D0
  109. wait 1 gpio SDIO_CLK_GPIO [0]; [CLKDIV-1] ; Wait for rising edge and then whole clock cycle
  110. rx_data:
  111. in PINS, 4 [0]; [CLKDIV-2] ; Read nibble
  112. jmp X--, rx_data
  113. ; Data transmission program
  114. ;
  115. ; Before running this program, pindirs should be set as output
  116. ; and register X should be initialized with the number of nibbles
  117. ; to send minus 1 (typically 8 + 1024 + 16 + 1 - 1 = 1048)
  118. ; and register Y with the number of response bits minus 1 (typically 31).
  119. ;
  120. ; Words written to TX FIFO must be:
  121. ; - Word 0: start token 0xFFFFFFF0
  122. ; - Word 1-128: transmitted data (512 bytes)
  123. ; - Word 129-130: CRC checksum
  124. ; - Word 131: end token 0xFFFFFFFF
  125. ;
  126. ; After the card reports idle status, RX FIFO will get a word that
  127. ; contains the D0 line response from card.
  128. .program sdio_data_tx
  129. wait 0 gpio SDIO_CLK_GPIO
  130. wait 1 gpio SDIO_CLK_GPIO [0]; [CLKDIV + D1 - 1]; Synchronize so that write occurs on falling edge
  131. tx_loop:
  132. out PINS, 4 [0]; [D0] ; Write nibble and wait for whole clock cycle
  133. jmp X-- tx_loop [0]; [D1]
  134. set pindirs, 0x00 [0]; [D0] ; Set data bus as input
  135. .wrap_target
  136. response_loop:
  137. in PINS, 1 [0]; [D1] ; Read D0 on rising edge
  138. jmp Y--, response_loop [0]; [D0]
  139. wait_idle:
  140. wait 1 pin 0 [0]; [D1] ; Wait for card to indicate idle condition
  141. push [0]; [D0] ; Push the response token
  142. .wrap