diff options
Diffstat (limited to 'wirish')
| -rw-r--r-- | wirish/boards/maple.h | 13 | ||||
| -rw-r--r-- | wirish/boards/maple_RET6.h | 10 | ||||
| -rw-r--r-- | wirish/boards/maple_mini.h | 10 | ||||
| -rw-r--r-- | wirish/boards/maple_native.cpp | 2 | ||||
| -rw-r--r-- | wirish/boards/maple_native.h | 21 | ||||
| -rw-r--r-- | wirish/comm/HardwareSPI.cpp | 335 | ||||
| -rw-r--r-- | wirish/comm/HardwareSPI.h | 178 | 
7 files changed, 454 insertions, 115 deletions
| diff --git a/wirish/boards/maple.h b/wirish/boards/maple.h index 4a4465c..4b55f7a 100644 --- a/wirish/boards/maple.h +++ b/wirish/boards/maple.h @@ -52,6 +52,19 @@  #define BOARD_USART3_TX_PIN     29  #define BOARD_USART3_RX_PIN     30 +/* Number of SPI ports */ +#define BOARD_NR_SPI            2 + +/* Default SPI pin numbers (not considering AFIO remap) */ +#define BOARD_SPI1_NSS_PIN      10 +#define BOARD_SPI1_MOSI_PIN     11 +#define BOARD_SPI1_MISO_PIN     12 +#define BOARD_SPI1_SCK_PIN      13 +#define BOARD_SPI2_NSS_PIN      31 +#define BOARD_SPI2_MOSI_PIN     34 +#define BOARD_SPI2_MISO_PIN     33 +#define BOARD_SPI2_SCK_PIN      32 +  /* Total number of GPIO pins that are broken out to headers and   * intended for general use. */  #define BOARD_NR_GPIO_PINS      44 diff --git a/wirish/boards/maple_RET6.h b/wirish/boards/maple_RET6.h index 97e609d..4195857 100644 --- a/wirish/boards/maple_RET6.h +++ b/wirish/boards/maple_RET6.h @@ -55,6 +55,16 @@  #define BOARD_USART3_TX_PIN     29  #define BOARD_USART3_RX_PIN     30 +#define BOARD_NR_SPI            2 +#define BOARD_SPI1_NSS_PIN      10 +#define BOARD_SPI1_MOSI_PIN     11 +#define BOARD_SPI1_MISO_PIN     12 +#define BOARD_SPI1_SCK_PIN      13 +#define BOARD_SPI2_NSS_PIN      31 +#define BOARD_SPI2_MOSI_PIN     34 +#define BOARD_SPI2_MISO_PIN     33 +#define BOARD_SPI2_SCK_PIN      32 +  #define BOARD_NR_GPIO_PINS      44  #define BOARD_NR_PWM_PINS       16  #define BOARD_NR_ADC_PINS       15 diff --git a/wirish/boards/maple_mini.h b/wirish/boards/maple_mini.h index 3df1da8..fde7f98 100644 --- a/wirish/boards/maple_mini.h +++ b/wirish/boards/maple_mini.h @@ -54,6 +54,16 @@  #define BOARD_USART3_TX_PIN       1  #define BOARD_USART3_RX_PIN       0 +#define BOARD_NR_SPI              2 +#define BOARD_SPI1_NSS_PIN        7 +#define BOARD_SPI1_MOSI_PIN       4 +#define BOARD_SPI1_MISO_PIN       5 +#define BOARD_SPI1_SCK_PIN        6 +#define BOARD_SPI2_NSS_PIN        31 +#define BOARD_SPI2_MOSI_PIN       28 +#define BOARD_SPI2_MISO_PIN       29 +#define BOARD_SPI2_SCK_PIN        30 +  #define BOARD_NR_GPIO_PINS        34  #define BOARD_NR_PWM_PINS         12  #define BOARD_NR_ADC_PINS         10 diff --git a/wirish/boards/maple_native.cpp b/wirish/boards/maple_native.cpp index ab8b282..c1f8d5c 100644 --- a/wirish/boards/maple_native.cpp +++ b/wirish/boards/maple_native.cpp @@ -171,7 +171,7 @@ extern const uint8 boardADCPins[BOARD_NR_ADC_PINS] __FLASH__ = {      54, 55  }; -/* FIXME! see comment by BOARD_NR_USED_PINS in maple_native.h */ +/* FIXME [0.0.10] see comment by BOARD_NR_USED_PINS in maple_native.h */  extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = {      BOARD_LED_PIN, BOARD_BUTTON_PIN, BOARD_JTMS_SWDIO_PIN,      BOARD_JTCK_SWCLK_PIN, BOARD_JTDI_PIN, BOARD_JTDO_PIN, BOARD_NJTRST_PIN diff --git a/wirish/boards/maple_native.h b/wirish/boards/maple_native.h index 13df153..2cbd406 100644 --- a/wirish/boards/maple_native.h +++ b/wirish/boards/maple_native.h @@ -58,12 +58,27 @@  #define BOARD_UART5_TX_PIN      21  #define BOARD_UART5_RX_PIN      29 +#define BOARD_NR_SPI            3 +#define BOARD_SPI1_NSS_PIN      52 +#define BOARD_SPI1_MOSI_PIN     55 +#define BOARD_SPI1_MISO_PIN     54 +#define BOARD_SPI1_SCK_PIN      53 +#define BOARD_SPI2_NSS_PIN      2 +#define BOARD_SPI2_MOSI_PIN     5 +#define BOARD_SPI2_MISO_PIN     4 +#define BOARD_SPI2_SCK_PIN      3 +#define BOARD_SPI3_NSS_PIN      103 +#define BOARD_SPI3_MOSI_PIN     37 +#define BOARD_SPI3_MISO_PIN     105 +#define BOARD_SPI3_SCK_PIN      104 +  #define BOARD_NR_GPIO_PINS      106  #define BOARD_NR_PWM_PINS       18  #define BOARD_NR_ADC_PINS       21 -/* FIXME! this isn't true at all; almost all of the triple header pins - * are used by the FSMC by default.  Fix this (and the corresponding - * boardUsedPins definition in maple_native.cpp) by QA time. */ +/* FIXME [0.0.10] this isn't true at all; almost all of the triple + * header pins are used by the FSMC by default.  Fix this (and the + * corresponding boardUsedPins definition in maple_native.cpp) by QA + * time. */  #define BOARD_NR_USED_PINS      7  #define BOARD_JTMS_SWDIO_PIN    101 diff --git a/wirish/comm/HardwareSPI.cpp b/wirish/comm/HardwareSPI.cpp index aea7734..1b36d21 100644 --- a/wirish/comm/HardwareSPI.cpp +++ b/wirish/comm/HardwareSPI.cpp @@ -23,120 +23,283 @@   *****************************************************************************/  /** - * @brief HardwareSPI "wiring-like" api for SPI + * @author Marti Bolivar <mbolivar@leaflabs.com> + * @brief Wirish SPI implementation.   */ -/* NOTES: - * - * Speeds: - * ----------------------------------- - * Interface num:     SPI1        SPI2 - * Bus                APB2        APB1 - * ----------------------------------- - * Prescaler         Frequencies - * ----------------------------------- - * 2:                  N/A  18 000 000 - * 4:           18 000 000   9 000 000 - * 8:            9 000 000   4 500 000 - * 16:           4 500 000   2 250 000 - * 32:           2 250 000   1 125 000 - * 64:           1 125 000     562 500 - * 128:            562 500     281 250 - * 256:            281 250     140 625 - * - * TODO: Do the complementary PWM outputs mess up SPI2? - * */ +#include "HardwareSPI.h" -#include "spi.h"  #include "timer.h" +#include "util.h"  #include "wirish.h" -#include "HardwareSPI.h" +#include "boards.h" -static const uint32 prescaleFactors[MAX_SPI_FREQS] = { -    SPI_PRESCALE_2,               // SPI_18MHZ -    SPI_PRESCALE_4,               // SPI_9MHZ -    SPI_PRESCALE_8,               // SPI_4_5MHZ -    SPI_PRESCALE_16,              // SPI_2_25MHZ -    SPI_PRESCALE_32,              // SPI_1_125MHZ -    SPI_PRESCALE_64,              // SPI_562_500KHZ -    SPI_PRESCALE_128,             // SPI_281_250KHZ -    SPI_PRESCALE_256,             // SPI_140_625KHZ -}; +static void enable_device(spi_dev *dev, +                          bool as_master, +                          SPIFrequency frequency, +                          spi_cfg_flag endianness, +                          spi_mode mode); -/** - * @brief Initialize a SPI peripheral - * @param freq frequency to run at, must one of the following values: - *           - SPI_18MHZ - *           - SPI_9MHZ - *           - SPI_4_5MHZ - *           - SPI_2_25MHZ - *           - SPI_1_125MHZ - *           - SPI_562_500KHZ - *           - SPI_281_250KHZ - *           - SPI_140_625KHZ - * @param endianness endianness of the data frame, must be either LSBFIRST - *           or MSBFIRST - * @param mode SPI standard CPOL and CPHA levels +/* + * Constructor, public methods   */ -void HardwareSPI::begin(SPIFrequency freq, uint32 endianness, uint32 mode) { -    uint32 spi_num    = this->spi_num; -    uint32 prescale; - -    if ((freq >= MAX_SPI_FREQS)     || -        !((endianness == LSBFIRST)  || -          (endianness == MSBFIRST)) || -        (mode >= 4)) { + +HardwareSPI::HardwareSPI(uint32 spi_num) { +    switch (spi_num) { +    case 1: +        this->spi_d = SPI1; +        break; +    case 2: +        this->spi_d = SPI2; +        break; +#ifdef STM32_HIGH_DENSITY +    case 3: +        this->spi_d = SPI3; +        break; +#endif +    default: +        ASSERT(0); +    } +} + +void HardwareSPI::begin(SPIFrequency frequency, uint32 bitOrder, uint32 mode) { +    if (mode >= 4) { +        ASSERT(0);          return;      } +    spi_cfg_flag end = bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB; +    spi_mode m = (spi_mode)mode; +    enable_device(this->spi_d, true, frequency, end, m); +} -    if (spi_num == 1) { -        /* SPI1 is too fast for 140625  */ -        if (freq == SPI_140_625KHZ) { -            return; -        } +void HardwareSPI::begin(void) { +    this->begin(SPI_1_125MHZ, MSBFIRST, 0); +} -        /* Turn off PWM on shared pins */ -        timer_set_mode(TIMER3, 2, TIMER_DISABLED); -        timer_set_mode(TIMER3, 1, TIMER_DISABLED); +void HardwareSPI::beginSlave(uint32 bitOrder, uint32 mode) { +    if (mode >= 4) { +        ASSERT(0); +        return;      } +    spi_cfg_flag end = bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB; +    spi_mode m = (spi_mode)mode; +    enable_device(this->spi_d, false, (SPIFrequency)0, end, m); +} -    endianness = (endianness == LSBFIRST) ? SPI_LSBFIRST : SPI_MSBFIRST; -    prescale = (spi_num == 1) ? -        prescaleFactors[freq + 1] : -        prescaleFactors[freq]; +void HardwareSPI::beginSlave(void) { +    this->beginSlave(MSBFIRST, 0); +} -    spi_init(spi_num, prescale, endianness, mode); +void HardwareSPI::end(void) { +    if (!spi_is_enabled(this->spi_d)) { +        return; +    } + +    // Follows RM0008's sequence for disabling a SPI in master/slave +    // full duplex mode. +    while (spi_is_rx_nonempty(this->spi_d)) { +        // FIXME [0.1.0] remove this once you have an interrupt based driver +        volatile uint16 rx __attribute__((unused)) = spi_rx_reg(this->spi_d); +    } +    while (!spi_is_tx_empty(this->spi_d)) +        ; +    while (spi_is_busy(this->spi_d)) +        ; +    spi_peripheral_disable(this->spi_d);  } -/** - * @brief Initialize a SPI peripheral with a default speed of 1.125 - *      MHZ, MSBFIRST, mode 0 - */ -void HardwareSPI::begin(void) { -   begin(SPI_1_125MHZ, MSBFIRST, 0); +uint8 HardwareSPI::read(void) { +    uint8 buf[1]; +    this->read(buf, 1); +    return buf[0];  } -/** - * @brief send a byte out the spi peripheral - * @param data byte to send +void HardwareSPI::read(uint8 *buf, uint32 len) { +    uint32 rxed = 0; +    while (rxed < len) { +        while (!spi_is_rx_nonempty(this->spi_d)) +            ; +        buf[rxed++] = (uint8)spi_rx_reg(this->spi_d); +    } +} + +void HardwareSPI::write(uint8 byte) { +    uint8 buf[] = {byte}; +    this->write(buf, 1); +} + +void HardwareSPI::write(uint8 *data, uint32 length) { +    uint32 txed = 0; +    while (txed < length) { +        txed += spi_tx(this->spi_d, data + txed, length - txed); +    } +} + +uint8 HardwareSPI::transfer(uint8 byte) { +    this->write(byte); +    return this->read(); +} + +/* + * Deprecated functions   */ +  uint8 HardwareSPI::send(uint8 data) { -   return spi_tx_byte(this->spi_num, data); +    uint8 buf[] = {data}; +    return this->send(buf, 1);  }  uint8 HardwareSPI::send(uint8 *buf, uint32 len) { -   return spi_tx(this->spi_num, buf, len); +    if (len == 0) { +        ASSERT(0); +        return 0; +    } +    uint32 txed = 0; +    uint8 ret = 0;              // shut up, GCC +    while (txed < len) { +        this->write(buf[txed++]); +        ret = this->read(); +    } +    return ret;  } -/** - * @brief read a byte from the spi peripheral - * @return byte in the buffer - */  uint8 HardwareSPI::recv(void) { -   return spi_rx(this->spi_num); +    return this->read();  } -HardwareSPI::HardwareSPI(uint32 spi_num) { -   this->spi_num = spi_num; +/* + * Auxiliary functions + */ + +static void configure_gpios(spi_dev *dev, bool as_master); +static spi_baud_rate determine_baud_rate(spi_dev *dev, SPIFrequency freq); + +/* Enables the device in master or slave full duplex mode.  If you + * change this code, you must ensure that appropriate changes are made + * to HardwareSPI::end(). */ +static void enable_device(spi_dev *dev, +                          bool as_master, +                          SPIFrequency freq, +                          spi_cfg_flag endianness, +                          spi_mode mode) { +    if (freq >= MAX_SPI_FREQS) { +        ASSERT(0); +        return; +    } + +    spi_baud_rate baud = determine_baud_rate(dev, freq); +    uint32 cfg_flags = (endianness | SPI_DFF_8_BIT | SPI_SW_SLAVE | +                        (as_master ? SPI_SOFT_SS : 0)); + +    spi_init(dev); +    configure_gpios(dev, as_master); +    if (as_master) { +        spi_master_enable(dev, baud, mode, cfg_flags); +    } else { +        spi_slave_enable(dev, mode, cfg_flags); +    } +} + +static void disable_pwm(const stm32_pin_info *i) { +    if (i->timer_device) { +        timer_set_mode(i->timer_device, i->timer_channel, TIMER_DISABLED); +    } +} + +typedef struct spi_pins { +    uint8 nss; +    uint8 sck; +    uint8 miso; +    uint8 mosi; +} spi_pins; + +static void configure_gpios(spi_dev *dev, bool as_master) { +    const spi_pins spi_pin_config[] = { +        {BOARD_SPI1_NSS_PIN, +         BOARD_SPI1_SCK_PIN, +         BOARD_SPI1_MISO_PIN, +         BOARD_SPI1_MOSI_PIN}, +        {BOARD_SPI2_NSS_PIN, +         BOARD_SPI2_SCK_PIN, +         BOARD_SPI2_MISO_PIN, +         BOARD_SPI2_MOSI_PIN}, +#ifdef STM32_HIGH_DENSITY +        {BOARD_SPI3_NSS_PIN, +         BOARD_SPI3_SCK_PIN, +         BOARD_SPI3_MISO_PIN, +         BOARD_SPI3_MOSI_PIN}, +#endif +    }; + +    const spi_pins *pins; + +    switch (dev->clk_id) { +    case RCC_SPI1: +        pins = &spi_pin_config[0]; +        break; +    case RCC_SPI2: +        pins = &spi_pin_config[1]; +        break; +#ifdef STM32_HIGH_DENSITY +    case RCC_SPI3: +        pins = &spi_pin_config[2]; +        break; +#endif +    default: +        ASSERT(0); +        return; +    } + +    const stm32_pin_info *nssi = &PIN_MAP[pins->nss]; +    const stm32_pin_info *scki = &PIN_MAP[pins->sck]; +    const stm32_pin_info *misoi = &PIN_MAP[pins->miso]; +    const stm32_pin_info *mosii = &PIN_MAP[pins->mosi]; + +    disable_pwm(nssi); +    disable_pwm(scki); +    disable_pwm(misoi); +    disable_pwm(mosii); + +    if (as_master) { +        spi_master_gpio_cfg(nssi->gpio_device, +                            scki->gpio_device, +                            nssi->gpio_bit, +                            scki->gpio_bit, +                            misoi->gpio_bit, +                            mosii->gpio_bit); +    } else { +        spi_slave_gpio_cfg(nssi->gpio_device, +                           scki->gpio_device, +                           nssi->gpio_bit, +                           scki->gpio_bit, +                           misoi->gpio_bit, +                           mosii->gpio_bit); +    } +} + +static const spi_baud_rate baud_rates[MAX_SPI_FREQS] __FLASH__ = { +    SPI_BAUD_PCLK_DIV_2, +    SPI_BAUD_PCLK_DIV_4, +    SPI_BAUD_PCLK_DIV_8, +    SPI_BAUD_PCLK_DIV_16, +    SPI_BAUD_PCLK_DIV_32, +    SPI_BAUD_PCLK_DIV_64, +    SPI_BAUD_PCLK_DIV_128, +    SPI_BAUD_PCLK_DIV_256, +}; + +/* + * Note: This assumes you're on a LeafLabs-style board + * (CYCLES_PER_MICROSECOND == 72, APB2 at 72MHz, APB1 at 36MHz). + */ +static spi_baud_rate determine_baud_rate(spi_dev *dev, SPIFrequency freq) { +    if (rcc_dev_clk(dev->clk_id) == RCC_APB2 && freq == SPI_140_625KHZ) { +        /* APB2 peripherals are too fast for 140.625 KHz */ +        ASSERT(0); +        return (spi_baud_rate)~0; +    } +    return (rcc_dev_clk(dev->clk_id) == RCC_APB2 ? +            baud_rates[freq + 1] : +            baud_rates[freq]);  } diff --git a/wirish/comm/HardwareSPI.h b/wirish/comm/HardwareSPI.h index 7241d0b..1b2a966 100644 --- a/wirish/comm/HardwareSPI.h +++ b/wirish/comm/HardwareSPI.h @@ -3,60 +3,188 @@   *   * Copyright (c) 2010 Perry Hung.   * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is   * furnished to do so, subject to the following conditions:   * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software.   * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE.   *****************************************************************************/  /** - * @brief HardwareSPI definitions + * @file HardwareSPI.h + * @brief High-level SPI interface + * + * This is a "bare essentials" polling driver for now.   */ +/* TODO [0.1.0] Remove deprecated methods. */ + +#include "libmaple_types.h" +#include "spi.h" + +#include "boards.h" +  #ifndef _HARDWARESPI_H_  #define _HARDWARESPI_H_  /** - * Defines the possible SPI communication speeds. + * @brief Defines the possible SPI communication speeds.   */  typedef enum SPIFrequency {      SPI_18MHZ       = 0, /**< 18 MHz */      SPI_9MHZ        = 1, /**< 9 MHz */      SPI_4_5MHZ      = 2, /**< 4.5 MHz */ -    SPI_2_25MHZ     = 3, /**< 2.25 MHZ */ +    SPI_2_25MHZ     = 3, /**< 2.25 MHz */      SPI_1_125MHZ    = 4, /**< 1.125 MHz */      SPI_562_500KHZ  = 5, /**< 562.500 KHz */      SPI_281_250KHZ  = 6, /**< 281.250 KHz */      SPI_140_625KHZ  = 7, /**< 140.625 KHz */ -    MAX_SPI_FREQS   = 8, /**< The number of SPI frequencies. */  } SPIFrequency; -/* Documented by hand in docs/source/lang/api/hardwarespi.rst; if you -   make any changes, make sure to update this document. */ +#define MAX_SPI_FREQS 8 + +#if CYCLES_PER_MICROSECOND != 72 +/* TODO [0.2.0?] something smarter than this */ +#warn "Unexpected clock speed; SPI frequency calculation will be incorrect" +#endif + +/** + * @brief Wirish SPI interface. + * + * This implementation uses software slave management, so the caller + * is responsible for controlling the slave select line. + */  class HardwareSPI { - private: -    uint32 spi_num; +public: +    /** +     * @param spiPortNumber Number of the SPI port to manage. +     */ +    HardwareSPI(uint32 spiPortNumber); + +    /** +     * @brief Turn on a SPI port and set its GPIO pin modes for use as master. +     * +     * SPI port is enabled in full duplex mode, with software slave management. +     * +     * @param frequency Communication frequency +     * @param bitOrder Either LSBFIRST (little-endian) or MSBFIRST (big-endian) +     * @param mode SPI mode to use, one of SPI_MODE_0, SPI_MODE_1, +     *             SPI_MODE_2, and SPI_MODE_3. +     */ +    void begin(SPIFrequency frequency, uint32 bitOrder, uint32 mode); - public: -    HardwareSPI(uint32 spi_num); +    /** +     * @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0). +     */      void begin(void); -    void begin(SPIFrequency freq, uint32 endianness, uint32 mode); + +    /** +     * @brief Turn on a SPI port and set its GPIO pin modes for use as a slave. +     * +     * SPI port is enabled in full duplex mode, with software slave management. +     * +     * @param bitOrder Either LSBFIRST (little-endian) or MSBFIRST(big-endian) +     * @param mode SPI mode to use +     */ +    void beginSlave(uint32 bitOrder, uint32 mode); + +    /** +     * @brief Equivalent to beginSlave(MSBFIRST, 0). +     */ +    void beginSlave(void); + +    /** +     * @brief Disables the SPI port, but leaves its GPIO pin modes unchanged. +     */ +    void end(void); + +    /** +     * @brief Return the next unread byte. +     * +     * If there is no unread byte waiting, this function will block +     * until one is received. +     */ +    uint8 read(void); + +    /** +     * @brief Read length bytes, storing them into buffer. +     * @param buffer Buffer to store received bytes into. +     * @param length Number of bytes to store in buffer.  This +     *               function will block until the desired number of +     *               bytes have been read. +     */ +    void read(uint8 *buffer, uint32 length); + +    /** +     * @brief Transmit a byte. +     * @param data Byte to transmit. +     */ +    void write(uint8 data); + +    /** +     * @brief Transmit multiple bytes. +     * @param buffer Bytes to transmit. +     * @param length Number of bytes in buffer to transmit. +     */ +    void write(uint8 *buffer, uint32 length); + +    /** +     * @brief Transmit a byte, then return the next unread byte. +     * +     * This function transmits before receiving. +     * +     * @param data Byte to transmit. +     * @return Next unread byte. +     */ +    uint8 transfer(uint8 data); + +    /* -- The following methods are deprecated --------------------------- */ + +    /** +     * @brief Deprecated. +     * +     * Use HardwareSPI::transfer() instead. +     * +     * @see HardwareSPI::transfer() +     */      uint8 send(uint8 data); + +    /** +     * @brief Deprecated. +     * +     * Use HardwareSPI::write() in combination with +     * HardwareSPI::read() (or HardwareSPI::transfer()) instead. +     * +     * @see HardwareSPI::write() +     * @see HardwareSPI::read() +     * @see HardwareSPI::transfer() +     */      uint8 send(uint8 *data, uint32 length); + +    /** +     * @brief Deprecated. +     * +     * Use HardwareSPI::read() instead. +     * +     * @see HardwareSPI::read() +     */      uint8 recv(void); +private: +    spi_dev *spi_d;  };  #endif | 
