|
| 1 | +/* |
| 2 | +// This file is subject to the terms and conditions defined in |
| 3 | +// file 'LICENSE.md', which is part of this source code package. |
| 4 | +*/ |
| 5 | + |
| 6 | +/* |
| 7 | +
|
| 8 | + SPI functionality is accessed via SPIClass objects or their children. |
| 9 | + On the Apollo3 the MbedSPI class inherits from the SPIClass class and |
| 10 | + provides the actual implemenation based on mbed-os SPI |
| 11 | + https://os.mbed.com/docs/mbed-os/v6.2/apis/spi.html |
| 12 | +
|
| 13 | + Apollo3 features 6 IOM peripherals that can each be configured as either |
| 14 | + SPI or I2C. Each IOM has only one set of pins that can be used. Check the |
| 15 | + board schematic or Apollo3 Blue datasheet to determine which IOM |
| 16 | + peripherals are available on your board. There are a few different ways |
| 17 | + to access these ports: |
| 18 | + - via pre-defined MbedSPI objects like SPI, SPI1 -> SPI5 |
| 19 | + - declaring your own MbedSPI object using pins that correspond to the correct IOM |
| 20 | +
|
| 21 | + Once you have an MbedSPI object to work with you can use all the standard |
| 22 | + Arduino SPI API methods on it |
| 23 | + https://www.arduino.cc/en/reference/SPI |
| 24 | +
|
| 25 | + This example will use threads to organize SPI operations based on board |
| 26 | + capabilities. The test function will check that outgoing bytes are proerly |
| 27 | + detected on a loop-back wire. |
| 28 | +
|
| 29 | + Wiring: |
| 30 | + For each applicable SPI port: |
| 31 | + SDO <--> SDI |
| 32 | + CLK (Not Connected) |
| 33 | +
|
| 34 | +*/ |
| 35 | + |
| 36 | +#include "SPI.h" |
| 37 | + |
| 38 | +// define SPI settings at which to test |
| 39 | +#define SPI_FREQ 10000000 |
| 40 | +#define SPI_MODE SPI_MODE3 |
| 41 | +#define SPI_ORDER MSBFIRST |
| 42 | +#define CS_PIN 0 |
| 43 | + |
| 44 | +#define SERIAL_PORT Serial |
| 45 | + |
| 46 | +// define pins to create a custom SPI port |
| 47 | +// using mbed PinNames or Arduino pin numbers |
| 48 | +// (must be all pins from one IOM module) |
| 49 | +#define mySDI D25 |
| 50 | +#define mySDO D28 |
| 51 | +#define myCLK D27 |
| 52 | + |
| 53 | +MbedSPI mySPI(mySDI, mySDO, myCLK); // declare the custom MbedSPI object mySPI |
| 54 | + |
| 55 | +// define a macro to aid testing |
| 56 | +#define TEST_SPI_PORT(P) SERIAL_PORT.printf("testing %s\n\ttime (ms): %d\n\tbyte transer: %s\n\tbuffer transfer: %s\n\n", #P, millis(), ((test_byte_transfer(P) == 0) ? "pass" : "fail"), ((test_buffer_transfer(P) == 0) ? "pass" : "fail")) |
| 57 | + |
| 58 | +// this thread will test the pre-defined SPI object if it exists |
| 59 | +rtos::Thread spi_thread; |
| 60 | +void spi_thread_fn( void ){ |
| 61 | +#if VARIANT_SPI_INTFCS > 0 |
| 62 | + delay(100); |
| 63 | + SPI.begin(); |
| 64 | + while(1){ |
| 65 | + TEST_SPI_PORT(SPI); |
| 66 | + delay(500); |
| 67 | + } |
| 68 | +#endif |
| 69 | +} |
| 70 | + |
| 71 | +// this thread tests the custom mySPI object |
| 72 | +extern "C" SPIName spi_get_peripheral_name(PinName mosi, PinName miso, PinName sclk); // this mbed internal function determines the IOM module number for a set of pins |
| 73 | +rtos::Thread myspi_thread; |
| 74 | +void myspi_thread_fn( void ){ |
| 75 | + delay(300); |
| 76 | + SERIAL_PORT.printf("starting mySPI on IOM %d\n", spi_get_peripheral_name(mySDO, mySDI, myCLK)); |
| 77 | + mySPI.begin(); |
| 78 | + while(1){ |
| 79 | + TEST_SPI_PORT(mySPI); |
| 80 | + delay(500); |
| 81 | + } |
| 82 | +} |
| 83 | + |
| 84 | +int test_byte_transfer( SPIClass &spi ){ |
| 85 | + uint8_t tx = random(1, 256); |
| 86 | + uint8_t rx = 0x00; |
| 87 | + spi.beginTransaction(SPISettings(SPI_FREQ, SPI_ORDER, SPI_MODE)); |
| 88 | + rx = spi.transfer(tx); |
| 89 | + spi.endTransaction(); |
| 90 | + if(rx != tx){ |
| 91 | + return -1; |
| 92 | + } |
| 93 | + return 0; |
| 94 | +} |
| 95 | + |
| 96 | +int test_buffer_transfer( SPIClass &spi ){ |
| 97 | + const size_t len = 10; |
| 98 | + uint8_t tx_buff[len]; |
| 99 | + uint8_t mirror[len]; |
| 100 | + for(size_t idx = 0; idx < len; idx++){ |
| 101 | + tx_buff[idx] = random(1, 256); |
| 102 | + mirror[idx] = tx_buff[idx]; |
| 103 | + } |
| 104 | + spi.beginTransaction(SPISettings(SPI_FREQ, SPI_ORDER, SPI_MODE)); |
| 105 | + spi.transfer(tx_buff, len); |
| 106 | + spi.endTransaction(); |
| 107 | + bool mismatched = false; |
| 108 | + for(size_t idx = 0; idx < len; idx++){ |
| 109 | + if(tx_buff[idx] != mirror[idx]){ |
| 110 | + mismatched = true; |
| 111 | + } |
| 112 | + } |
| 113 | + if(mismatched){ |
| 114 | + return -1; |
| 115 | + } |
| 116 | + return 0; |
| 117 | +} |
| 118 | + |
| 119 | +void setup() { |
| 120 | + SERIAL_PORT.begin(115200); |
| 121 | + SERIAL_PORT.println("Apollo3 - Simple SPI"); |
| 122 | + |
| 123 | + pinMode(LED_BUILTIN, OUTPUT); |
| 124 | + pinMode(CS_PIN, OUTPUT); |
| 125 | + digitalWrite(CS_PIN, HIGH); |
| 126 | + |
| 127 | + spi_thread.start(spi_thread_fn); |
| 128 | + myspi_thread.start(myspi_thread_fn); |
| 129 | +} |
| 130 | + |
| 131 | +void loop() { |
| 132 | + digitalWrite(LED_BUILTIN, HIGH); |
| 133 | + delay(500); |
| 134 | + digitalWrite(LED_BUILTIN, LOW); |
| 135 | + delay(500); |
| 136 | +} |
0 commit comments