This is the multi-page printable view of this section. Click here to print...

Return to the regular view of this page

As of 2025-09-10

mwf_periph_spi - SPI

mwf_periph_spi - SPI
    This is a class object for using the SPI bus.

    mwf_periph_spi - SPI

    This implements the_spi1, a class object for using the SPI bus.

    • SPI0 support is not included in the code.
    • Some definitions are included for non-blocking operations, but only blocking APIs are available in the current version.

    Code Example

    #include "mwf_periph_spi.hpp"
    
    void func_spi_init() {
        if (!mwf::the_spi1) {
            mwf::spi::global_init_spi1_manager();
            Serial << crlf << "the_spi1 constructed.";
        }
    
        mwf::spi::config conf{};
        conf.baud = 4000000UL; // 4MHz
        conf.bits = 8;         // 8bit
        conf.dir  = mwf::spi::E_SPI_DIR::MSB_FIRST;
        conf.mode = mwf::spi::E_SPI_MODE::MODE_3_INV_RISE;
        conf.pin_ssel[0] = mwf::spi::E_PIN_SSEL::SSEL0_PIO3;
        conf.pin_ssel[1] = mwf::spi::E_PIN_SSEL::SSEL1_PIO16;
        mwf::the_spi1->init(conf);
    }
    
    void func_spi_transfer() {
        uint8_t tx[16] = { 0xa5, 0x5a, 0x11, 0x88 }; // data to transmit
        uint8_t rx[16];                              // receive buffer
    
        mwf::the_spi1->ssel_select(0);
        mwf::the_spi1->transfer_blocking(tx, rx, 4); // four bytes transfer
        CLOCK_uDelay(5); // wait 5us
        mwf::the_spi1->transfer_blocking(tx, rx, 4); // four bytes transfer
        mwf::the_spi1->ssel_deselect();
    }

    class mwf::periph::spi

    struct config

    The mwf::periph::spi::config structure is defined as follows:

    struct config {
        // evaluated only in init()
        E_PIN_MAIN pin_conf;    // master pin configuration (so far not used)
        E_PIN_SSEL pin_ssel[3]; // SSEL0..2 (assignment settings for slave select pins.
                                // At least pin_ssel[0] shall be configured.
    
        // evaluated in conf(), reconf()
        uint32_t baud;      // SPI frequency (default 50Mhz)
        E_SPI_DIR dir;      // transfer LSB first
        E_SPI_MODE mode;	// SPI mode (clock polarity and detect edge)
        uint8_t bits;       // bit width (0:default=8, ...)
        uint8_t ssel;       // 0..3 or 0x80..0x80 (if MSB is set, assert/deassert SSEL automatically)
    };

    You set values in the structure and call init(). The structure’s settings are copied internally during the init() call, so you can discard the structure’s memory area afterward.

    Here is an explanation of each member of the structure:

    Signal NameDescription
    pin_confSpecifies the pin assignment (primary or alternate). If E_PIN_CONF::NODEF (=0) is selected, the setting from global_init_spi1_manager() is used.
    pin_ssel[3]Specifies the SELECT pins. Index 0 of the array specifies the pin for SPI SELECT 0 (SSEL0), index 1 for SSEL1, and index 2 for SSEL2. SSEL0 must always be specified, while SSEL1 and SSEL2 should be set to E_PIN_SSEL::SSEL_VOID=0. If you use two types of pins, specify SSEL0 and SSEL1; if you use three, store values in all of them.
    *Note: If you specify a software-controlled pin (e.g., E_PIN_SSEL::SSEL0_PIO3), all select pins will be software-controlled. With software control, the pins are set to a continuous HIGH level output and change to a LOW level when selected. TWENETcmpt (AHI library compatible) uses software control.
    *Note: With hardware control, the SELECT pin control follows the behavior of SPI_MasterTransferNonBlocking() in fsl_spi.c.
    baudSpecifies the SPI clock frequency. It can be set up to 32MHz, but frequencies around 1MHz are often used for sensor devices.<br />(Behavior follows spi_master_config_t::bandRate_Bps in fsl_spi.h and SPI_MasterSetBaud() in fsl_spi.c)
    modeSPISEL is specified in init().
    bitsThis is the transfer unit. 8 is usually specified. It can be set from 1 to 16. If 9 bits or more are specified, the byte array for data transfer is read in 2-byte units, requiring twice the amount of data. The first byte represents 8 bits from the LSB, and the second byte represents the remaining bits.
    (Behavior follows SPI_MasterTransferBlocking() in fsl_spi.h)
    sselThis is the SPI SELECT. Specify 0 to 2.

    enum class E_PIN_CONF

    enum class E_PIN_CONF : uint8_t {
        NODEF = 0,   // Not specified
        PRIMARY = 1, // Primary assignment (PIO10/11)
        ALT = 2      // Alternate assignment (PIO15/16)
    };
    // Type for assignments, comparisons, etc. between enum class and int types.
    using wE_PIN_CONF = mwf::enum_wapper<E_PIN_CONF>;

    This is an enumeration for specifying pin assignments.

    enum class E_PIN_SSEL

    enum class E_PIN_SSEL : uint8_t {
        SSEL_VOID = 0, // Undefined
        SSEL_PRIMARY,  // Primary setting pin
        SSEL_ALT,      // Alternate setting pin
        SSEL_SOFT = 0x10,
        SSEL0_PIO3,  // SSEL0 is software-controlled, using PIO3
        SSEL1_PIO16, // SSEL1 is software-controlled, using PIO16
        SSEL2_PIO17, // SSEL2 is software-controlled, using PIO17
        SSEL1_PIO4,  // SSEL1 is software-controlled, using PIO4
        SSEL2_PIO13, // SSEL2 is software-controlled, using PIO13
    };

    This enumeration determines the arrangement of the SPI SELECT pins. The corresponding value is stored in spi::config::pin_ssel[3].

    • Set pin_ssel[] according to the number of devices used.

      • For one device, set pin_ssel[0]. pin_ssel[1] and pin_ssel[2] should be SSEL_VOID.
      • For two devices, set pin_ssel[0] and pin_ssel[1]. pin_ssel[2] should be SSEL_VOID.
      • For three devices, set pin_ssel[0], pin_ssel[1], and pin_ssel[2].
    • To specify hardware control, use SSEL_PRIMARY or SSEL_ALT (and SSEL_VOID). If you mix them, it will result in software control.

    enum class E_SPI_DIR

    enum class E_SPI_DIR {
        MSB_FIRST = 0,
        LSB_FIRST
    };

    This specifies the bit order. MSB_FIRST is typically used.

    enum class E_SPI_MODE

    enum class E_SPI_MODE {
        MODE_0_RISE = 0,
        MODE_1_FALL = 1,
        MODE_2_INV_FALL = 2,
        MODE_3_INV_RISE = 3,
    };

    This specifies the SPI transfer mode. It determines the clock’s detection edge and whether the H/L value at that time is 0 or 1. Set this according to the connected device’s datasheet.

    global_init_spi1_manager(), global_deinit_spi1_manager()

    static void global_init_spi1_manager(E_PIN_MAIN pin_conf = E_PIN_MAIN::PRIMARY);
    static void global_deinit_spi1_manager();

    These functions create and destroy the class object for using the SPI1 bus. During class object creation, you select the pin combination to use with pin_conf. You can specify E_PIN_MAIN::PRIMARY (value 0) or E_PIN_MAIN::ALT (value 1) for the pin configuration.

    init()

    void init();
    void init(spi::config& cnf);
    void init(spi::config&& cnf);

    This function initializes the SPI bus. By providing the cnf parameter, you can set several configurations. If the parameter is omitted, it re-initializes with the previous settings.

    • Even if you are software-controlling the select pin in your user program, you must specify at least one. The specified pin will be configured as a GPIO output. By calling unset_ssel_auto(), the library will no longer control that pin.

    reconf()

    void reconf();

    This function re-applies the peripheral parameters. To access the internal settings, use spi::config& get_conf(). Pin settings (pin_ssel[]) are not reflected by this procedure.

    set_data_width()

    void set_data_width(uint8_t bits);

    This function changes the transfer data width. It is a lighter procedure than reconf().

    set|unset|get_ssel_auto()

    void set_ssel_auto();
    void unset_ssel_auto();
    bool get_ssel_auto();

    Sets, unsets, and gets the automatic control flag for the select pin.

    • This is only effective when using software control.
    • When transfer_blocking() is called, the SELECT pin is automatically set to LOW. It is set back to HIGH upon completion.

    ssel_select()

    void ssel_select(uint8_t select);

    This function specifies the select pin. select takes values of 0, 1, or 2, corresponding to SSEL0 through SSEL2.

    • With hardware or software control and the automatic control flag (set_ssel_auto()) enabled, pin control is performed when the transfer API is called.
    • With software control, regardless of the automatic control flag, the SELECT pin is set to LOW immediately after the ssel_select() call.
    • With hardware control, it calls reconf() to re-initialize. This process has a high time cost, so if you frequently switch between devices for transfers, please use software control.

    ssel_deselect()

    void ssel_deselect();

    This function deselects the select pins.

    • With software control, all select pins are returned to a HIGH level.
    • With hardware control, it does nothing.
    • It does not change the pin specification from ssel_select().

    Other

    bool has_init(); // Returns true if init() has been executed
    spi::config& get_conf(); // Accesses internally stored configuration information
    

    Pin Assignments

    For E_PIN_CONF::PRIMARY

    SignalPIO NumberDescription
    SCK0Clock signal
    MOSI2SPIMOSI. TWELITE side is output, external SPI device side is input.
    MISO5SPIMISO. TWELITE side is input, external SPI device side is output.

    Select Pins

    pin_sselE_PIN_SSELPIORemarks
    SSEL0 pin_ssel[0]SSEL_PRIMARY3
    SSEL_ALT16
    SSEL0_PIO33Software-controlled
    SSEL0_PIO1616Software-controlled
    SSEL1 pin_ssel[1]SSEL_PRIMARY4
    SSEL_ALT14
    SSEL1_PIO44Software-controlled
    SSEL1_PIO1414Software-controlled
    SSEL1_PIO1616Software-controlled (Cannot specify SSEL0_PIO16)
    SSEL_VOIDOnly use SSEL0 for selection
    SSEL2 pin_ssel[2]SSEL_PRIMARY13
    SSEL2_PIO1313Software-controlled
    SSEL2_PIO1717Software-controlled
    SSEL_VOIDOnly use SSEL0 and SSEL1 for selection
    • A maximum of three select pins can be set in order from SSEL0 to SSEL1 and SSEL2.
    • If any of the pin_ssel[] specifications are for software control, all select pins will be software-controlled by the library.

    For E_PIN_CONF::ALT

    SignalPIO NumberDescription
    SCK15Clock signal
    MOSI17SPIMOSI. TWELITE side is output, external SPI device side is input.
    MISO18SPIMISO. TWELITE side is input, external SPI device side is output.

    Select Pins

    pin_sselE_PIN_SSELPIORemarks
    SSEL0 pin_ssel[0]SSEL_PRIMARY16
    SSEL_ALT3
    SSEL0_PIO33Software-controlled
    SSEL0_PIO1616Software-controlled
    SSEL1 pin_ssel[1]SSEL_PRIMARY14SSEL0 must be specified
    SSEL_ALT4
    SSEL1_PIO44Software-controlled
    SSEL1_PIO1414Software-controlled
    SSEL_VOIDOnly use SSEL0 for selection
    SSEL2 pin_ssel[2]SSEL_PRIMARY13
    SSEL_ALT5Note that this is also the PRG pin.
    SSEL2_PIO55Software-controlled. Note that this is also the PRG pin.
    SSEL2_PIO1313Software-controlled
    SSEL_VOIDOnly use SSEL0 and SSEL1 for selection
    • A maximum of three select pins can be set in order from SSEL0 to SSEL1 and SSEL2.
    • If any of the pin_ssel[] specifications are for software control, all select pins will be software-controlled by the library.

    class mwf::periph::spi (sys_ev_handler)

    on_sleep()

    As a procedure before sleep, the SPI is returned to an unused state. If it has been initialized by init(), this state is saved.

    on_wakeup()

    If it was in an initialized state before sleep, it is re-initialized so that the SPI bus can be used.