From 1c16368fe063b3e7ad6fe1077fe00859a0cc5a45 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 9 Jul 2019 16:56:00 -0600 Subject: [PATCH 1/7] Inital theory working --- libraries/SPI/src/SPI.cpp | 21 +++++++---- libraries/SPI/src/SPI.h | 79 ++++++++++++++++++++++----------------- 2 files changed, 58 insertions(+), 42 deletions(-) diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 4f441a1..8cc5863 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -206,6 +206,14 @@ void SPIClass::endTransaction(void) void SPIClass::setBitOrder(BitOrder order) { _order = order; + + //MSB/LSB is not exposed in the HAL v2.2 in a nice way + //This is a hack to set the SPILSB bit of the MSPICFG register + //Note that calling initialize() will overwrite the LSB bit + if (order == LSBFIRST) + { + AM_REGVAL(0x50004300 + ((uint32_t)0x1000 * _instance)) |= (1 << 23); + } } void SPIClass::setDataMode(uint8_t mode) @@ -214,14 +222,11 @@ void SPIClass::setDataMode(uint8_t mode) initialize(); } -// void SPIClass::setClockDivider(uint8_t div) -// { -// // if (div < SPI_MIN_CLOCK_DIVIDER) { -// // _p_sercom->setBaudrateSPI(SPI_MIN_CLOCK_DIVIDER); -// // } else { -// // _p_sercom->setBaudrateSPI(div); -// // } -// } +void SPIClass::setClockDivider(uint8_t div) +{ + _config.ui32ClockFreq = F_CPU / div; + initialize(); +} byte SPIClass::transfer(uint8_t data) { diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 8fef3ed..0c46216 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -38,34 +38,43 @@ #define SPI_MODE2 AM_HAL_IOM_SPI_MODE_2 #define SPI_MODE3 AM_HAL_IOM_SPI_MODE_3 -typedef enum{ +typedef enum +{ ap3_spi_tx_only = 1, ap3_spi_rx_only = 2, ap3_spi_full_duplex = 3, -}ap3_spi_duplex_e; - -class SPISettings { - public: - SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) { - if (__builtin_constant_p(clock)) { +} ap3_spi_duplex_e; + +class SPISettings +{ +public: + SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) + { + if (__builtin_constant_p(clock)) + { init_AlwaysInline(clock, bitOrder, dataMode); - } else { + } + else + { init_MightInline(clock, bitOrder, dataMode); } } // Default speed set to 4MHz, SPI mode set to MODE 0 and Bit order set to MSB first. - SPISettings() { - init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); + SPISettings() + { + init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); } - private: - public: // temporary - void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) { +private: +public: // temporary + void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) + { init_AlwaysInline(clock, bitOrder, dataMode); } - void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) __attribute__((__always_inline__)) { + void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) __attribute__((__always_inline__)) + { this->clockFreq = clock; this->bitOrder = bitOrder; this->dataMode = (am_hal_iom_spi_mode_e)dataMode; @@ -78,8 +87,9 @@ class SPISettings { friend class SPIClass; }; -class SPIClass : public IOMaster { - public: +class SPIClass : public IOMaster +{ +public: SPIClass(uint8_t iom_instance); SPIClass(uint8_t iom_instance, ap3_spi_duplex_e duplex); @@ -104,11 +114,12 @@ class SPIClass : public IOMaster { void setBitOrder(BitOrder order); void setDataMode(uint8_t uc_mode); - // void setClockDivider(uint8_t uc_div); + void setClockDivider(uint8_t div); + + void _transfer(void *buf_out = NULL, void *buf_in = NULL, size_t count = 0); private: void config(SPISettings settings); - void _transfer(void* buf_out = NULL, void* buf_in = NULL, size_t count = 0); // Bit Order (need a better way to handle this) BitOrder _order; @@ -117,9 +128,9 @@ class SPIClass : public IOMaster { ap3_spi_duplex_e _duplex; // Pads (for reference) - ap3_gpio_pin_t _padSCLK; - ap3_gpio_pin_t _padMOSI; - ap3_gpio_pin_t _padMISO; + ap3_gpio_pin_t _padSCLK; + ap3_gpio_pin_t _padMOSI; + ap3_gpio_pin_t _padMISO; // SERCOM *_p_sercom; // uint8_t _uc_pinMiso; @@ -136,34 +147,34 @@ class SPIClass : public IOMaster { }; #if SPI_INTERFACES_COUNT > 0 - extern SPIClass SPI; +extern SPIClass SPI; #endif #if SPI_INTERFACES_COUNT > 1 - extern SPIClass SPI1; +extern SPIClass SPI1; #endif #if SPI_INTERFACES_COUNT > 2 - extern SPIClass SPI2; +extern SPIClass SPI2; #endif #if SPI_INTERFACES_COUNT > 3 - extern SPIClass SPI3; +extern SPIClass SPI3; #endif #if SPI_INTERFACES_COUNT > 4 - extern SPIClass SPI4; +extern SPIClass SPI4; #endif #if SPI_INTERFACES_COUNT > 5 - extern SPIClass SPI5; +extern SPIClass SPI5; #endif // For compatibility with sketches designed for AVR @ 16 MHz // New programs should use SPI.beginTransaction to set the SPI clock #if F_CPU == 48000000 - #define SPI_CLOCK_DIV2 6 - #define SPI_CLOCK_DIV4 12 - #define SPI_CLOCK_DIV8 24 - #define SPI_CLOCK_DIV16 48 - #define SPI_CLOCK_DIV32 96 - #define SPI_CLOCK_DIV64 192 - #define SPI_CLOCK_DIV128 255 +#define SPI_CLOCK_DIV2 6 +#define SPI_CLOCK_DIV4 12 +#define SPI_CLOCK_DIV8 24 +#define SPI_CLOCK_DIV16 48 +#define SPI_CLOCK_DIV32 96 +#define SPI_CLOCK_DIV64 192 +#define SPI_CLOCK_DIV128 255 #endif #endif From a8924f373f951825c0b7d33610c78f8a53c92866 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 9 Jul 2019 16:56:55 -0600 Subject: [PATCH 2/7] Whitespace change to iomaster.cpp --- .../arduino/ard_sup/iomaster/ap3_iomaster.cpp | 310 ++++++++++++------ 1 file changed, 214 insertions(+), 96 deletions(-) diff --git a/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp b/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp index 098cb25..80642c8 100644 --- a/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp +++ b/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp @@ -20,137 +20,255 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - #include "ap3_iomaster.h" -IOMaster::IOMaster(uint8_t instance){ +IOMaster::IOMaster(uint8_t instance) +{ _instance = instance; } -ap3_err_t IOMaster::initialize( void ){ +ap3_err_t IOMaster::initialize(void) +{ return initialize(_config); } -ap3_err_t IOMaster::initialize(am_hal_iom_config_t config){ +ap3_err_t IOMaster::initialize(am_hal_iom_config_t config) +{ uint32_t retVal32 = 0; _config = config; am_hal_iom_disable(_handle); am_hal_iom_uninitialize(_handle); - + retVal32 = am_hal_iom_initialize(_instance, &_handle); - if (retVal32 != AM_HAL_STATUS_SUCCESS){ return AP3_ERR; } + if (retVal32 != AM_HAL_STATUS_SUCCESS) + { + return AP3_ERR; + } retVal32 = am_hal_iom_power_ctrl(_handle, AM_HAL_SYSCTRL_WAKE, false); - if (retVal32 != AM_HAL_STATUS_SUCCESS){ return AP3_ERR; } - + if (retVal32 != AM_HAL_STATUS_SUCCESS) + { + return AP3_ERR; + } + retVal32 = am_hal_iom_configure(_handle, &_config); - if (retVal32 != AM_HAL_STATUS_SUCCESS){ return AP3_ERR; } + if (retVal32 != AM_HAL_STATUS_SUCCESS) + { + return AP3_ERR; + } retVal32 = am_hal_iom_enable(_handle); - if (retVal32 != AM_HAL_STATUS_SUCCESS){ return AP3_ERR; } + if (retVal32 != AM_HAL_STATUS_SUCCESS) + { + return AP3_ERR; + } // Configure the IOM pins. (Must be done by the inherited classes [this is just a reminder]) } -ap3_err_t IOMaster::deinitialize( void ){ +ap3_err_t IOMaster::deinitialize(void) +{ uint32_t retVal32 = 0; - + retVal32 = am_hal_iom_disable(_handle); - if( retVal32 != AM_HAL_STATUS_SUCCESS){ return AP3_ERR; } + if (retVal32 != AM_HAL_STATUS_SUCCESS) + { + return AP3_ERR; + } retVal32 = am_hal_iom_uninitialize(_handle); - if( retVal32 != AM_HAL_STATUS_SUCCESS){ return AP3_ERR; } + if (retVal32 != AM_HAL_STATUS_SUCCESS) + { + return AP3_ERR; + } return AP3_OK; } - -ap3_err_t ap3_iom_pad_funcsel( uint8_t instance, ap3_iom_pad_type_e type, ap3_gpio_pad_t* pad, uint8_t* funcsel){ +ap3_err_t ap3_iom_pad_funcsel(uint8_t instance, ap3_iom_pad_type_e type, ap3_gpio_pad_t *pad, uint8_t *funcsel) +{ ap3_err_t retval = AP3_OK; - switch( instance ){ - case 0 : - switch( type ){ - case AP3_IOM_I2C_SCL : *pad = 5; *funcsel = AM_HAL_PIN_5_M0SCL; break; - case AP3_IOM_I2C_SDA : *pad = 6; *funcsel = AM_HAL_PIN_6_M0SDAWIR3; break; - case AP3_IOM_SPI_SCLK : *pad = 5; *funcsel = AM_HAL_PIN_5_M0SCK; break; - case AP3_IOM_SPI_MOSI : *pad = 7; *funcsel = AM_HAL_PIN_7_M0MOSI; break; - case AP3_IOM_SPI_MISO : *pad = 6; *funcsel = AM_HAL_PIN_6_M0MISO; break; - default : - goto invalid_args; - break; - } - break; - - case 1 : - switch( type ){ - case AP3_IOM_I2C_SCL : *pad = 8; *funcsel = AM_HAL_PIN_8_M1SCL; break; - case AP3_IOM_I2C_SDA : *pad = 9; *funcsel = AM_HAL_PIN_9_M1SDAWIR3; break; - case AP3_IOM_SPI_SCLK : *pad = 8; *funcsel = AM_HAL_PIN_8_M1SCK; break; - case AP3_IOM_SPI_MOSI : *pad = 10; *funcsel = AM_HAL_PIN_10_M1MOSI; break; - case AP3_IOM_SPI_MISO : *pad = 9; *funcsel = AM_HAL_PIN_9_M1MISO; break; - default : - goto invalid_args; - break; - } - break; - - case 2 : - switch( type ){ - case AP3_IOM_I2C_SCL : *pad = 27; *funcsel = AM_HAL_PIN_27_M2SCL; break; - case AP3_IOM_I2C_SDA : *pad = 25; *funcsel = AM_HAL_PIN_25_M2SDAWIR3; break; - case AP3_IOM_SPI_SCLK : *pad = 27; *funcsel = AM_HAL_PIN_27_M2SCK; break; - case AP3_IOM_SPI_MOSI : *pad = 28; *funcsel = AM_HAL_PIN_28_M2MOSI; break; - case AP3_IOM_SPI_MISO : *pad = 25; *funcsel = AM_HAL_PIN_25_M2MISO; break; - default : - goto invalid_args; - break; - } - break; - - case 3 : - switch( type ){ - case AP3_IOM_I2C_SCL : *pad = 42; *funcsel = AM_HAL_PIN_42_M3SCL; break; - case AP3_IOM_I2C_SDA : *pad = 43; *funcsel = AM_HAL_PIN_43_M3SDAWIR3; break; - case AP3_IOM_SPI_SCLK : *pad = 42; *funcsel = AM_HAL_PIN_42_M3SCK; break; - case AP3_IOM_SPI_MOSI : *pad = 38; *funcsel = AM_HAL_PIN_38_M3MOSI; break; - case AP3_IOM_SPI_MISO : *pad = 43; *funcsel = AM_HAL_PIN_43_M3MISO; break; - default : - goto invalid_args; - break; - } - break; - - case 4 : - switch( type ){ - case AP3_IOM_I2C_SCL : *pad = 39; *funcsel = AM_HAL_PIN_39_M4SCL; break; - case AP3_IOM_I2C_SDA : *pad = 40; *funcsel = AM_HAL_PIN_40_M4SDAWIR3; break; - case AP3_IOM_SPI_SCLK : *pad = 39; *funcsel = AM_HAL_PIN_39_M4SCK; break; - case AP3_IOM_SPI_MOSI : *pad = 44; *funcsel = AM_HAL_PIN_44_M4MOSI; break; - case AP3_IOM_SPI_MISO : *pad = 40; *funcsel = AM_HAL_PIN_40_M4MISO; break; - default : - goto invalid_args; - break; - } - break; - - case 5 : - switch( type ){ - case AP3_IOM_I2C_SCL : *pad = 48; *funcsel = AM_HAL_PIN_48_M5SCL; break; - case AP3_IOM_I2C_SDA : *pad = 49; *funcsel = AM_HAL_PIN_49_M5SDAWIR3; break; - case AP3_IOM_SPI_SCLK : *pad = 48; *funcsel = AM_HAL_PIN_48_M5SCK; break; - case AP3_IOM_SPI_MOSI : *pad = 47; *funcsel = AM_HAL_PIN_47_M5MOSI; break; - case AP3_IOM_SPI_MISO : *pad = 49; *funcsel = AM_HAL_PIN_49_M5MISO; break; - default : - goto invalid_args; - break; - } - break; - - default : + switch (instance) + { + case 0: + switch (type) + { + case AP3_IOM_I2C_SCL: + *pad = 5; + *funcsel = AM_HAL_PIN_5_M0SCL; + break; + case AP3_IOM_I2C_SDA: + *pad = 6; + *funcsel = AM_HAL_PIN_6_M0SDAWIR3; + break; + case AP3_IOM_SPI_SCLK: + *pad = 5; + *funcsel = AM_HAL_PIN_5_M0SCK; + break; + case AP3_IOM_SPI_MOSI: + *pad = 7; + *funcsel = AM_HAL_PIN_7_M0MOSI; + break; + case AP3_IOM_SPI_MISO: + *pad = 6; + *funcsel = AM_HAL_PIN_6_M0MISO; + break; + default: + goto invalid_args; + break; + } + break; + + case 1: + switch (type) + { + case AP3_IOM_I2C_SCL: + *pad = 8; + *funcsel = AM_HAL_PIN_8_M1SCL; + break; + case AP3_IOM_I2C_SDA: + *pad = 9; + *funcsel = AM_HAL_PIN_9_M1SDAWIR3; + break; + case AP3_IOM_SPI_SCLK: + *pad = 8; + *funcsel = AM_HAL_PIN_8_M1SCK; + break; + case AP3_IOM_SPI_MOSI: + *pad = 10; + *funcsel = AM_HAL_PIN_10_M1MOSI; + break; + case AP3_IOM_SPI_MISO: + *pad = 9; + *funcsel = AM_HAL_PIN_9_M1MISO; + break; + default: goto invalid_args; break; + } + break; + + case 2: + switch (type) + { + case AP3_IOM_I2C_SCL: + *pad = 27; + *funcsel = AM_HAL_PIN_27_M2SCL; + break; + case AP3_IOM_I2C_SDA: + *pad = 25; + *funcsel = AM_HAL_PIN_25_M2SDAWIR3; + break; + case AP3_IOM_SPI_SCLK: + *pad = 27; + *funcsel = AM_HAL_PIN_27_M2SCK; + break; + case AP3_IOM_SPI_MOSI: + *pad = 28; + *funcsel = AM_HAL_PIN_28_M2MOSI; + break; + case AP3_IOM_SPI_MISO: + *pad = 25; + *funcsel = AM_HAL_PIN_25_M2MISO; + break; + default: + goto invalid_args; + break; + } + break; + + case 3: + switch (type) + { + case AP3_IOM_I2C_SCL: + *pad = 42; + *funcsel = AM_HAL_PIN_42_M3SCL; + break; + case AP3_IOM_I2C_SDA: + *pad = 43; + *funcsel = AM_HAL_PIN_43_M3SDAWIR3; + break; + case AP3_IOM_SPI_SCLK: + *pad = 42; + *funcsel = AM_HAL_PIN_42_M3SCK; + break; + case AP3_IOM_SPI_MOSI: + *pad = 38; + *funcsel = AM_HAL_PIN_38_M3MOSI; + break; + case AP3_IOM_SPI_MISO: + *pad = 43; + *funcsel = AM_HAL_PIN_43_M3MISO; + break; + default: + goto invalid_args; + break; + } + break; + + case 4: + switch (type) + { + case AP3_IOM_I2C_SCL: + *pad = 39; + *funcsel = AM_HAL_PIN_39_M4SCL; + break; + case AP3_IOM_I2C_SDA: + *pad = 40; + *funcsel = AM_HAL_PIN_40_M4SDAWIR3; + break; + case AP3_IOM_SPI_SCLK: + *pad = 39; + *funcsel = AM_HAL_PIN_39_M4SCK; + break; + case AP3_IOM_SPI_MOSI: + *pad = 44; + *funcsel = AM_HAL_PIN_44_M4MOSI; + break; + case AP3_IOM_SPI_MISO: + *pad = 40; + *funcsel = AM_HAL_PIN_40_M4MISO; + break; + default: + goto invalid_args; + break; + } + break; + + case 5: + switch (type) + { + case AP3_IOM_I2C_SCL: + *pad = 48; + *funcsel = AM_HAL_PIN_48_M5SCL; + break; + case AP3_IOM_I2C_SDA: + *pad = 49; + *funcsel = AM_HAL_PIN_49_M5SDAWIR3; + break; + case AP3_IOM_SPI_SCLK: + *pad = 48; + *funcsel = AM_HAL_PIN_48_M5SCK; + break; + case AP3_IOM_SPI_MOSI: + *pad = 47; + *funcsel = AM_HAL_PIN_47_M5MOSI; + break; + case AP3_IOM_SPI_MISO: + *pad = 49; + *funcsel = AM_HAL_PIN_49_M5MISO; + break; + default: + goto invalid_args; + break; + } + break; + + default: + goto invalid_args; + break; } return retval; From 0c73c84dcf2791a87a521af6c52ea1bc0373b3db Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 9 Jul 2019 16:58:00 -0600 Subject: [PATCH 3/7] Rename var to emphasize bitorder not byteorder --- libraries/SPI/src/SPI.cpp | 6 +++--- libraries/SPI/src/SPI.h | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 8cc5863..116a561 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -113,7 +113,7 @@ void SPIClass::config(SPISettings settings) _config.eInterfaceMode = AM_HAL_IOM_SPI_MODE; _config.ui32ClockFreq = settings.clockFreq; _config.eSpiMode = settings.dataMode; - _order = settings.bitOrder; + _bitOrder = settings.bitOrder; initialize(); // Initialize the IOM } @@ -205,7 +205,7 @@ void SPIClass::endTransaction(void) void SPIClass::setBitOrder(BitOrder order) { - _order = order; + _bitOrder = order; //MSB/LSB is not exposed in the HAL v2.2 in a nice way //This is a hack to set the SPILSB bit of the MSPICFG register @@ -246,7 +246,7 @@ uint16_t SPIClass::transfer16(uint16_t data) t.val = data; - if (_order == LSBFIRST) + if (_bitOrder == LSBFIRST) { t.lsb = transfer(t.lsb); t.msb = transfer(t.msb); diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 0c46216..6ea3af4 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -121,8 +121,7 @@ class SPIClass : public IOMaster private: void config(SPISettings settings); - // Bit Order (need a better way to handle this) - BitOrder _order; + BitOrder _bitOrder; // Duplex ap3_spi_duplex_e _duplex; From a8af4a2511a1176f758817833ac71b89608a51b2 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 9 Jul 2019 17:14:12 -0600 Subject: [PATCH 4/7] Pass bitorder to ap3_iomaster We can't put bitOrder in the config structure because the HAL defines am_hal_iom_config_t. So instead we pass it by argument to the two initialize functions. Not elegant but functional. --- cores/arduino/ard_sup/ap3_iomaster.h | 19 ++++++++----------- .../arduino/ard_sup/iomaster/ap3_iomaster.cpp | 18 +++++++++++++++--- libraries/SPI/src/SPI.cpp | 16 +++++----------- libraries/SPI/src/SPI.h | 2 +- 4 files changed, 29 insertions(+), 26 deletions(-) diff --git a/cores/arduino/ard_sup/ap3_iomaster.h b/cores/arduino/ard_sup/ap3_iomaster.h index 867dda1..e4ff208 100644 --- a/cores/arduino/ard_sup/ap3_iomaster.h +++ b/cores/arduino/ard_sup/ap3_iomaster.h @@ -28,24 +28,21 @@ SOFTWARE. #include "Arduino.h" #include "ap3_iomaster_types.h" -class IOMaster { +class IOMaster +{ private: protected: - uint8_t _instance; - void* _handle; + uint8_t _instance; + void *_handle; am_hal_iom_config_t _config; public: IOMaster(uint8_t instance); - ap3_err_t initialize( void ); - ap3_err_t initialize(am_hal_iom_config_t config); - ap3_err_t deinitialize( void ); + ap3_err_t initialize(uint8_t bitOrder); + ap3_err_t initialize(am_hal_iom_config_t config, uint8_t bitOrder); + ap3_err_t deinitialize(void); }; - - -ap3_err_t ap3_iom_pad_funcsel( uint8_t instance, ap3_iom_pad_type_e type, ap3_gpio_pad_t* pad, uint8_t* funcsel ); - - +ap3_err_t ap3_iom_pad_funcsel(uint8_t instance, ap3_iom_pad_type_e type, ap3_gpio_pad_t *pad, uint8_t *funcsel); #endif // _AP3_IOMASTER_H_ \ No newline at end of file diff --git a/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp b/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp index 80642c8..9f7b9d9 100644 --- a/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp +++ b/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp @@ -27,12 +27,12 @@ IOMaster::IOMaster(uint8_t instance) _instance = instance; } -ap3_err_t IOMaster::initialize(void) +ap3_err_t IOMaster::initialize(uint8_t bitOrder) { - return initialize(_config); + return initialize(_config, bitOrder); } -ap3_err_t IOMaster::initialize(am_hal_iom_config_t config) +ap3_err_t IOMaster::initialize(am_hal_iom_config_t config, uint8_t bitOrder) { uint32_t retVal32 = 0; _config = config; @@ -64,6 +64,18 @@ ap3_err_t IOMaster::initialize(am_hal_iom_config_t config) return AP3_ERR; } + //MSB/LSB is not exposed in the HAL v2.2 in a nice way + //This is a hack to set the SPILSB bit of the MSPICFG register + //Note that calling am_hal_iom_configure will overwrite the LSB bit so we do this at the end + if (bitOrder == LSBFIRST) + { + AM_REGVAL(0x50004300 + (0x1000 * _instance)) |= (1 << 23); + } + else + { + AM_REGVAL(0x50004300 + (0x1000 * _instance)) &= ~(uint32_t)(1 << 23); + } + // Configure the IOM pins. (Must be done by the inherited classes [this is just a reminder]) } diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 116a561..0cfd1a9 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -115,7 +115,7 @@ void SPIClass::config(SPISettings settings) _config.eSpiMode = settings.dataMode; _bitOrder = settings.bitOrder; - initialize(); // Initialize the IOM + initialize(_bitOrder); // Initialize the IOM } void SPIClass::end() @@ -203,29 +203,23 @@ void SPIClass::endTransaction(void) // } } +//This sets local/private var _bitOrder +//_bitOrder is passed any time initialize is called due to HAL hack to get SPILSB bit set void SPIClass::setBitOrder(BitOrder order) { _bitOrder = order; - - //MSB/LSB is not exposed in the HAL v2.2 in a nice way - //This is a hack to set the SPILSB bit of the MSPICFG register - //Note that calling initialize() will overwrite the LSB bit - if (order == LSBFIRST) - { - AM_REGVAL(0x50004300 + ((uint32_t)0x1000 * _instance)) |= (1 << 23); - } } void SPIClass::setDataMode(uint8_t mode) { _config.eSpiMode = (am_hal_iom_spi_mode_e)mode; - initialize(); + initialize(_bitOrder); } void SPIClass::setClockDivider(uint8_t div) { _config.ui32ClockFreq = F_CPU / div; - initialize(); + initialize(_bitOrder); } byte SPIClass::transfer(uint8_t data) diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 6ea3af4..0c63a23 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -121,7 +121,7 @@ class SPIClass : public IOMaster private: void config(SPISettings settings); - BitOrder _bitOrder; + BitOrder _bitOrder = MSBFIRST; // Duplex ap3_spi_duplex_e _duplex; From 8bd660a754e1d8c610012e3274178b98e95efbbe Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 9 Jul 2019 20:28:11 -0600 Subject: [PATCH 5/7] spiClockDivider and bit polarity now working. One big pitfall was the lack of return AP3_OK from initialize. The lack of it did not throw an error but caused very weird behavior. Where else do we not have return values? --- cores/arduino/ard_sup/ap3_iomaster.h | 4 ++-- cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cores/arduino/ard_sup/ap3_iomaster.h b/cores/arduino/ard_sup/ap3_iomaster.h index e4ff208..fab9e58 100644 --- a/cores/arduino/ard_sup/ap3_iomaster.h +++ b/cores/arduino/ard_sup/ap3_iomaster.h @@ -38,8 +38,8 @@ class IOMaster public: IOMaster(uint8_t instance); - ap3_err_t initialize(uint8_t bitOrder); - ap3_err_t initialize(am_hal_iom_config_t config, uint8_t bitOrder); + ap3_err_t initialize(BitOrder bitOrder); + ap3_err_t initialize(am_hal_iom_config_t config, BitOrder bitOrder); ap3_err_t deinitialize(void); }; diff --git a/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp b/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp index 9f7b9d9..7933212 100644 --- a/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp +++ b/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp @@ -27,12 +27,12 @@ IOMaster::IOMaster(uint8_t instance) _instance = instance; } -ap3_err_t IOMaster::initialize(uint8_t bitOrder) +ap3_err_t IOMaster::initialize(BitOrder bitOrder) { return initialize(_config, bitOrder); } -ap3_err_t IOMaster::initialize(am_hal_iom_config_t config, uint8_t bitOrder) +ap3_err_t IOMaster::initialize(am_hal_iom_config_t config, BitOrder bitOrder) { uint32_t retVal32 = 0; _config = config; @@ -69,13 +69,15 @@ ap3_err_t IOMaster::initialize(am_hal_iom_config_t config, uint8_t bitOrder) //Note that calling am_hal_iom_configure will overwrite the LSB bit so we do this at the end if (bitOrder == LSBFIRST) { - AM_REGVAL(0x50004300 + (0x1000 * _instance)) |= (1 << 23); + AM_REGVAL(0x50004300 + (0x1000 * _instance)) |= (uint32_t)(1 << 23); } else { AM_REGVAL(0x50004300 + (0x1000 * _instance)) &= ~(uint32_t)(1 << 23); } + return AP3_OK; + // Configure the IOM pins. (Must be done by the inherited classes [this is just a reminder]) } From 612f0f6e5a72c4127afef962db997cc8d635717d Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 10 Jul 2019 10:25:28 -0600 Subject: [PATCH 6/7] Use the HAL to control LSB. --- cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp b/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp index 7933212..db573bc 100644 --- a/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp +++ b/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp @@ -64,16 +64,13 @@ ap3_err_t IOMaster::initialize(am_hal_iom_config_t config, BitOrder bitOrder) return AP3_ERR; } - //MSB/LSB is not exposed in the HAL v2.2 in a nice way - //This is a hack to set the SPILSB bit of the MSPICFG register - //Note that calling am_hal_iom_configure will overwrite the LSB bit so we do this at the end - if (bitOrder == LSBFIRST) - { - AM_REGVAL(0x50004300 + (0x1000 * _instance)) |= (uint32_t)(1 << 23); - } - else + //Arduino defines LSBFIRST as 0, Ambiq HAL defines this bit as 1 + //So we invert + uint8_t temp = (bitOrder ? 0 : 1); + retVal32 = am_hal_iom_control(_handle, AM_HAL_IOM_REQ_SPI_LSB, &temp); + if (retVal32 != AM_HAL_STATUS_SUCCESS) { - AM_REGVAL(0x50004300 + (0x1000 * _instance)) &= ~(uint32_t)(1 << 23); + return AP3_ERR; } return AP3_OK; From eeb594643040fdee5f1bf54eece864f3ad933089 Mon Sep 17 00:00:00 2001 From: Owen L - SFE Date: Fri, 26 Jul 2019 14:15:35 -0600 Subject: [PATCH 7/7] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 74b707e..f2d7740 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ # Mac *.DS_Store +*OTA_blob.bin*