/ adafruit_boardtest / boardtest_sd.py
boardtest_sd.py
  1  # The MIT License (MIT)
  2  #
  3  # Copyright (c) 2018 Shawn Hymel for Adafruit Industries
  4  #
  5  # Permission is hereby granted, free of charge, to any person obtaining a copy
  6  # of this software and associated documentation files (the "Software"), to deal
  7  # in the Software without restriction, including without limitation the rights
  8  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9  # copies of the Software, and to permit persons to whom the Software is
 10  # furnished to do so, subject to the following conditions:
 11  #
 12  # The above copyright notice and this permission notice shall be included in
 13  # all copies or substantial portions of the Software.
 14  #
 15  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 20  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 21  # THE SOFTWARE.
 22  """
 23  `adafruit_boardtest.boardtest_sd`
 24  ====================================================
 25  Performs random writes and reads to SD card over SPI.
 26  
 27  Run this script as its own main.py to individually run the test, or compile
 28  with mpy-cross and call from separate test script.
 29  
 30  * Author(s): Shawn Hymel for Adafruit Industries
 31  
 32  Implementation Notes
 33  --------------------
 34  
 35  **Hardware:**
 36  
 37  * `SD Card <https://www.adafruit.com/product/1294>`_
 38  
 39  **Software and Dependencies:**
 40  
 41  * Adafruit CircuitPython firmware for the supported boards:
 42    https://github.com/adafruit/circuitpython/releases
 43  * Adafruit's Bus Device library:
 44    https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
 45  * Adafruit CircuitPython SD card driver:
 46    https://github.com/adafruit/Adafruit_CircuitPython_SD
 47  
 48  """
 49  import random
 50  
 51  import board
 52  import busio
 53  import digitalio
 54  import adafruit_sdcard
 55  import storage
 56  
 57  __version__ = "0.0.0-auto.0"
 58  __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BoardTest.git"
 59  
 60  # Constants
 61  MOSI_PIN_NAME = "SD_MOSI"
 62  MISO_PIN_NAME = "SD_MISO"
 63  SCK_PIN_NAME = "SD_SCK"
 64  CS_PIN_NAME = "SD_CS"
 65  FILENAME = "test.txt"  # File that will be written to
 66  BAUD_RATE = 100000  # Bits per second
 67  NUM_UART_BYTES = 40  # Number of bytes to transmit over UART
 68  ASCII_MIN = 0x21  # '!' Lowest ASCII char in random range (inclusive)
 69  ASCII_MAX = 0x7E  # '~' Highest ASCII char in random range (inclusive)
 70  
 71  # Test result strings
 72  PASS = "PASS"
 73  FAIL = "FAIL"
 74  NA = "N/A"
 75  
 76  
 77  def run_test(
 78      pins,
 79      mosi_pin=MOSI_PIN_NAME,
 80      miso_pin=MISO_PIN_NAME,
 81      sck_pin=SCK_PIN_NAME,
 82      cs_pin=CS_PIN_NAME,
 83  ):
 84  
 85      """
 86      Performs random writes and reads to file on attached SD card.
 87  
 88      :param list[str] pins: list of pins to run the test on
 89      :param str mosi_pin: pin name of SPI MOSI
 90      :param str miso_pin: pin name of SPI MISO
 91      :param str sck_pin: pin name of SPI SCK
 92      :param str cs_pin: pin name of SPI CS
 93      :param str filename: name of file to use as test on SD card
 94      :return: tuple(str, list[str]): test result followed by list of pins tested
 95      """
 96  
 97      # Write characters to file on SD card and verify they were written
 98      if list(set(pins).intersection(set([mosi_pin, miso_pin, sck_pin]))):
 99  
100          # Tell user to connect SD card
101          print("Insert SD card into holder and connect SPI lines to holder.")
102          print("Connect " + cs_pin + " to the CS (DAT3) pin on the SD " + "card holder.")
103          print("WARNING: " + FILENAME + " will be created or overwritten.")
104          print("Press enter to continue.")
105          input()
106  
107          # Configure CS pin
108          csel = digitalio.DigitalInOut(getattr(board, cs_pin))
109          csel.direction = digitalio.Direction.OUTPUT
110          csel.value = True
111  
112          # Set up SPI
113          spi = busio.SPI(
114              getattr(board, sck_pin),
115              MOSI=getattr(board, mosi_pin),
116              MISO=getattr(board, miso_pin),
117          )
118  
119          # Try to connect to the card and mount the filesystem
120          try:
121              sdcard = adafruit_sdcard.SDCard(spi, csel)
122              vfs = storage.VfsFat(sdcard)
123              storage.mount(vfs, "/sd")
124          except OSError:
125              print("Could not mount SD card")
126              return FAIL, [mosi_pin, miso_pin, sck_pin]
127  
128          # Generate test string
129          test_str = ""
130          for _ in range(NUM_UART_BYTES):
131              test_str += chr(random.randint(ASCII_MIN, ASCII_MAX))
132  
133          # Write test string to a text file on the card
134          try:
135              with open("/sd/" + FILENAME, "w") as file:
136                  print("Writing:\t" + test_str)
137                  file.write(test_str)
138          except OSError:
139              print("Could not write to SD card")
140              return FAIL, [mosi_pin, miso_pin, sck_pin]
141  
142          # Read from test file on the card
143          read_str = ""
144          try:
145              with open("/sd/" + FILENAME, "r") as file:
146                  lines = file.readlines()
147                  for line in lines:
148                      read_str += line
149              print("Read:\t\t" + read_str)
150          except OSError:
151              print("Could not write to SD card")
152              return FAIL, [mosi_pin, miso_pin, sck_pin]
153  
154          # Release SPI
155          spi.deinit()
156  
157          # Compare strings
158          if read_str == test_str:
159              return PASS, [mosi_pin, miso_pin, sck_pin]
160  
161          return FAIL, [mosi_pin, miso_pin, sck_pin]
162  
163      # Else (no pins found)
164      print("No SD card pins found")
165      return NA, []
166  
167  
168  def _main():
169  
170      # List out all the pins available to us
171      pins = list(dir(board))
172      print()
173      print("All pins found:", end=" ")
174  
175      # Print pins
176      for pin in pins:
177          print(pin, end=" ")
178      print("\n")
179  
180      # Run test
181      result = run_test(pins)
182      print()
183      print(result[0])
184      print("Pins tested: " + str(result[1]))
185  
186  
187  # Execute only if run as main.py or code.py
188  if __name__ == "__main__":
189      _main()