From 78ac981591d3091a9b6a81c330bb3c63ec998532 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 20 Feb 2023 15:08:29 -0600 Subject: [PATCH] tweak formatting --- Marlin/src/HAL/AVR/HAL_SPI_HW.cpp | 731 +++-- Marlin/src/HAL/AVR/HAL_SPI_HWgen.cpp | 2 +- Marlin/src/HAL/DUE/HAL_SPI.cpp | 473 ++- Marlin/src/HAL/ESP32/HAL_SPI_HW.cpp | 363 +- Marlin/src/HAL/ESP32/HAL_SPI_HWgen.cpp | 115 +- Marlin/src/HAL/ESP32/HAL_SPI_SW.cpp | 5 +- Marlin/src/HAL/LINUX/spi_pins.h | 2 +- Marlin/src/HAL/LPC1768/HAL_SPI_HW.cpp | 4175 ++++++++++++------------ Marlin/src/HAL/LPC1768/HAL_SPI_SW.cpp | 279 +- Marlin/src/HAL/NATIVE_SIM/spi_pins.h | 2 +- Marlin/src/HAL/SAMD21/HAL_SPI.cpp | 2 +- Marlin/src/HAL/SAMD51/HAL_SPI.cpp | 2 +- Marlin/src/HAL/STM32/HAL_SPI_HW.cpp | 1556 ++++----- Marlin/src/HAL/STM32/HAL_SPI_HWgen.cpp | 166 +- Marlin/src/HAL/STM32/HAL_SPI_SW.cpp | 382 ++- Marlin/src/HAL/shared/tft/tft_spi.cpp | 49 +- Marlin/src/module/stepper/trinamic.cpp | 2 +- 17 files changed, 4034 insertions(+), 4272 deletions(-) diff --git a/Marlin/src/HAL/AVR/HAL_SPI_HW.cpp b/Marlin/src/HAL/AVR/HAL_SPI_HW.cpp index 1a73c064516a..314ad365af00 100644 --- a/Marlin/src/HAL/AVR/HAL_SPI_HW.cpp +++ b/Marlin/src/HAL/AVR/HAL_SPI_HW.cpp @@ -1,6 +1,6 @@ /** * Marlin 3D Printer Firmware - * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * Based on Sprinter and grbl. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm @@ -21,7 +21,7 @@ */ /** - * AVR HAL SPI implementation made by Martin Turski, company owner of EirDev + * AVR HAL SPI implementation by Martin Turski, company owner of EirDev * This implementation was specifically made for the Marlin FW. * For inquiries please contact turningtides@outlook.de * If there is any issue with this implementation, please open an inquiry on GitHub @@ -44,16 +44,16 @@ #include #ifndef AVR_CHIPOSCILLATOR_FREQ -#error Missing AVR crystal oscillator frequency (AVR_CHIPOSCILLATOR_FREQ)! Consult manufacturer schematics for further details (XTAL1/XTAL2 pins as guidance) + #error "Missing AVR crystal oscillator frequency (AVR_CHIPOSCILLATOR_FREQ)! Consult manufacturer schematics for further details (XTAL1/XTAL2 pins as guidance)" #endif - // ------------------------ - // Hardware SPI - // ------------------------ +// ------------------------ +// Hardware SPI +// ------------------------ - static void _spi_on_error(int code) { - for (;;) { -#if ENABLED(HALSPI_DO_ERRORBEEPS) && PIN_EXISTS(BEEPER) +static void _spi_on_error(int code) { + for (;;) { + #if ENABLED(HALSPI_DO_ERRORBEEPS) && PIN_EXISTS(BEEPER) OUT_WRITE(BEEPER_PIN, HIGH); delay(400); OUT_WRITE(BEEPER_PIN, LOW); @@ -78,28 +78,27 @@ delay(800); OUT_WRITE(BEEPER_PIN, LOW); delay(2000); -#endif - } + #endif } +} - #ifndef HALSPI_LOOPBEEP_TIMEOUT - #define HALSPI_LOOPBEEP_TIMEOUT 3000 - #endif +#ifndef HALSPI_LOOPBEEP_TIMEOUT + #define HALSPI_LOOPBEEP_TIMEOUT 3000 +#endif - struct spi_monitored_loop - { - private: +struct spi_monitored_loop { +private: #if defined(HALSPI_DO_LOOPBEEPS) && PIN_EXISTS(BEEPER) uint32_t _start_millis; #endif - public: - inline spi_monitored_loop() { - #if defined(HALSPI_DO_LOOPBEEPS) && PIN_EXISTS(BEEPER) +public: + inline spi_monitored_loop() { + #if defined(HALSPI_DO_LOOPBEEPS) && PIN_EXISTS(BEEPER) _start_millis = millis(); - #endif - } - inline void update(unsigned int beep_code) { - #if defined(HALSPI_DO_LOOPBEEPS) && PIN_EXISTS(BEEPER) + #endif + } + inline void update(unsigned int beep_code) { + #if defined(HALSPI_DO_LOOPBEEPS) && PIN_EXISTS(BEEPER) if ((millis() - _start_millis) <= HALSPI_LOOPBEEP_TIMEOUT) return; OUT_WRITE(BEEPER_PIN, HIGH); delay(500); @@ -124,61 +123,62 @@ delay(1000); OUT_WRITE(BEEPER_PIN, LOW); delay(2000); - #endif - } - }; + #endif + } +}; - static bool _spi_is_running = false; - static int _spi_cs_pin; - static bool _spi_transaction_is_active; - static bool _spi_dirty_tx; +static bool _spi_is_running = false; +static int _spi_cs_pin; +static bool _spi_transaction_is_active; +static bool _spi_dirty_tx; #if defined(GET_LOW_FUSE_BITS) static uint8_t _spi_lfuse; #endif - void spiBegin() { - #if PIN_EXISTS(SD_SS) - // Do not init HIGH for boards with pin 4 used as Fans or Heaters or otherwise, not likely to have multiple SPI devices anyway. - #if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__) - // SS must be in output mode even if it is not chip select - SET_OUTPUT(SD_SS_PIN); - #else - // set SS high - may be chip select for another SPI device - OUT_WRITE(SD_SS_PIN, HIGH); - #endif +void spiBegin() { + #if PIN_EXISTS(SD_SS) + // Do not init HIGH for boards with pin 4 used as Fans or Heaters or otherwise, not likely to have multiple SPI devices anyway. + #if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__) + // SS must be in output mode even if it is not chip select + SET_OUTPUT(SD_SS_PIN); + #else + // set SS high - may be chip select for another SPI device + OUT_WRITE(SD_SS_PIN, HIGH); #endif - // This could still be required because the specification says that the DDR of those pins is "User Defined". - // (we only support master SPI) - SET_OUTPUT(SD_SCK_PIN); - SET_INPUT(SD_MISO_PIN); - SET_OUTPUT(SD_MOSI_PIN); + #endif + // This could still be required because the specification says that the DDR of those pins is "User Defined". + // (we only support master SPI) + SET_OUTPUT(SD_SCK_PIN); + SET_INPUT(SD_MISO_PIN); + SET_OUTPUT(SD_MOSI_PIN); - #if defined(GET_LOW_FUSE_BITS) + #ifdef GET_LOW_FUSE_BITS cli(); _spi_lfuse = boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS); sei(); #endif - // By default we disable the SPI peripheral. - _PRR0._PRSPI = false; - _SPCR._SPE = false; - _PRR0._PRSPI = true; - } - - // Returns the clock frequency as output by the System Clock Prescaler. - inline uint32_t _GetSystemClockFrequency() { - // See which clock is selected. - const ATmega_lfuse lfuse = -#ifndef GET_LOW_FUSE_BITS - AVR_DEFAULT_LFUSE_VALUE; -#else - _spi_lfuse; -#endif + // By default we disable the SPI peripheral. + _PRR0._PRSPI = false; + _SPCR._SPE = false; + _PRR0._PRSPI = true; +} + +// Returns the clock frequency as output by the System Clock Prescaler. +inline uint32_t _GetSystemClockFrequency() { + // See which clock is selected. + const ATmega_lfuse lfuse = ( + #ifndef GET_LOW_FUSE_BITS + AVR_DEFAULT_LFUSE_VALUE + #else + _spi_lfuse + #endif + ); - uint32_t baseclk; + uint32_t baseclk; - switch(lfuse._CKSEL) { + switch (lfuse._CKSEL) { case 15: case 14: case 13: case 12: case 11: case 10: case 9: case 8: case 7: case 6: case 5: case 4: baseclk = AVR_CHIPOSCILLATOR_FREQ; @@ -195,44 +195,42 @@ case 0: _spi_on_error(3); break; - } + } - // Divide the system clock. - uint8_t clkps_po2 = _CLKPR._CLKPS; + // Divide the system clock. + uint8_t clkps_po2 = _CLKPR._CLKPS; - return ( baseclk >> clkps_po2 ); - } + return ( baseclk >> clkps_po2 ); +} - // We could improve these definitions if we had C++20. - template // SPCR_reg_t - inline void _spiConfigBitOrder(regType& __SPCR, int mode) { - if (mode == SPI_BITORDER_LSB) { - __SPCR._DORD = 1; - } - else if (mode == SPI_BITORDER_MSB) { - __SPCR._DORD = 0; - } - } +// We could improve these definitions if we had C++20. +template // SPCR_reg_t +inline void _spiConfigBitOrder(regType& __SPCR, int mode) { + if (mode == SPI_BITORDER_LSB) + __SPCR._DORD = 1; + else if (mode == SPI_BITORDER_MSB) + __SPCR._DORD = 0; +} - template // SPCR_reg_t - inline void _spiConfigClockMode(regType& __SPCR, int mode) { - if (mode == SPI_CLKMODE_0) { - __SPCR._CPOL = 0; - __SPCR._CPHA = 0; - } - else if (mode == SPI_CLKMODE_1) { - __SPCR._CPOL = 0; - __SPCR._CPHA = 1; - } - else if (mode == SPI_CLKMODE_2) { - __SPCR._CPOL = 1; - __SPCR._CPHA = 0; - } - else if (mode == SPI_CLKMODE_3) { - __SPCR._CPOL = 1; - __SPCR._CPHA = 1; - } +template // SPCR_reg_t +inline void _spiConfigClockMode(regType& __SPCR, int mode) { + if (mode == SPI_CLKMODE_0) { + __SPCR._CPOL = 0; + __SPCR._CPHA = 0; + } + else if (mode == SPI_CLKMODE_1) { + __SPCR._CPOL = 0; + __SPCR._CPHA = 1; + } + else if (mode == SPI_CLKMODE_2) { + __SPCR._CPOL = 1; + __SPCR._CPHA = 0; } + else if (mode == SPI_CLKMODE_3) { + __SPCR._CPOL = 1; + __SPCR._CPHA = 1; + } +} #ifndef HALSPI_AVR_NO_SLEEP @@ -266,321 +264,322 @@ _spi_txcomplete = true; } -#include + #include ISR(SPI_STC_vect) { // Make sure that a SLEEP instruction right after this interrupt call does not halt the processor. // This is sort of like an event variable in Win32 or a futex in Linux. _spi_leave_wait(); } -#endif - inline void _spi_waitForInterrupt() { -#ifndef HALSPI_AVR_NO_SLEEP +#endif // !HALSPI_AVR_NO_SLEEP + +inline void _spi_waitForInterrupt() { + #ifndef HALSPI_AVR_NO_SLEEP // This function is meant to sleep until the AVR SPI peripheral triggers the SPIF interrupt. __asm__ __volatile__( A("SLEEP") ); -#endif - } - - inline bool _spi_hasTransferCompleted() { -#ifdef HALSPI_AVR_NO_SLEEP - return _SPSR._SPIF; -#else - return _spi_txcomplete; -#endif - } + #endif +} + +inline bool _spi_hasTransferCompleted() { + return ( + #ifdef HALSPI_AVR_NO_SLEEP + _SPSR._SPIF + #else + _spi_txcomplete + #endif + ); +} - inline void _spi_push(uint8_t b) { -#ifndef HALSPI_AVR_NO_SLEEP +inline void _spi_push(uint8_t b) { + #ifndef HALSPI_AVR_NO_SLEEP _spi_enter_wait(); -#endif - _SPDR = b; - } + #endif + _SPDR = b; +} - /** - * Initialize hardware SPI transaction - */ - void spiInitEx(uint32_t maxClockFreq, const int hint_sck/*=-1*/, const int hint_miso/*=-1*/, const int hint_mosi/*=-1*/, const int hint_cs/*=-1*/) { - if (_spi_is_running) - _spi_on_error(1); - - // In hardware SPI mode we can only use the pre-determined SPI pins for MISO, MOSI and SCK, thus ignore the first three pin hints. - // We only support master SPI for now. - // For this we have to configure the chip-select (~SS) pin as output. - // This way it cannot be driven low by external peripherals., thus keeping our master state. - _spi_cs_pin = hint_cs; - - // Clear the power-reduction. - _PRR0._PRSPI = false; - - // Calculate the required division to run the SPI clock below maxClockFreq. - uint32_t sysclk = _GetSystemClockFrequency(); - - SPCR_reg_t __SPCR; - __SPCR._SPIE = false; - __SPCR._SPE = false; - _spiConfigBitOrder(__SPCR, SPI_BITORDER_DEFAULT); - __SPCR._MSTR = true; - _spiConfigClockMode(__SPCR, SPI_CLKMODE_DEFAULT); - - if ((sysclk / 2) <= maxClockFreq) { - _SPSR._SPI2X = true; - __SPCR._SPR = 0; - } - else if ((sysclk / 4) <= maxClockFreq) { - _SPSR._SPI2X = false; - __SPCR._SPR = 0; - } - else if ((sysclk / 8) <= maxClockFreq) { - _SPSR._SPI2X = true; - __SPCR._SPR = 1; - } - else if ((sysclk / 16) <= maxClockFreq) { - _SPSR._SPI2X = false; - __SPCR._SPR = 1; - } - else if ((sysclk / 32) <= maxClockFreq) { - _SPSR._SPI2X = true; - __SPCR._SPR = 2; - } - else if ((sysclk / 64) <= maxClockFreq) { - _SPSR._SPI2X = false; - __SPCR._SPR = 2; - } - else { - // Cannot go below it. - _SPSR._SPI2X = false; - __SPCR._SPR = 3; - } - - // Write initial configuration. - AVRHelpers::dwrite(_SPCR, __SPCR); - - _spi_is_running = true; - _spi_transaction_is_active = false; - _spi_dirty_tx = false; - } +/** + * Initialize hardware SPI transaction + */ +void spiInitEx(uint32_t maxClockFreq, const int hint_sck/*=-1*/, const int hint_miso/*=-1*/, const int hint_mosi/*=-1*/, const int hint_cs/*=-1*/) { + if (_spi_is_running) + _spi_on_error(1); - static void _maybe_start_transaction() { - if (_spi_transaction_is_active) return; + // In hardware SPI mode we can only use the pre-determined SPI pins for MISO, MOSI and SCK, thus ignore the first three pin hints. + // We only support master SPI for now. + // For this we have to configure the chip-select (~SS) pin as output. + // This way it cannot be driven low by external peripherals., thus keeping our master state. + _spi_cs_pin = hint_cs; - _SPCR._SPE = true; + // Clear the power-reduction. + _PRR0._PRSPI = false; - if (_spi_cs_pin >= 0) { - _ATmega_pinMode(_spi_cs_pin, OUTPUT); - _ATmega_digitalWrite(_spi_cs_pin, LOW); - } + // Calculate the required division to run the SPI clock below maxClockFreq. + uint32_t sysclk = _GetSystemClockFrequency(); - _spi_transaction_is_active = true; - } + SPCR_reg_t __SPCR; + __SPCR._SPIE = false; + __SPCR._SPE = false; + _spiConfigBitOrder(__SPCR, SPI_BITORDER_DEFAULT); + __SPCR._MSTR = true; + _spiConfigClockMode(__SPCR, SPI_CLKMODE_DEFAULT); - void spiInit(uint8_t spiRate, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { - // Use datarates Marlin uses - uint32_t clock; - switch (spiRate) { - case SPI_FULL_SPEED: clock = 20000000; break; // 13.9mhz=20000000 6.75mhz=10000000 3.38mhz=5000000 .833mhz=1000000 - case SPI_HALF_SPEED: clock = 5000000; break; - case SPI_QUARTER_SPEED: clock = 2500000; break; - case SPI_EIGHTH_SPEED: clock = 1250000; break; - case SPI_SPEED_5: clock = 625000; break; - case SPI_SPEED_6: clock = 300000; break; - default: - clock = 4000000; // Default from the SPI library - } - spiInitEx(clock, hint_sck, hint_miso, hint_mosi, hint_cs); + if ((sysclk / 2) <= maxClockFreq) { + _SPSR._SPI2X = true; + __SPCR._SPR = 0; } - - inline void _spi_safety_delay() { - //asm("nop"); // enable this if you encounter any delay troubles. + else if ((sysclk / 4) <= maxClockFreq) { + _SPSR._SPI2X = false; + __SPCR._SPR = 0; } - - inline void _spi_finish_tx() { - if (_spi_dirty_tx == false) return; - - _spi_safety_delay(); - spi_monitored_loop txew; - while (_spi_hasTransferCompleted() == false) { txew.update(1); _spi_waitForInterrupt(); } - - _spi_dirty_tx = false; + else if ((sysclk / 8) <= maxClockFreq) { + _SPSR._SPI2X = true; + __SPCR._SPR = 1; + } + else if ((sysclk / 16) <= maxClockFreq) { + _SPSR._SPI2X = false; + __SPCR._SPR = 1; + } + else if ((sysclk / 32) <= maxClockFreq) { + _SPSR._SPI2X = true; + __SPCR._SPR = 2; + } + else if ((sysclk / 64) <= maxClockFreq) { + _SPSR._SPI2X = false; + __SPCR._SPR = 2; + } + else { + // Cannot go below it. + _SPSR._SPI2X = false; + __SPCR._SPR = 3; } - void spiClose() { - if (_spi_is_running == false) - _spi_on_error(2); - - if (_spi_transaction_is_active) { - _spi_finish_tx(); - - if (_spi_cs_pin >= 0) - _ATmega_digitalWrite(_spi_cs_pin, HIGH); + // Write initial configuration. + AVRHelpers::dwrite(_SPCR, __SPCR); - _SPCR._SPE = false; + _spi_is_running = true; + _spi_transaction_is_active = false; + _spi_dirty_tx = false; +} - _spi_transaction_is_active = false; - } +static void _maybe_start_transaction() { + if (_spi_transaction_is_active) return; - // Disable the peripheral again. - _PRR0._PRSPI = true; + _SPCR._SPE = true; - _spi_is_running = false; + if (_spi_cs_pin >= 0) { + _ATmega_pinMode(_spi_cs_pin, OUTPUT); + _ATmega_digitalWrite(_spi_cs_pin, LOW); } - void spiSetBitOrder(int bitOrder) { - if (_spi_is_running == false) _spi_on_error(4); - _spiConfigBitOrder(_SPCR, bitOrder); - } + _spi_transaction_is_active = true; +} - void spiSetClockMode(int clockMode) { - if (_spi_is_running == false) _spi_on_error(4); - _spiConfigClockMode(_SPCR, clockMode); +void spiInit(uint8_t spiRate, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { + // Use Marlin datarates + uint32_t clock; + switch (spiRate) { + case SPI_FULL_SPEED: clock = 20000000; break; // 13.9mhz=20000000 6.75mhz=10000000 3.38mhz=5000000 .833mhz=1000000 + case SPI_HALF_SPEED: clock = 5000000; break; + case SPI_QUARTER_SPEED: clock = 2500000; break; + case SPI_EIGHTH_SPEED: clock = 1250000; break; + case SPI_SPEED_5: clock = 625000; break; + case SPI_SPEED_6: clock = 300000; break; + default: + clock = 4000000; // Default from the SPI library } + spiInitEx(clock, hint_sck, hint_miso, hint_mosi, hint_cs); +} - void spiEstablish() { - if (_spi_is_running == false) _spi_on_error(4); - _maybe_start_transaction(); - } +inline void _spi_safety_delay() { + //asm("nop"); // enable this if you encounter any delay troubles. +} - /** SPI receive a byte */ - uint8_t spiRec(uint8_t txval) { - if (_spi_is_running == false) _spi_on_error(4); - _maybe_start_transaction(); - _spi_finish_tx(); - _spi_push(txval); - _spi_safety_delay(); - spi_monitored_loop rxew; - while (_spi_hasTransferCompleted() == false) { rxew.update(2); _spi_waitForInterrupt(); } - return _SPDR; - } +inline void _spi_finish_tx() { + if (_spi_dirty_tx == false) return; - inline void _split_txbytes(uint16_t txval, uint8_t& tx_first, uint8_t& tx_second, bool msb) { - if (msb) { - tx_first = ( txval >> 8 ); - tx_second = ( txval & 0xFF ); - } - else { - tx_first = ( txval & 0xFF ); - tx_second = ( txval >> 8 ); - } - } + _spi_safety_delay(); + spi_monitored_loop txew; + while (_spi_hasTransferCompleted() == false) { txew.update(1); _spi_waitForInterrupt(); } - inline uint16_t _fuse_txbytes(uint8_t rx_first, uint8_t rx_second, bool msb) { - if (msb) { - return ( (uint16_t)rx_first << 8 ) | ( (uint16_t)rx_second ); - } - else { - return ( (uint16_t)rx_first ) | ( (uint16_t)rx_second << 8 ); - } - } + _spi_dirty_tx = false; +} - uint16_t spiRec16(uint16_t txval) { - if (_spi_is_running == false) _spi_on_error(4); - _maybe_start_transaction(); - bool msb = ( _SPCR._DORD == 0 ); - uint8_t tx_first, tx_second; - _split_txbytes(txval, tx_first, tx_second, msb); - _spi_finish_tx(); - _spi_push(tx_first); - _spi_safety_delay(); - spi_monitored_loop rxe1w; - while (_spi_hasTransferCompleted() == false) { rxe1w.update(3); _spi_waitForInterrupt(); } - uint8_t rx_first = _SPDR; - _spi_push(tx_second); - _spi_safety_delay(); - spi_monitored_loop rxe2w; - while (_spi_hasTransferCompleted() == false) { rxe2w.update(4); _spi_waitForInterrupt(); } - uint8_t rx_second = _SPDR; - return _fuse_txbytes(rx_first, rx_second, msb); - } +void spiClose() { + if (_spi_is_running == false) + _spi_on_error(2); - /** SPI read data */ - void spiRead(uint8_t *buf, uint16_t nbyte, uint8_t txval) { - if (_spi_is_running == false) _spi_on_error(4); - if (nbyte == 0) return; - _maybe_start_transaction(); + if (_spi_transaction_is_active) { _spi_finish_tx(); - for (uint16_t i = 0; i < nbyte; i++) { - _spi_push(txval); - _spi_safety_delay(); - spi_monitored_loop rxew; - while (_spi_hasTransferCompleted() == false) { rxew.update(5); _spi_waitForInterrupt(); } - buf[i] = _SPDR; - } - } - inline void _spiSendByte(uint8_t byte) { - _spi_finish_tx(); - _spi_push(byte); - _spi_dirty_tx = true; - } + if (_spi_cs_pin >= 0) + _ATmega_digitalWrite(_spi_cs_pin, HIGH); + + _SPCR._SPE = false; - /** SPI send a byte */ - void spiSend(uint8_t b) { - if (_spi_is_running == false) _spi_on_error(4); - _maybe_start_transaction(); - _spiSendByte(b); + _spi_transaction_is_active = false; } - void spiSend16(uint16_t v) { - if (_spi_is_running == false) _spi_on_error(4); - _maybe_start_transaction(); - bool msb = ( _SPCR._DORD == 0 ); + // Disable the peripheral again. + _PRR0._PRSPI = true; + + _spi_is_running = false; +} + +void spiSetBitOrder(int bitOrder) { + if (_spi_is_running == false) _spi_on_error(4); + _spiConfigBitOrder(_SPCR, bitOrder); +} + +void spiSetClockMode(int clockMode) { + if (_spi_is_running == false) _spi_on_error(4); + _spiConfigClockMode(_SPCR, clockMode); +} + +void spiEstablish() { + if (_spi_is_running == false) _spi_on_error(4); + _maybe_start_transaction(); +} + +// SPI receive a byte +uint8_t spiRec(uint8_t txval) { + if (_spi_is_running == false) _spi_on_error(4); + _maybe_start_transaction(); + _spi_finish_tx(); + _spi_push(txval); + _spi_safety_delay(); + spi_monitored_loop rxew; + while (_spi_hasTransferCompleted() == false) { rxew.update(2); _spi_waitForInterrupt(); } + return _SPDR; +} + +inline void _split_txbytes(uint16_t txval, uint8_t& tx_first, uint8_t& tx_second, bool msb) { + if (msb) { + tx_first = txval >> 8; + tx_second = txval & 0xFF; + } + else { + tx_first = txval & 0xFF; + tx_second = txval >> 8; + } +} + +inline uint16_t _fuse_txbytes(uint8_t rx_first, uint8_t rx_second, bool msb) { + if (msb) + return ( (uint16_t)rx_first << 8 ) | ( (uint16_t)rx_second ); + else + return ( (uint16_t)rx_first ) | ( (uint16_t)rx_second << 8 ); +} + +uint16_t spiRec16(uint16_t txval) { + if (_spi_is_running == false) _spi_on_error(4); + _maybe_start_transaction(); + bool msb = ( _SPCR._DORD == 0 ); + uint8_t tx_first, tx_second; + _split_txbytes(txval, tx_first, tx_second, msb); + _spi_finish_tx(); + _spi_push(tx_first); + _spi_safety_delay(); + spi_monitored_loop rxe1w; + while (_spi_hasTransferCompleted() == false) { rxe1w.update(3); _spi_waitForInterrupt(); } + uint8_t rx_first = _SPDR; + _spi_push(tx_second); + _spi_safety_delay(); + spi_monitored_loop rxe2w; + while (_spi_hasTransferCompleted() == false) { rxe2w.update(4); _spi_waitForInterrupt(); } + uint8_t rx_second = _SPDR; + return _fuse_txbytes(rx_first, rx_second, msb); +} + +// SPI read data +void spiRead(uint8_t *buf, uint16_t nbyte, uint8_t txval) { + if (_spi_is_running == false) _spi_on_error(4); + if (nbyte == 0) return; + _maybe_start_transaction(); + _spi_finish_tx(); + for (uint16_t i = 0; i < nbyte; i++) { + _spi_push(txval); + _spi_safety_delay(); + spi_monitored_loop rxew; + while (_spi_hasTransferCompleted() == false) { rxew.update(5); _spi_waitForInterrupt(); } + buf[i] = _SPDR; + } +} + +inline void _spiSendByte(uint8_t byte) { + _spi_finish_tx(); + _spi_push(byte); + _spi_dirty_tx = true; +} + +// SPI send a byte +void spiSend(uint8_t b) { + if (_spi_is_running == false) _spi_on_error(4); + _maybe_start_transaction(); + _spiSendByte(b); +} + +void spiSend16(uint16_t v) { + if (_spi_is_running == false) _spi_on_error(4); + _maybe_start_transaction(); + bool msb = ( _SPCR._DORD == 0 ); + uint8_t tx_first, tx_second; + _split_txbytes(v, tx_first, tx_second, msb); + _spiSendByte(tx_first); + _spiSendByte(tx_second); +} + +// SPI send block +void spiSendBlock(uint8_t token, const uint8_t *buf) { + if (_spi_is_running == false) _spi_on_error(4); + _maybe_start_transaction(); + _spiSendByte(token); + for (uint16_t i = 0; i < 512; i++) { + _spiSendByte(buf[i]); + } +} + +// Begin SPI transaction +void spiWrite(const uint8_t *buf, uint16_t cnt) { + if (_spi_is_running == false) _spi_on_error(4); + _maybe_start_transaction(); + for (uint16_t n = 0; n < cnt; n++) + _spiSendByte(buf[n]); +} + +void spiWrite16(const uint16_t *buf, uint16_t cnt) { + if (_spi_is_running == false) _spi_on_error(4); + _maybe_start_transaction(); + bool msb = ( _SPCR._DORD == 0 ); + for (uint16_t n = 0; n < cnt; n++) { uint8_t tx_first, tx_second; - _split_txbytes(v, tx_first, tx_second, msb); + _split_txbytes(buf[n], tx_first, tx_second, msb); _spiSendByte(tx_first); _spiSendByte(tx_second); } - - /** SPI send block */ - void spiSendBlock(uint8_t token, const uint8_t *buf) { - if (_spi_is_running == false) _spi_on_error(4); - _maybe_start_transaction(); - _spiSendByte(token); - for (uint16_t i = 0; i < 512; i++) { - _spiSendByte(buf[i]); - } - } - - /** Begin SPI transaction */ - void spiWrite(const uint8_t *buf, uint16_t cnt) { - if (_spi_is_running == false) _spi_on_error(4); - _maybe_start_transaction(); - for (uint16_t n = 0; n < cnt; n++) - _spiSendByte(buf[n]); - } - - void spiWrite16(const uint16_t *buf, uint16_t cnt) { - if (_spi_is_running == false) _spi_on_error(4); - _maybe_start_transaction(); - bool msb = ( _SPCR._DORD == 0 ); - for (uint16_t n = 0; n < cnt; n++) { - uint8_t tx_first, tx_second; - _split_txbytes(buf[n], tx_first, tx_second, msb); - _spiSendByte(tx_first); - _spiSendByte(tx_second); - } - } - - void spiWriteRepeat(uint8_t val, uint16_t repcnt) { - if (_spi_is_running == false) _spi_on_error(4); - _maybe_start_transaction(); - for (uint16_t n = 0; n < repcnt; n++) - _spiSendByte(val); - } - - void spiWriteRepeat16(uint16_t val, uint16_t repcnt) { - if (_spi_is_running == false) _spi_on_error(4); - _maybe_start_transaction(); - bool msb = ( _SPCR._DORD == 0 ); - uint8_t tx_first, tx_second; - _split_txbytes(val, tx_first, tx_second, msb); - for (uint16_t n = 0; n < repcnt; n++) { - _spiSendByte(tx_first); - _spiSendByte(tx_second); - } +} + +void spiWriteRepeat(uint8_t val, uint16_t repcnt) { + if (_spi_is_running == false) _spi_on_error(4); + _maybe_start_transaction(); + for (uint16_t n = 0; n < repcnt; n++) + _spiSendByte(val); +} + +void spiWriteRepeat16(uint16_t val, uint16_t repcnt) { + if (_spi_is_running == false) _spi_on_error(4); + _maybe_start_transaction(); + bool msb = ( _SPCR._DORD == 0 ); + uint8_t tx_first, tx_second; + _split_txbytes(val, tx_first, tx_second, msb); + for (uint16_t n = 0; n < repcnt; n++) { + _spiSendByte(tx_first); + _spiSendByte(tx_second); } +} -#endif +#endif // !SOFTWARE_SPI && !FORCE_SOFT_SPI && !HALSPI_HW_GENERIC -#endif +#endif // __AVR__ diff --git a/Marlin/src/HAL/AVR/HAL_SPI_HWgen.cpp b/Marlin/src/HAL/AVR/HAL_SPI_HWgen.cpp index 101e711dc3b1..69c20f264a93 100644 --- a/Marlin/src/HAL/AVR/HAL_SPI_HWgen.cpp +++ b/Marlin/src/HAL/AVR/HAL_SPI_HWgen.cpp @@ -73,7 +73,7 @@ } void spiInit(uint8_t spiRate, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { - // Use datarates Marlin uses + // Use Marlin datarates uint32_t clock; switch (spiRate) { case SPI_FULL_SPEED: clock = 20000000; break; // 13.9mhz=20000000 6.75mhz=10000000 3.38mhz=5000000 .833mhz=1000000 diff --git a/Marlin/src/HAL/DUE/HAL_SPI.cpp b/Marlin/src/HAL/DUE/HAL_SPI.cpp index 5604f3d8c532..b638e27b4646 100644 --- a/Marlin/src/HAL/DUE/HAL_SPI.cpp +++ b/Marlin/src/HAL/DUE/HAL_SPI.cpp @@ -146,67 +146,67 @@ // addr: The byte address of bitbanding bit. // bit: The bit position of bitbanding bit. #define BITBAND_ADDRESS(addr, bit) \ - (((uint32_t)(addr) & 0xF0000000) + 0x02000000 + ((uint32_t)(addr)&0xFFFFF)*32 + (bit)*4) + (((uint32_t)(addr) & 0xF0000000) + 0x02000000 + ((uint32_t)(addr) & 0xFFFFF)*32 + (bit)*4) // run at ~8 .. ~10Mhz - Rx version (Tx line not altered) static uint8_t spiTransferRx0(uint8_t) { // using Mode 0 uint32_t bin = 0; uint32_t work = 0; - uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(SD_MISO_PIN))+0x3C, PIN_SHIFT(SD_MISO_PIN)); /* PDSR of port in bitband area */ - uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */ + uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(SD_MISO_PIN)) + 0x3C, PIN_SHIFT(SD_MISO_PIN)); // PDSR of port in bitband area + uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; // SODR of port uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN); - /* The software SPI routine */ + // The software SPI routine __asm__ __volatile__( A(".syntax unified") // is to prevent CM0,CM1 non-unified syntax - /* bit 7 */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bfi %[bin],%[work],#7,#1") /* Store read bit as the bit 7 */ - - /* bit 6 */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bfi %[bin],%[work],#6,#1") /* Store read bit as the bit 6 */ - - /* bit 5 */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bfi %[bin],%[work],#5,#1") /* Store read bit as the bit 5 */ - - /* bit 4 */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bfi %[bin],%[work],#4,#1") /* Store read bit as the bit 4 */ - - /* bit 3 */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bfi %[bin],%[work],#3,#1") /* Store read bit as the bit 3 */ - - /* bit 2 */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bfi %[bin],%[work],#2,#1") /* Store read bit as the bit 2 */ - - /* bit 1 */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bfi %[bin],%[work],#1,#1") /* Store read bit as the bit 1 */ - - /* bit 0 */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bfi %[bin],%[work],#0,#1") /* Store read bit as the bit 0 */ + // bit 7 + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ldr %[work],[%[bitband_miso_port]]") // PDSR on bitband area for required bit: work will be 1 or 0 based on port + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bfi %[bin],%[work],#7,#1") // Store read bit as the bit 7 + + // bit 6 + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ldr %[work],[%[bitband_miso_port]]") // PDSR on bitband area for required bit: work will be 1 or 0 based on port + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bfi %[bin],%[work],#6,#1") // Store read bit as the bit 6 + + // bit 5 + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ldr %[work],[%[bitband_miso_port]]") // PDSR on bitband area for required bit: work will be 1 or 0 based on port + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bfi %[bin],%[work],#5,#1") // Store read bit as the bit 5 + + // bit 4 + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ldr %[work],[%[bitband_miso_port]]") // PDSR on bitband area for required bit: work will be 1 or 0 based on port + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bfi %[bin],%[work],#4,#1") // Store read bit as the bit 4 + + // bit 3 + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ldr %[work],[%[bitband_miso_port]]") // PDSR on bitband area for required bit: work will be 1 or 0 based on port + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bfi %[bin],%[work],#3,#1") // Store read bit as the bit 3 + + // bit 2 + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ldr %[work],[%[bitband_miso_port]]") // PDSR on bitband area for required bit: work will be 1 or 0 based on port + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bfi %[bin],%[work],#2,#1") // Store read bit as the bit 2 + + // bit 1 + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ldr %[work],[%[bitband_miso_port]]") // PDSR on bitband area for required bit: work will be 1 or 0 based on port + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bfi %[bin],%[work],#1,#1") // Store read bit as the bit 1 + + // bit 0 + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ldr %[work],[%[bitband_miso_port]]") // PDSR on bitband area for required bit: work will be 1 or 0 based on port + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bfi %[bin],%[work],#0,#1") // Store read bit as the bit 0 : [bin]"+r"(bin), [work]"+r"(work) @@ -270,71 +270,71 @@ // Block transfers run at ~8 .. ~10Mhz - Tx version (Rx data discarded) static void spiTxBlock0(const uint8_t *ptr, uint32_t todo) { - uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(SD_MOSI_PIN)) + 0x30; /* SODR of port */ + uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(SD_MOSI_PIN)) + 0x30; // SODR of port uint32_t MOSI_MASK = PIN_MASK(SD_MOSI_PIN); - uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */ + uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; // SODR of port uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN); uint32_t work = 0; uint32_t txval = 0; - /* The software SPI routine */ + // The software SPI routine __asm__ __volatile__( A(".syntax unified") // is to prevent CM0,CM1 non-unified syntax L("loop%=") - A("ldrb.w %[txval], [%[ptr]], #1") /* Load value to send, increment buffer */ - A("mvn %[txval],%[txval]") /* Negate value */ - - /* Bit 7 */ - A("ubfx %[work],%[txval],#7,#1") /* Place bit 7 in bit 0 of work*/ - - A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ubfx %[work],%[txval],#6,#1") /* Place bit 6 in bit 0 of work*/ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - - /* Bit 6 */ - A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ubfx %[work],%[txval],#5,#1") /* Place bit 5 in bit 0 of work*/ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - - /* Bit 5 */ - A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ubfx %[work],%[txval],#4,#1") /* Place bit 4 in bit 0 of work*/ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - - /* Bit 4 */ - A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ubfx %[work],%[txval],#3,#1") /* Place bit 3 in bit 0 of work*/ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - - /* Bit 3 */ - A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ubfx %[work],%[txval],#2,#1") /* Place bit 2 in bit 0 of work*/ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - - /* Bit 2 */ - A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ubfx %[work],%[txval],#1,#1") /* Place bit 1 in bit 0 of work*/ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - - /* Bit 1 */ - A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ubfx %[work],%[txval],#0,#1") /* Place bit 0 in bit 0 of work*/ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - - /* Bit 0 */ - A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("subs %[todo],#1") /* Decrement count of pending words to send, update status */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bne.n loop%=") /* Repeat until done */ + A("ldrb.w %[txval], [%[ptr]], #1") // Load value to send, increment buffer + A("mvn %[txval],%[txval]") // Negate value + + // Bit 7 + A("ubfx %[work],%[txval],#7,#1") // Place bit 7 in bit 0 of work + + A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") // Access the proper SODR or CODR registers based on that bit + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ubfx %[work],%[txval],#6,#1") // Place bit 6 in bit 0 of work + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + + // Bit 6 + A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") // Access the proper SODR or CODR registers based on that bit + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ubfx %[work],%[txval],#5,#1") // Place bit 5 in bit 0 of work + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + + // Bit 5 + A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") // Access the proper SODR or CODR registers based on that bit + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ubfx %[work],%[txval],#4,#1") // Place bit 4 in bit 0 of work + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + + // Bit 4 + A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") // Access the proper SODR or CODR registers based on that bit + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ubfx %[work],%[txval],#3,#1") // Place bit 3 in bit 0 of work + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + + // Bit 3 + A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") // Access the proper SODR or CODR registers based on that bit + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ubfx %[work],%[txval],#2,#1") // Place bit 2 in bit 0 of work + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + + // Bit 2 + A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") // Access the proper SODR or CODR registers based on that bit + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ubfx %[work],%[txval],#1,#1") // Place bit 1 in bit 0 of work + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + + // Bit 1 + A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") // Access the proper SODR or CODR registers based on that bit + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ubfx %[work],%[txval],#0,#1") // Place bit 0 in bit 0 of work + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + + // Bit 0 + A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") // Access the proper SODR or CODR registers based on that bit + A("str %[sck_mask],[%[sck_port]]") // SODR + A("subs %[todo],#1") // Decrement count of pending words to send, update status + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bne.n loop%=") // Repeat until done : [ptr]"+r" ( ptr ) , [todo]"+r" ( todo ) , @@ -355,63 +355,63 @@ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */ uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN); - /* The software SPI routine */ + // The software SPI routine __asm__ __volatile__( A(".syntax unified") // is to prevent CM0,CM1 non-unified syntax L("loop%=") - /* bit 7 */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bfi %[bin],%[work],#7,#1") /* Store read bit as the bit 7 */ - - /* bit 6 */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bfi %[bin],%[work],#6,#1") /* Store read bit as the bit 6 */ - - /* bit 5 */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bfi %[bin],%[work],#5,#1") /* Store read bit as the bit 5 */ - - /* bit 4 */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bfi %[bin],%[work],#4,#1") /* Store read bit as the bit 4 */ - - /* bit 3 */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bfi %[bin],%[work],#3,#1") /* Store read bit as the bit 3 */ - - /* bit 2 */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bfi %[bin],%[work],#2,#1") /* Store read bit as the bit 2 */ - - /* bit 1 */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bfi %[bin],%[work],#1,#1") /* Store read bit as the bit 1 */ - - /* bit 0 */ - A("str %[sck_mask],[%[sck_port]]") /* SODR */ - A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */ - A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */ - A("bfi %[bin],%[work],#0,#1") /* Store read bit as the bit 0 */ - - A("subs %[todo],#1") /* Decrement count of pending words to send, update status */ - A("strb.w %[bin], [%[ptr]], #1") /* Store read value into buffer, increment buffer pointer */ - A("bne.n loop%=") /* Repeat until done */ + // bit 7 + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ldr %[work],[%[bitband_miso_port]]") // PDSR on bitband area for required bit: work will be 1 or 0 based on port + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bfi %[bin],%[work],#7,#1") // Store read bit as the bit 7 + + // bit 6 + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ldr %[work],[%[bitband_miso_port]]") // PDSR on bitband area for required bit: work will be 1 or 0 based on port + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bfi %[bin],%[work],#6,#1") // Store read bit as the bit 6 + + // bit 5 + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ldr %[work],[%[bitband_miso_port]]") // PDSR on bitband area for required bit: work will be 1 or 0 based on port + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bfi %[bin],%[work],#5,#1") // Store read bit as the bit 5 + + // bit 4 + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ldr %[work],[%[bitband_miso_port]]") // PDSR on bitband area for required bit: work will be 1 or 0 based on port + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bfi %[bin],%[work],#4,#1") // Store read bit as the bit 4 + + // bit 3 + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ldr %[work],[%[bitband_miso_port]]") // PDSR on bitband area for required bit: work will be 1 or 0 based on port + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bfi %[bin],%[work],#3,#1") // Store read bit as the bit 3 + + // bit 2 + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ldr %[work],[%[bitband_miso_port]]") // PDSR on bitband area for required bit: work will be 1 or 0 based on port + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bfi %[bin],%[work],#2,#1") // Store read bit as the bit 2 + + // bit 1 + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ldr %[work],[%[bitband_miso_port]]") // PDSR on bitband area for required bit: work will be 1 or 0 based on port + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bfi %[bin],%[work],#1,#1") // Store read bit as the bit 1 + + // bit 0 + A("str %[sck_mask],[%[sck_port]]") // SODR + A("ldr %[work],[%[bitband_miso_port]]") // PDSR on bitband area for required bit: work will be 1 or 0 based on port + A("str %[sck_mask],[%[sck_port],#0x4]") // CODR + A("bfi %[bin],%[work],#0,#1") // Store read bit as the bit 0 + + A("subs %[todo],#1") // Decrement count of pending words to send, update status + A("strb.w %[bin], [%[ptr]], #1") // Store read value into buffer, increment buffer pointer + A("bne.n loop%=") // Repeat until done : [ptr]"+r"(ptr), [todo]"+r"(todo), @@ -426,8 +426,7 @@ static inline uint8_t _flip_bits_8(uint8_t v) { uint8_t result = 0; - for (int n = 0; n < 8; n++) - { + for (int n = 0; n < 8; n++) { result <<= 1; bool bitval = ( v & ( 1 << n ) ) != 0; result |= bitval; @@ -435,16 +434,12 @@ return result; } - static inline uint8_t _spiTransferRx_ordered(uint8_t txval) - { + static inline uint8_t _spiTransferRx_ordered(uint8_t txval) { return ( _spi_bit_order == SPI_BITORDER_MSB ? spiTransferRx(txval) : _flip_bits_8(spiTransferRx(_flip_bits_8(txval))) ); } static inline void _spiTransferTx_ordered(uint8_t b) { - if ( _spi_bit_order == SPI_BITORDER_LSB ) - { - b = _flip_bits_8(b); - } + if (_spi_bit_order == SPI_BITORDER_LSB) b = _flip_bits_8(b); (void)spiTransferTx(b); } @@ -506,20 +501,20 @@ } uint16_t spiRec16(uint16_t txval) { - bool msb = ( _spi_bit_order == SPI_BITORDER_MSB ); + const bool msb = _spi_bit_order == SPI_BITORDER_MSB; uint8_t tx_first, tx_second; if (msb) { - tx_first = ( txval >> 8 ); - tx_second = ( txval & 0xFF ); + tx_first = txval >> 8; + tx_second = txval & 0xFF; } else { - tx_first = ( txval & 0xFF ); - tx_second = ( txval >> 8 ); + tx_first = txval & 0xFF; + tx_second = txval >> 8; } _SS_WRITE(LOW); WRITE(SD_MOSI_PIN, HIGH); // Output 1s 1 - uint16_t v = ( msb ? ( (uint16_t)_spiTransferRx_ordered(tx_first) << 8 ) : _spiTransferRx_ordered(tx_first) ); - v |= ( msb ? _spiTransferRx_ordered(tx_second) : ( (uint16_t)_spiTransferRx_ordered(tx_second) << 8 ) ); + uint16_t v = msb ? (uint16_t)_spiTransferRx_ordered(tx_first) << 8 : _spiTransferRx_ordered(tx_first); + v |= msb ? _spiTransferRx_ordered(tx_second) : (uint16_t)_spiTransferRx_ordered(tx_second) << 8; _SS_WRITE(HIGH); return v; } @@ -549,7 +544,7 @@ } void spiSend16(uint16_t v) { - bool msb = ( _spi_bit_order == SPI_BITORDER_MSB ); + const bool msb = _spi_bit_order == SPI_BITORDER_MSB; _SS_WRITE(LOW); _spiSend16Internal(v); _SS_WRITE(HIGH); @@ -569,7 +564,7 @@ } void spiWrite16(const uint16_t *buf, uint16_t cnt) { - bool msb = ( _spi_bit_order == SPI_BITORDER_MSB ); + const bool msb = _spi_bit_order == SPI_BITORDER_MSB; _SS_WRITE(LOW); for (uint16_t n = 0; n < cnt; n++) _spiSend16Internal(buf[n], msb); @@ -584,7 +579,7 @@ } void spiWriteRepeat16(uint16_t val, uint16_t repcnt) { - bool msb = ( _spi_bit_order == SPI_BITORDER_MSB ); + const bool msb = _spi_bit_order == SPI_BITORDER_MSB; _SS_WRITE(LOW); for (uint16_t n = 0; n < repcnt; n++) _spiSend16Internal(val, msb); @@ -632,28 +627,15 @@ } void spiInitEx(uint32_t maxClockFreq, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { - // Use datarates Marlin uses + // Use Marlin datarates uint8_t spiRate; - if (maxClockFreq >= 20000000) { - spiRate = SPI_FULL_SPEED; - } - else if (maxClockFreq >= 5000000) { - spiRate = SPI_HALF_SPEED; - } - else if (maxClockFreq >= 2500000) { - spiRate = SPI_QUARTER_SPEED; - } - else if (maxClockFreq >= 1250000) { - spiRate = SPI_EIGHTH_SPEED; - } - else if (maxClockFreq >= 625000) { - spiRate = SPI_SPEED_5; - } - else if (maxClockFreq >= 300000) { - spiRate = SPI_SPEED_6; - } - else - spiRate = SPI_SPEED_6; + if (maxClockFreq >= 20000000) spiRate = SPI_FULL_SPEED; + else if (maxClockFreq >= 5000000) spiRate = SPI_HALF_SPEED; + else if (maxClockFreq >= 2500000) spiRate = SPI_QUARTER_SPEED; + else if (maxClockFreq >= 1250000) spiRate = SPI_EIGHTH_SPEED; + else if (maxClockFreq >= 625000) spiRate = SPI_SPEED_5; + else if (maxClockFreq >= 300000) spiRate = SPI_SPEED_6; + else spiRate = SPI_SPEED_6; spiInit(spiRate, hint_sck, hint_miso, hint_mosi, hint_cs); } @@ -715,7 +697,7 @@ } void spiInit(uint8_t spiRate, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { - // Use datarates Marlin uses + // Use Marlin datarates uint32_t clock; switch (spiRate) { case SPI_FULL_SPEED: clock = 8000000; break; @@ -814,13 +796,11 @@ } void spiSend16(uint16_t v) { - if (_has_spi_pins) - { + if (_has_spi_pins) { sdSPI.beginTransaction(_spi_pin_cs, spiConfig); sdSPI.transfer16(_spi_pin_cs, v); } - else - { + else { sdSPI.beginTransaction(spiConfig); sdSPI.transfer16(v); } @@ -905,28 +885,15 @@ } void spiInitEx(uint32_t maxClockFreq, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { - // Use datarates Marlin uses + // Use Marlin datarates uint8_t spiRate; - if (maxClockFreq >= 20000000) { - spiRate = SPI_FULL_SPEED; - } - else if (maxClockFreq >= 5000000) { - spiRate = SPI_HALF_SPEED; - } - else if (maxClockFreq >= 2500000) { - spiRate = SPI_QUARTER_SPEED; - } - else if (maxClockFreq >= 1250000) { - spiRate = SPI_EIGHTH_SPEED; - } - else if (maxClockFreq >= 625000) { - spiRate = SPI_SPEED_5; - } - else if (maxClockFreq >= 300000) { - spiRate = SPI_SPEED_6; - } - else - spiRate = SPI_SPEED_6; + if (maxClockFreq >= 20000000) spiRate = SPI_FULL_SPEED; + else if (maxClockFreq >= 5000000) spiRate = SPI_HALF_SPEED; + else if (maxClockFreq >= 2500000) spiRate = SPI_QUARTER_SPEED; + else if (maxClockFreq >= 1250000) spiRate = SPI_EIGHTH_SPEED; + else if (maxClockFreq >= 625000) spiRate = SPI_SPEED_5; + else if (maxClockFreq >= 300000) spiRate = SPI_SPEED_6; + else spiRate = SPI_SPEED_6; spiInit(spiRate, hint_sck, hint_miso, hint_mosi, hint_cs); } @@ -1017,16 +984,16 @@ } uint16_t spiRec16(uint16_t txval) { - bool msb = ( ( SPI0->SPI_CR & ( 1 << 5 ) ) == 0 ); + const bool msb = !TEST(SPI0->SPI_CR, 5); uint8_t tx_first, tx_second; if (msb) { - tx_first = ( txval >> 8 ); - tx_second = ( txval & 0xFF ); + tx_first = txval >> 8; + tx_second = txval & 0xFF; } else { - tx_first = ( txval & 0xFF ); - tx_second = ( txval >> 8 ); + tx_first = txval & 0xFF; + tx_second = txval >> 8; } SPI0->SPI_TDR = tx_first | SPI_PCS(SPI_CHAN); @@ -1034,19 +1001,19 @@ WHILE_TX(0); WHILE_RX(0); - uint16_t v = ( msb ? ( (uint16_t)(SPI0->SPI_RDR&0xFF) << 8 ) : (SPI0->SPI_RDR&0xFF) ); + uint16_t v = msb ? uint16_t(SPI0->SPI_RDR & 0xFF) << 8 : SPI0->SPI_RDR & 0xFF; SPI0->SPI_TDR = tx_second | SPI_PCS(SPI_CHAN) | SPI_TDR_LASTXFER; WHILE_TX(0); WHILE_RX(0); - v |= ( msb ? (SPI0->SPI_RDR&0xFF) : ( (uint16_t)(SPI0->SPI_RDR&0xFF) << 8 ) ); + v |= (msb ? SPI0->SPI_RDR & 0xFF : uint16_t(SPI0->SPI_RDR & 0xFF) << 8); return v; } -#if 0 + #if 0 uint8_t spiRec(uint32_t chan) { WHILE_TX(0); @@ -1058,7 +1025,7 @@ return SPI0->SPI_RDR; } -#endif + #endif // Read from SPI into buffer void spiRead(uint8_t *buf, uint16_t nbyte, uint8_t txval) { @@ -1085,12 +1052,12 @@ } void spiSend16(uint16_t v) { - bool msb = ( ( SPI0->SPI_CR & ( 1 << 5 ) ) == 0 ); - SPI0->SPI_TDR = (uint32_t)( msb ? (v&0xFF) : (v>>8) ) | SPI_PCS(SPI_CHAN); + const bool msb = !TEST(SPI0->SPI_CR, 5); + SPI0->SPI_TDR = uint32_t(msb ? (v & 0xFF) : (v >> 8)) | SPI_PCS(SPI_CHAN); WHILE_TX(0); WHILE_RX(0); SPI0->SPI_RDR; - SPI0->SPI_TDR = (uint32_t)( msb ? (v>>8) : (v&0xFF) ) | SPI_PCS(SPI_CHAN) | SPI_TDR_LASTXFER; + SPI0->SPI_TDR = uint32_t(msb ? (v >> 8) : (v & 0xFF)) | SPI_PCS(SPI_CHAN) | SPI_TDR_LASTXFER; WHILE_TX(0); WHILE_RX(0); SPI0->SPI_RDR; @@ -1124,7 +1091,7 @@ spiSend16(val); } -#if 0 + #if 0 void spiSend(uint32_t chan, byte b) { WHILE_TX(0); // write byte with address and end transmission flag @@ -1144,7 +1111,7 @@ } spiSend(chan, buf[nbyte]); } -#endif + #endif // Write from buffer to SPI void spiSendBlock(uint8_t token, const uint8_t *buf) { @@ -1268,24 +1235,20 @@ } uint16_t spiRec16(uint16_t txval) { - bool msb = ( ( SPI0->SPI_CR & ( 1 << 5 ) ) == 0 ); + const bool msb = !TEST(SPI0->SPI_CR, 5); uint8_t tx_first, tx_second; if (msb) { - take_first = ( txval >> 8 ); - take_second = ( txval & 0xFF ); + take_first = txval >> 8; + take_second = txval & 0xFF; } else { - take_first = ( tx_val & 0xFF ); - take_second = ( tx_val >> 8 ); - } - if ( msb ) - { - return ( (uint16_t)spiRec(take_first) << 8 ) | ( (uint16_t)spiRec(take_second) ); + take_first = tx_val & 0xFF; + take_second = tx_val >> 8; } + if (msb) + return (uint16_t)spiRec(take_first) << 8 | (uint16_t)spiRec(take_second); else - { - return ( (uint16_t)spiRec(take_first) ) | ( (uint16_t)spiRec(take_second) << 8 ); - } + return (uint16_t)spiRec(take_first) | (uint16_t)spiRec(take_second) << 8; } void spiRead(uint8_t *buf, uint16_t nbyte, uint8_t txval) { @@ -1293,18 +1256,15 @@ buf[i] = spiTransfer(txval); } - void spiSend(uint8_t data) - { + void spiSend(uint8_t data) { spiTransfer(data); } - void spiSend16(uint16_t data) - { - bool msb = ( ( SPI0->SPI_CR & ( 1 << 5 ) ) == 0 ); + void spiSend16(uint16_t data) { + const bool msb = !TEST(SPI0->SPI_CR, 5); if (msb) { spiSend(data >> 8); spiSend(data & 0xFF); - } else { spiSend(data & 0xFF); @@ -1344,6 +1304,7 @@ } #endif // !ALLIGATOR + #endif // !SOFTWARE_SPI #endif // ARDUINO_ARCH_SAM diff --git a/Marlin/src/HAL/ESP32/HAL_SPI_HW.cpp b/Marlin/src/HAL/ESP32/HAL_SPI_HW.cpp index 7e9fd89413dc..7356080d2bb0 100644 --- a/Marlin/src/HAL/ESP32/HAL_SPI_HW.cpp +++ b/Marlin/src/HAL/ESP32/HAL_SPI_HW.cpp @@ -42,7 +42,7 @@ #include "../shared/HAL_SPI.h" -#if !ENABLED(SOFTWARE_SPI) && !ENABLED(HALSPI_HW_GENERIC) +#if DISABLED(SOFTWARE_SPI) && DISABLED(HALSPI_HW_GENERIC) #include "sdk/BitManage.h" @@ -1086,14 +1086,14 @@ inline gpioMapResult_t SPIMapGPIO(int gpio_sck, int gpio_miso, int gpio_mosi, in gpio_iomux_out((unsigned int)gpio_mosi, func_mosi, false); has_mosi_map = true; } -#if 0 - if (func_cs != SPI_IOMUX_INVAL) { - gpio_iomux_in((unsigned int)gpio_cs, cs_sig); - gpio_iomux_out((unsigned int)gpio_cs, func_cs, false); - has_cs_map = true; - has_mosi_map = true; - } -#endif + #if 0 + if (func_cs != SPI_IOMUX_INVAL) { + gpio_iomux_in((unsigned int)gpio_cs, cs_sig); + gpio_iomux_out((unsigned int)gpio_cs, func_cs, false); + has_cs_map = true; + has_mosi_map = true; + } + #endif } if (has_sck_map == false && gpio_sck >= 0) { @@ -1108,12 +1108,12 @@ inline gpioMapResult_t SPIMapGPIO(int gpio_sck, int gpio_miso, int gpio_mosi, in gpio_matrix_out((unsigned int)gpio_mosi, mosi_sig, false, false); pinMode(gpio_mosi, OUTPUT); } -#if 0 - if (has_cs_map == false && gpio_cs >= 0) { - gpio_matrix_out((unsigned int)gpio_cs, cs_sig, false, false); - pinMode(gpio_cs, OUTPUT); - } -#endif + #if 0 + if (has_cs_map == false && gpio_cs >= 0) { + gpio_matrix_out((unsigned int)gpio_cs, cs_sig, false, false); + pinMode(gpio_cs, OUTPUT); + } + #endif gpioMapResult_t result; result.spibusIdx = spibusIdx; @@ -1135,11 +1135,11 @@ inline void SPIUnmapGPIO(gpioMapResult_t& result) { if (result.gpio_mosi >= 0) { gpio_reset_pin(_GetInternalPinName(result.gpio_mosi)); } -#if 0 - if (result.gpio_cs >= 0) { - gpio_reset_pin(_GetInternalPinName(result.gpio_cs)); - } -#endif + #if 0 + if (result.gpio_cs >= 0) { + gpio_reset_pin(_GetInternalPinName(result.gpio_cs)); + } + #endif } struct dport_perip_clk_en_reg_t { @@ -1902,11 +1902,10 @@ static void IRAM_ATTR spi_async_fill_buffer(volatile spi_async_process_t& proc) } if (has_prepared_spibus == false || writecnt_bytes == 0) { - #ifdef HALSPI_DEBUG - if (proc.curoff_bytes < proc.txlen * proc.txunitsize) { - _spi_on_error(12); - } - #endif + #ifdef HALSPI_DEBUG + if (proc.curoff_bytes < proc.txlen * proc.txunitsize) + _spi_on_error(12); + #endif // Disable the interrupt. SPI.SPI_SLAVE_REG.SPI_TRANS_INTEN = false; @@ -1924,21 +1923,18 @@ static void IRAM_ATTR spi_async_fill_buffer(volatile spi_async_process_t& proc) proc.is_active = false; // Call any completion handler, if provided by the user. - if (cb) { - cb(ud); - } + if (cb) cb(ud); } else { proc.curoff_bytes += writecnt_bytes; uint32_t txcount_bits = ( writecnt_bytes * 8 ); - if (SPI.SPI_USER_REG.SPI_USR_MOSI == true) { + if (SPI.SPI_USER_REG.SPI_USR_MOSI == true) SPI.SPI_MOSI_DLEN_REG.SPI_USR_MOSI_DBITLEN = txcount_bits - 1; - } - if (SPI.SPI_USER_REG.SPI_USR_MISO == true) { + + if (SPI.SPI_USER_REG.SPI_USR_MISO == true) SPI.SPI_MISO_DLEN_REG.SPI_USR_MISO_DBITLEN = txcount_bits - 1; - } // Kick-off another async SPI transfer. SPI.SPI_CMD_REG.SPI_USR = true; @@ -2020,10 +2016,10 @@ static void __attribute__((unused)) SPIUninstallAsync(intr_handle_t handle) { } static void SPIAsyncInitialize() { -#ifdef HALSPI_ESP32_ENABLE_INTERNBUS - SPIInstallAsync(SPI0, _spi0_interrupt); - SPIInstallAsync(SPI1, _spi1_interrupt); -#endif + #ifdef HALSPI_ESP32_ENABLE_INTERNBUS + SPIInstallAsync(SPI0, _spi0_interrupt); + SPIInstallAsync(SPI1, _spi1_interrupt); + #endif SPIInstallAsync(SPI2, _spi2_interrupt); SPIInstallAsync(SPI3, _spi3_interrupt); } @@ -2072,7 +2068,7 @@ static void SPIAbortRawAsync() { sei(); } -#endif //HAL_SPI_SUPPORTS_ASYNC +#endif // HAL_SPI_SUPPORTS_ASYNC #ifndef HALSPI_DISABLE_DMA @@ -2123,31 +2119,31 @@ inline bool DMAIsValidDescriptor(volatile dma_descriptor_t *desc) noexcept { } inline void DMAInitializeMachine() { -#ifdef HALSPI_ESP32_STATIC_DMADESCS - for (auto& desc : _usable_dma_descs_static) { - if (DMAIsValidDescriptor(&desc) == false) { + #ifdef HALSPI_ESP32_STATIC_DMADESCS + for (auto& desc : _usable_dma_descs_static) { + if (DMAIsValidDescriptor(&desc) == false) { + _spi_on_error(3); + } + desc.owner = SPIDMA_OWNER_CPU; + desc.reserved = 0; + desc.sosf = false; + } + #else + void *dmabuf = heap_caps_malloc( sizeof(dma_descriptor_t)*HALSPI_ESP32_DMADESC_COUNT, MALLOC_CAP_DMA ); + if (dmabuf == nullptr) _spi_on_error(3); + _usable_dma_descs_dynamic = (volatile dma_descriptor_t*)dmabuf; + _usable_dma_descs_count = HALSPI_ESP32_DMADESC_COUNT; + if (DMAIsValidDescriptor(_usable_dma_descs_dynamic) == false) + _spi_on_error(3); + for (uint32_t n = 0; n < _usable_dma_descs_count; n++) { + auto& desc = _usable_dma_descs_dynamic[n]; + + desc.owner = SPIDMA_OWNER_CPU; + desc.reserved = 0; + desc.sosf = false; } - desc.owner = SPIDMA_OWNER_CPU; - desc.reserved = 0; - desc.sosf = false; - } -#else - void *dmabuf = heap_caps_malloc( sizeof(dma_descriptor_t)*HALSPI_ESP32_DMADESC_COUNT, MALLOC_CAP_DMA ); - if (dmabuf == nullptr) - _spi_on_error(3); - _usable_dma_descs_dynamic = (volatile dma_descriptor_t*)dmabuf; - _usable_dma_descs_count = HALSPI_ESP32_DMADESC_COUNT; - if (DMAIsValidDescriptor(_usable_dma_descs_dynamic) == false) - _spi_on_error(3); - for (uint32_t n = 0; n < _usable_dma_descs_count; n++) { - auto& desc = _usable_dma_descs_dynamic[n]; - - desc.owner = SPIDMA_OWNER_CPU; - desc.reserved = 0; - desc.sosf = false; - } -#endif + #endif } /* Important restriction on DMA-usable memory addresses and their buffer sizes: @@ -2166,6 +2162,7 @@ inline bool DMAIsValidWriteDataBuffer(const void *buf, size_t bufsz) noexcept { return true; } + inline bool DMAIsValidReadDataBuffer(const void *buf) noexcept { if (DMAIsValidPointer(buf) == false) return false; @@ -2197,10 +2194,10 @@ struct dma_process_t { static volatile dma_process_t dma_current_process; static void DMABusInitialize(volatile spi_dev_t& SPI) { -#ifdef HALSPI_DEBUG - if (DMAIsCapableSPIBus(SPI) == false) - _spi_on_error(4); -#endif + #ifdef HALSPI_DEBUG + if (DMAIsCapableSPIBus(SPI) == false) + _spi_on_error(4); + #endif // Reset and enable the SPI DMA clock. DPORT_PERIP_RST_EN_REG.DPORT_SPI_DMA_RST = true; @@ -2210,44 +2207,32 @@ static void DMABusInitialize(volatile spi_dev_t& SPI) { // Select the SPI DMA channel. auto spibusIdx = SPIGetBusIndex(SPI); - unsigned int dma_chansel = -#ifdef HALSPI_ESP32_DMA_SELECT_CHAN1 - DPORT_SPI_DMA_CHAN_SEL_CHAN1 -#elif defined(HALSPI_ESP32_DMA_SELECT_CHAN2) - DPORT_SPI_DMA_CHAN_SEL_CHAN2 -#else - DPORT_SPI_DMA_CHAN_SEL_CHAN1 -#endif - ; -#ifdef HALSPI_ESP32_ENABLE_INTERNBUS - if (spibusIdx == 1) { - DPORT_SPI_DMA_CHAN_SEL_REG.DPORT_SPI_SPI1_DMA_CHAN_SEL = dma_chansel; - } - else -#endif - if (spibusIdx == 2) { - DPORT_SPI_DMA_CHAN_SEL_REG.DPORT_SPI_SPI2_DMA_CHAN_SEL = dma_chansel; - } - else if (spibusIdx == 3) { - DPORT_SPI_DMA_CHAN_SEL_REG.DPORT_SPI_SPI3_DMA_CHAN_SEL = dma_chansel; + unsigned int dma_chansel = ( + #ifdef HALSPI_ESP32_DMA_SELECT_CHAN1 + DPORT_SPI_DMA_CHAN_SEL_CHAN1 + #elif defined(HALSPI_ESP32_DMA_SELECT_CHAN2) + DPORT_SPI_DMA_CHAN_SEL_CHAN2 + #else + DPORT_SPI_DMA_CHAN_SEL_CHAN1 + #endif + ); + switch (spibusIdx) { + #ifdef HALSPI_ESP32_ENABLE_INTERNBUS + case 1: DPORT_SPI_DMA_CHAN_SEL_REG.DPORT_SPI_SPI1_DMA_CHAN_SEL = dma_chansel; break; + #endif + case 2: DPORT_SPI_DMA_CHAN_SEL_REG.DPORT_SPI_SPI2_DMA_CHAN_SEL = dma_chansel; break; + case 3: DPORT_SPI_DMA_CHAN_SEL_REG.DPORT_SPI_SPI3_DMA_CHAN_SEL = dma_chansel; break; } } static void DMABusShutdown(volatile spi_dev_t& SPI) { // Unselect the SPI DMA channel. - auto spibusIdx = SPIGetBusIndex(SPI); - -#ifdef HALSPI_ESP32_ENABLE_INTERNBUS - if (spibusIdx == 1) { - DPORT_SPI_DMA_CHAN_SEL_REG.DPORT_SPI_SPI1_DMA_CHAN_SEL = DPORT_SPI_DMA_CHAN_SEL_NONE; - } - else -#endif - if (spibusIdx == 2) { - DPORT_SPI_DMA_CHAN_SEL_REG.DPORT_SPI_SPI2_DMA_CHAN_SEL = DPORT_SPI_DMA_CHAN_SEL_NONE; - } - else if (spibusIdx == 3) { - DPORT_SPI_DMA_CHAN_SEL_REG.DPORT_SPI_SPI3_DMA_CHAN_SEL = DPORT_SPI_DMA_CHAN_SEL_NONE; + switch (SPIGetBusIndex(SPI)) { + #ifdef HALSPI_ESP32_ENABLE_INTERNBUS + case 1: DPORT_SPI_DMA_CHAN_SEL_REG.DPORT_SPI_SPI1_DMA_CHAN_SEL = DPORT_SPI_DMA_CHAN_SEL_NONE; break; + #endif + case 2: DPORT_SPI_DMA_CHAN_SEL_REG.DPORT_SPI_SPI2_DMA_CHAN_SEL = DPORT_SPI_DMA_CHAN_SEL_NONE; break; + case 3: DPORT_SPI_DMA_CHAN_SEL_REG.DPORT_SPI_SPI3_DMA_CHAN_SEL = DPORT_SPI_DMA_CHAN_SEL_NONE; break; } // Disable the SPI DMA clock. @@ -2257,18 +2242,16 @@ static void DMABusShutdown(volatile spi_dev_t& SPI) { // TODO: manage list of free descriptors to speed up the process of generating a DMA chain. static volatile dma_descriptor_t* DMAGetFreeDescriptor() noexcept { -#ifdef HALSPI_ESP32_STATIC_DMADESCS - for (auto& desc : _usable_dma_descs_static) { -#else - for (uint32_t _n = 0; _n < _usable_dma_descs_count; _n++) { - auto& desc = _usable_dma_descs_dynamic[_n]; -#endif + #ifdef HALSPI_ESP32_STATIC_DMADESCS + for (auto& desc : _usable_dma_descs_static) { + #else + for (uint32_t _n = 0; _n < _usable_dma_descs_count; _n++) { + auto& desc = _usable_dma_descs_dynamic[_n]; + #endif if (desc.owner == SPIDMA_OWNER_CPU) { -#ifdef HALSPI_DEBUG - if (DMAIsValidDescriptor(&desc) == false) - _spi_on_error(5); -#endif - + #ifdef HALSPI_DEBUG + if (DMAIsValidDescriptor(&desc) == false) _spi_on_error(5); + #endif return &desc; } } @@ -2363,61 +2346,61 @@ static void DMASendBlocking(volatile spi_dev_t& SPI, const void *buf, size_t buf proc.txlen = txlen; proc.curoff = 0; -#if 0 - static volatile dma_descriptor_t _rxdesc; - _rxdesc.size = 0; - _rxdesc.length = 0; - _rxdesc.reserved = 0; - _rxdesc.sosf = false; - _rxdesc.eof = true; - _rxdesc.owner = SPIDMA_OWNER_DMAC; - _rxdesc.address = nullptr; - _rxdesc.next = nullptr; - { - // Workaround for SPI DMA hardware bug. - // (https://www.esp32.com/viewtopic.php?t=8433 spi_master.zip:spi_master.c:line 754) - // TODO: does it really matter??? - spi_dma_in_link_reg_t SPI_DMA_IN_LINK_REG; - SPI_DMA_IN_LINK_REG.SPI_INLINK_ADDR = ESP32_DMADESC_HWPTR(&_rxdesc); - SPI_DMA_IN_LINK_REG.SPI_INLINK_AUTO_RET = false; - SPI_DMA_IN_LINK_REG.reserved1 = 0; - SPI_DMA_IN_LINK_REG.SPI_INLINK_STOP = false; - SPI_DMA_IN_LINK_REG.SPI_INLINK_START = true; - SPI_DMA_IN_LINK_REG.SPI_INLINK_RESTART = false; - SPI_DMA_IN_LINK_REG.reserved2 = 0; - dwrite(SPI.SPI_DMA_IN_LINK_REG, SPI_DMA_IN_LINK_REG); - } - - SPI.SPI_USER_REG.SPI_USR_MISO = true; - SPI.SPI_USER_REG.SPI_USR_MOSI = true; - SPI.SPI_CTRL_REG.SPI_FASTRD_MODE = false; - SPI.SPI_CTRL_REG.reserved2 = 0; - SPI.SPI_CTRL2_REG.SPI_SETUP_TIME = 0; - SPI.SPI_CTRL2_REG.SPI_HOLD_TIME = 0; - SPI.SPI_USER1_REG.SPI_USR_DUMMY_CYCLELEN = 0; - SPI.SPI_USER1_REG.SPI_USR_ADDR_BITLEN = 0; - SPI.SPI_USER2_REG.SPI_USR_COMMAND_BITLEN = 0; - SPI.SPI_SLAVE1_REG.SPI_SLV_STATUS_READBACK = 0; - SPI.SPI_DMA_INT_CLR_REG.SPI_INLINK_DSCR_ERROR_INT_CLR = true; - - SERIAL_ECHOLNPGM("RX CHAIN PTR: ", (uint32_t)&_rxdesc); - SERIAL_ECHOLNPGM("SOC_DMA: ", SOC_DMA_LOW, " to ", SOC_DMA_HIGH); + #if 0 + static volatile dma_descriptor_t _rxdesc; + _rxdesc.size = 0; + _rxdesc.length = 0; + _rxdesc.reserved = 0; + _rxdesc.sosf = false; + _rxdesc.eof = true; + _rxdesc.owner = SPIDMA_OWNER_DMAC; + _rxdesc.address = nullptr; + _rxdesc.next = nullptr; + { + // Workaround for SPI DMA hardware bug. + // (https://www.esp32.com/viewtopic.php?t=8433 spi_master.zip:spi_master.c:line 754) + // TODO: does it really matter??? + spi_dma_in_link_reg_t SPI_DMA_IN_LINK_REG; + SPI_DMA_IN_LINK_REG.SPI_INLINK_ADDR = ESP32_DMADESC_HWPTR(&_rxdesc); + SPI_DMA_IN_LINK_REG.SPI_INLINK_AUTO_RET = false; + SPI_DMA_IN_LINK_REG.reserved1 = 0; + SPI_DMA_IN_LINK_REG.SPI_INLINK_STOP = false; + SPI_DMA_IN_LINK_REG.SPI_INLINK_START = true; + SPI_DMA_IN_LINK_REG.SPI_INLINK_RESTART = false; + SPI_DMA_IN_LINK_REG.reserved2 = 0; + dwrite(SPI.SPI_DMA_IN_LINK_REG, SPI_DMA_IN_LINK_REG); + } - SPI.SPI_MOSI_DLEN_REG.SPI_USR_MOSI_DBITLEN = 0u; - SPI.SPI_MISO_DLEN_REG.SPI_USR_MISO_DBITLEN = 0u; -#endif + SPI.SPI_USER_REG.SPI_USR_MISO = true; + SPI.SPI_USER_REG.SPI_USR_MOSI = true; + SPI.SPI_CTRL_REG.SPI_FASTRD_MODE = false; + SPI.SPI_CTRL_REG.reserved2 = 0; + SPI.SPI_CTRL2_REG.SPI_SETUP_TIME = 0; + SPI.SPI_CTRL2_REG.SPI_HOLD_TIME = 0; + SPI.SPI_USER1_REG.SPI_USR_DUMMY_CYCLELEN = 0; + SPI.SPI_USER1_REG.SPI_USR_ADDR_BITLEN = 0; + SPI.SPI_USER2_REG.SPI_USR_COMMAND_BITLEN = 0; + SPI.SPI_SLAVE1_REG.SPI_SLV_STATUS_READBACK = 0; + SPI.SPI_DMA_INT_CLR_REG.SPI_INLINK_DSCR_ERROR_INT_CLR = true; + + SERIAL_ECHOLNPGM("RX CHAIN PTR: ", (uint32_t)&_rxdesc); + SERIAL_ECHOLNPGM("SOC_DMA: ", SOC_DMA_LOW, " to ", SOC_DMA_HIGH); + + SPI.SPI_MOSI_DLEN_REG.SPI_USR_MOSI_DBITLEN = 0u; + SPI.SPI_MISO_DLEN_REG.SPI_USR_MISO_DBITLEN = 0u; + #endif -#if 0 - // DUMP MACHINE STATE. - { - static bool _dumped = false; + #if 0 + // DUMP MACHINE STATE. + { + static bool _dumped = false; - if (_dumped == false) { - SPI.serial_dump(); - _dumped = true; + if (_dumped == false) { + SPI.serial_dump(); + _dumped = true; + } } - } -#endif + #endif //OUT_WRITE(BEEPER_PIN, HIGH); @@ -2443,25 +2426,25 @@ static void DMASendBlocking(volatile spi_dev_t& SPI, const void *buf, size_t buf SPI_DMA_OUT_LINK_REG.reserved2 = 0; dwrite(SPI.SPI_DMA_OUT_LINK_REG, SPI_DMA_OUT_LINK_REG); -#if 0 - SPI.SPI_DMA_IN_LINK_REG.SPI_INLINK_ADDR = ESP32_DMADESC_HWPTR(chain); // ??? - SPI.SPI_DMA_IN_LINK_REG.SPI_INLINK_START = true; -#elif 0 - { - // Workaround for SPI DMA hardware bug. - // (https://www.esp32.com/viewtopic.php?t=8433 spi_master.zip:spi_master.c:line 754) - // TODO: does it really matter??? - spi_dma_in_link_reg_t SPI_DMA_IN_LINK_REG; - SPI_DMA_IN_LINK_REG.SPI_INLINK_ADDR = ESP32_DMADESC_HWPTR(chain); - SPI_DMA_IN_LINK_REG.SPI_INLINK_AUTO_RET = false; - SPI_DMA_IN_LINK_REG.reserved1 = 0; - SPI_DMA_IN_LINK_REG.SPI_INLINK_STOP = false; - SPI_DMA_IN_LINK_REG.SPI_INLINK_START = true; - SPI_DMA_IN_LINK_REG.SPI_INLINK_RESTART = false; - SPI_DMA_IN_LINK_REG.reserved2 = 0; - dwrite(SPI.SPI_DMA_IN_LINK_REG, SPI_DMA_IN_LINK_REG); - } -#endif + #if 0 + SPI.SPI_DMA_IN_LINK_REG.SPI_INLINK_ADDR = ESP32_DMADESC_HWPTR(chain); // ??? + SPI.SPI_DMA_IN_LINK_REG.SPI_INLINK_START = true; + #elif 0 + { + // Workaround for SPI DMA hardware bug. + // (https://www.esp32.com/viewtopic.php?t=8433 spi_master.zip:spi_master.c:line 754) + // TODO: does it really matter??? + spi_dma_in_link_reg_t SPI_DMA_IN_LINK_REG; + SPI_DMA_IN_LINK_REG.SPI_INLINK_ADDR = ESP32_DMADESC_HWPTR(chain); + SPI_DMA_IN_LINK_REG.SPI_INLINK_AUTO_RET = false; + SPI_DMA_IN_LINK_REG.reserved1 = 0; + SPI_DMA_IN_LINK_REG.SPI_INLINK_STOP = false; + SPI_DMA_IN_LINK_REG.SPI_INLINK_START = true; + SPI_DMA_IN_LINK_REG.SPI_INLINK_RESTART = false; + SPI_DMA_IN_LINK_REG.reserved2 = 0; + dwrite(SPI.SPI_DMA_IN_LINK_REG, SPI_DMA_IN_LINK_REG); + } + #endif //SPI.SPI_DMA_RSTATUS_REG.serial_dump(); //SPI.SPI_DMA_TSTATUS_REG.serial_dump(); @@ -2479,19 +2462,15 @@ static void DMASendBlocking(volatile spi_dev_t& SPI, const void *buf, size_t buf /* wait until DMA transfer has finished */ spi_monitored_loop usrw; -#if 0 - while (SPI.SPI_DMA_RSTATUS_REG.TX_FIFO_EMPTY == false) { - usrw.update(3); - } -#endif - while (SPI.SPI_DMA_STATUS_REG.SPI_DMA_TX_EN) { - usrw.update(3); - } - while (SPI.SPI_CMD_REG.SPI_USR) { - usrw.update(3); - } + #if 0 + while (SPI.SPI_DMA_RSTATUS_REG.TX_FIFO_EMPTY == false) { + usrw.update(3); + } + #endif + while (SPI.SPI_DMA_STATUS_REG.SPI_DMA_TX_EN) usrw.update(3); + while (SPI.SPI_CMD_REG.SPI_USR) usrw.update(3); -#if 0 + #if 0 if (SPI.SPI_DMA_INT_RAW_REG.SPI_OUTLINK_DSCR_ERROR_INT_RAW) { _spi_on_error(20); } @@ -2505,7 +2484,7 @@ static void DMASendBlocking(volatile spi_dev_t& SPI, const void *buf, size_t buf if (SPI.SPI_DMA_INT_RAW_REG.SPI_INLINK_DSCR_EMPTY_INT_RAW) { _spi_on_error(23); } -#endif + #endif //SERIAL_ECHOLNPGM("CHAIN LENGTH (after tx): ", chain->length); @@ -2532,7 +2511,7 @@ static void DMASendBlocking(volatile spi_dev_t& SPI, const void *buf, size_t buf DMABusShutdown(SPI); } -#endif //HALSPI_DISABLE_DMA +#endif // HALSPI_DISABLE_DMA } // namespace MarlinESP32 diff --git a/Marlin/src/HAL/ESP32/HAL_SPI_HWgen.cpp b/Marlin/src/HAL/ESP32/HAL_SPI_HWgen.cpp index 3d5f3b31237a..0e77970f20b2 100644 --- a/Marlin/src/HAL/ESP32/HAL_SPI_HWgen.cpp +++ b/Marlin/src/HAL/ESP32/HAL_SPI_HWgen.cpp @@ -1,6 +1,6 @@ /** * Marlin 3D Printer Firmware - * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * Based on Sprinter and grbl. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm @@ -26,7 +26,7 @@ #include "../shared/HAL_SPI.h" -#if !ENABLED(SOFTWARE_SPI) && ENABLED(HALSPI_HW_GENERIC) +#if DISABLED(SOFTWARE_SPI) && ENABLED(HALSPI_HW_GENERIC) // ------------------------ // Hardware SPI @@ -34,49 +34,49 @@ static void _spi_on_error() { for (;;) { -#if defined(HALSPI_DO_ERRORBEEPS) && PIN_EXISTS(BEEPER) - OUT_WRITE(BEEPER_PIN, HIGH); - delay(500); - OUT_WRITE(BEEPER_PIN, LOW); - delay(500); - OUT_WRITE(BEEPER_PIN, HIGH); - delay(500); - OUT_WRITE(BEEPER_PIN, LOW); - delay(500); - OUT_WRITE(BEEPER_PIN, HIGH); - delay(150); - OUT_WRITE(BEEPER_PIN, LOW); - delay(150); - OUT_WRITE(BEEPER_PIN, HIGH); - delay(150); - OUT_WRITE(BEEPER_PIN, LOW); - delay(150); - OUT_WRITE(BEEPER_PIN, HIGH); - delay(150); - OUT_WRITE(BEEPER_PIN, LOW); - delay(3000); -#endif + #if defined(HALSPI_DO_ERRORBEEPS) && PIN_EXISTS(BEEPER) + OUT_WRITE(BEEPER_PIN, HIGH); + delay(500); + OUT_WRITE(BEEPER_PIN, LOW); + delay(500); + OUT_WRITE(BEEPER_PIN, HIGH); + delay(500); + OUT_WRITE(BEEPER_PIN, LOW); + delay(500); + OUT_WRITE(BEEPER_PIN, HIGH); + delay(150); + OUT_WRITE(BEEPER_PIN, LOW); + delay(150); + OUT_WRITE(BEEPER_PIN, HIGH); + delay(150); + OUT_WRITE(BEEPER_PIN, LOW); + delay(150); + OUT_WRITE(BEEPER_PIN, HIGH); + delay(150); + OUT_WRITE(BEEPER_PIN, LOW); + delay(3000); + #endif } } static void __attribute__((unused)) _spi_infobeep(uint32_t code) { -#if PIN_EXISTS(BEEPER) - OUT_WRITE(BEEPER_PIN, HIGH); - delay(500); - OUT_WRITE(BEEPER_PIN, LOW); - delay(500); - for (uint32_t n = 0; n < code; n++) { + #if PIN_EXISTS(BEEPER) OUT_WRITE(BEEPER_PIN, HIGH); - delay(200); + delay(500); OUT_WRITE(BEEPER_PIN, LOW); - delay(200); - } - delay(300); - OUT_WRITE(BEEPER_PIN, HIGH); - delay(400); - OUT_WRITE(BEEPER_PIN, LOW); - delay(1000); -#endif + delay(500); + for (uint32_t n = 0; n < code; n++) { + OUT_WRITE(BEEPER_PIN, HIGH); + delay(200); + OUT_WRITE(BEEPER_PIN, LOW); + delay(200); + } + delay(300); + OUT_WRITE(BEEPER_PIN, HIGH); + delay(400); + OUT_WRITE(BEEPER_PIN, LOW); + delay(1000); + #endif } #include @@ -102,21 +102,12 @@ void spiSetupChipSelect(int pin) { } void spiInitEx(uint32_t maxClockFreq, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { - if (hint_sck != -1) { - SET_OUTPUT(hint_sck); - } - if (hint_miso != -1) { - SET_INPUT(hint_miso); - } - if (hint_mosi != -1) { - SET_OUTPUT(hint_mosi); - } - if (hint_cs != -1) { - SET_OUTPUT(hint_cs); - } + if (hint_sck != -1) SET_OUTPUT(hint_sck); + if (hint_miso != -1) SET_INPUT(hint_miso); + if (hint_mosi != -1) SET_OUTPUT(hint_mosi); + if (hint_cs != -1) SET_OUTPUT(hint_cs); - if (_spi_initialized) - _spi_on_error(); + if (_spi_initialized) _spi_on_error(); _spi_clock = maxClockFreq; _spi_bitOrder = MSBFIRST; @@ -134,13 +125,13 @@ void spiInit(uint8_t spiRate, int hint_sck, int hint_miso, int hint_mosi, int hi switch (spiRate) { case SPI_FULL_SPEED: clock = 16000000; break; - case SPI_HALF_SPEED: clock = 8000000; break; - case SPI_QUARTER_SPEED: clock = 4000000; break; - case SPI_EIGHTH_SPEED: clock = 2000000; break; - case SPI_SIXTEENTH_SPEED: clock = 1000000; break; - case SPI_SPEED_5: clock = 500000; break; - case SPI_SPEED_6: clock = 250000; break; - default: clock = 1000000; // Default from the SPI library + case SPI_HALF_SPEED: clock = 8000000; break; + case SPI_QUARTER_SPEED: clock = 4000000; break; + case SPI_EIGHTH_SPEED: clock = 2000000; break; + case SPI_SIXTEENTH_SPEED: clock = 1000000; break; + case SPI_SPEED_5: clock = 500000; break; + case SPI_SPEED_6: clock = 250000; break; + default: clock = 1000000; // Default from the SPI library } spiInitEx(clock, hint_sck, hint_miso, hint_mosi, hint_cs); } @@ -280,6 +271,6 @@ void spiWriteRepeat16(uint16_t val, uint16_t repcnt) { } } -#endif +#endif // !SOFTWARE_SPI && HALSPI_HW_GENERIC -#endif +#endif // ARDUINO_ARCH_ESP32 diff --git a/Marlin/src/HAL/ESP32/HAL_SPI_SW.cpp b/Marlin/src/HAL/ESP32/HAL_SPI_SW.cpp index d7b0b3d23253..ef8430f63e44 100644 --- a/Marlin/src/HAL/ESP32/HAL_SPI_SW.cpp +++ b/Marlin/src/HAL/ESP32/HAL_SPI_SW.cpp @@ -1,10 +1,9 @@ /** * Marlin 3D Printer Firmware - * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * Based on Sprinter and grbl. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm - * Copyright (c) 2017 Victor Perez * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,4 +34,4 @@ #endif -#endif +#endif // ARDUINO_ARCH_ESP32 diff --git a/Marlin/src/HAL/LINUX/spi_pins.h b/Marlin/src/HAL/LINUX/spi_pins.h index 91e1f509865e..0a0032548fbb 100644 --- a/Marlin/src/HAL/LINUX/spi_pins.h +++ b/Marlin/src/HAL/LINUX/spi_pins.h @@ -25,7 +25,7 @@ #include "../../inc/MarlinConfigPre.h" #if BOTH(HAS_MARLINUI_U8GLIB, SDSUPPORT) && (LCD_PINS_D4 == SD_SCK_PIN || LCD_PINS_ENABLE == SD_MOSI_PIN || DOGLCD_SCK == SD_SCK_PIN || DOGLCD_MOSI == SD_MOSI_PIN) - #define SOFTWARE_SPI // If the SD card and LCD adapter share the same SPI pins, then software SPI is currently + #define SOFTWARE_SPI // If the SD card and LCD adapter share the same SPI pins, then software SPI is currently // needed due to the speed and mode required for communicating with each device being different. // This requirement can be removed if the SPI access to these devices is updated to use // spiBeginTransaction. diff --git a/Marlin/src/HAL/LPC1768/HAL_SPI_HW.cpp b/Marlin/src/HAL/LPC1768/HAL_SPI_HW.cpp index f04435872b02..55797747c027 100644 --- a/Marlin/src/HAL/LPC1768/HAL_SPI_HW.cpp +++ b/Marlin/src/HAL/LPC1768/HAL_SPI_HW.cpp @@ -1,6 +1,6 @@ /** * Marlin 3D Printer Firmware - * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * Based on Sprinter and grbl. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm @@ -28,7 +28,7 @@ */ /** - * Hardware SPI and Software SPI implementations are included in this file. + * Hardware SPI * * Control of the slave select pin(s) is handled by the calling routines. * @@ -58,2512 +58,2505 @@ #include "../../inc/MarlinConfig.h" -#include "../shared/HAL_SPI.h" -#include "../shared/ARM/HAL_NVIC.h" - #if DISABLED(SOFTWARE_SPI) - // Hardware SPI - - #ifndef LPC_MAINOSCILLATOR_FREQ - #error "Missing LPC176X/LPC175X main oscillator frequency (LPC_MAINOSCILLATOR_FREQ)! Consult manufacturer schematics for further details (XTAL1/XTAL2 pins as guidance)" - #endif +#include "../shared/HAL_SPI.h" +#include "../shared/ARM/HAL_NVIC.h" - static void _spi_on_error(const uint32_t code=0) { - for (;;) { - #if ENABLED(HALSPI_DO_ERRORBEEPS) && PIN_EXISTS(BEEPER) - OUT_WRITE(BEEPER_PIN, HIGH); delay(1000); - OUT_WRITE(BEEPER_PIN, LOW); delay(1000); - OUT_WRITE(BEEPER_PIN, HIGH); delay(500); - OUT_WRITE(BEEPER_PIN, LOW); if (code > 0) delay(500); - for (uint32_t n = 0; n < code; n++) { - OUT_WRITE(BEEPER_PIN, HIGH); - delay(250); - OUT_WRITE(BEEPER_PIN, LOW); - if (n < code - 1) delay(250); - } - if (code > 0) delay(800); - OUT_WRITE(BEEPER_PIN, HIGH); delay(1000); - OUT_WRITE(BEEPER_PIN, LOW); delay(2000); - #endif - } - } +#ifndef LPC_MAINOSCILLATOR_FREQ + #error "Missing LPC176X/LPC175X main oscillator frequency (LPC_MAINOSCILLATOR_FREQ)! Consult manufacturer schematics for further details (XTAL1/XTAL2 pins as guidance)" +#endif - static void __attribute__((unused)) _spi_infobeep(uint32_t code) { - #if PIN_EXISTS(BEEPER) +static void _spi_on_error(const uint32_t code=0) { + for (;;) { + #if ENABLED(HALSPI_DO_ERRORBEEPS) && PIN_EXISTS(BEEPER) + OUT_WRITE(BEEPER_PIN, HIGH); delay(1000); + OUT_WRITE(BEEPER_PIN, LOW); delay(1000); OUT_WRITE(BEEPER_PIN, HIGH); delay(500); - OUT_WRITE(BEEPER_PIN, LOW); - if (code > 0) delay(500); + OUT_WRITE(BEEPER_PIN, LOW); if (code > 0) delay(500); for (uint32_t n = 0; n < code; n++) { OUT_WRITE(BEEPER_PIN, HIGH); - delay(200); + delay(250); OUT_WRITE(BEEPER_PIN, LOW); - if (n < code-1) - delay(200); + if (n < code - 1) delay(250); } - delay(1000); - OUT_WRITE(BEEPER_PIN, HIGH); - delay(400); - OUT_WRITE(BEEPER_PIN, LOW); - delay(2000); + if (code > 0) delay(800); + OUT_WRITE(BEEPER_PIN, HIGH); delay(1000); + OUT_WRITE(BEEPER_PIN, LOW); delay(2000); #endif } +} + +static void __attribute__((unused)) _spi_infobeep(uint32_t code) { + #if PIN_EXISTS(BEEPER) + OUT_WRITE(BEEPER_PIN, HIGH); delay(500); + OUT_WRITE(BEEPER_PIN, LOW); + if (code > 0) delay(500); + for (uint32_t n = 0; n < code; n++) { + OUT_WRITE(BEEPER_PIN, HIGH); + delay(200); + OUT_WRITE(BEEPER_PIN, LOW); + if (n < code-1) + delay(200); + } + delay(1000); + OUT_WRITE(BEEPER_PIN, HIGH); + delay(400); + OUT_WRITE(BEEPER_PIN, LOW); + delay(2000); + #endif +} - template - inline numberType __MIN(numberType a, numberType b) { - return ( a < b ? a : b ); - } +template +inline numberType __MIN(numberType a, numberType b) { + return ( a < b ? a : b ); +} - namespace LPCHelpers { +namespace LPCHelpers { - // Helper. - template - struct no_volatile { - typedef T type; - }; - template - struct no_volatile : public no_volatile {}; + // Helper. + template + struct no_volatile { + typedef T type; + }; + template + struct no_volatile : public no_volatile {}; - template - inline void dwrite(volatile T& v, const T& V) noexcept { - if constexpr ( sizeof(T) == sizeof(uint8_t) ) { - (volatile uint8_t&)v = (const uint8_t&)V; - } - else if constexpr ( sizeof(T) == sizeof(uint16_t) ) { - (volatile uint16_t&)v = (const uint16_t&)V; - } - else if constexpr ( sizeof(T) == sizeof(uint32_t) ) { - (volatile uint32_t&)v = (const uint32_t&)V; - } - else { - v = V; - } + template + inline void dwrite(volatile T& v, const T& V) noexcept { + if constexpr ( sizeof(T) == sizeof(uint8_t) ) { + (volatile uint8_t&)v = (const uint8_t&)V; } - } // namespace LPCHelpers - - namespace MarlinLPC { - - #define __LPC_DEFREG(tn, n, l) static volatile tn& n = *(tn*)l - - // NXP UM10360 date: 20th of November, 2022 - - // There are pins for each "port" on the LPC1768. Do not be confused with other architectures - // where there is GPIO_0 .. GPIO_n linearly numbered. The naming convention on the LPC1768 is - // very unique. - - struct pinsel0_reg_t { - uint32_t p0_00 : 2; - uint32_t p0_01 : 2; - uint32_t p0_02 : 2; - uint32_t p0_03 : 2; - uint32_t p0_04 : 2; - uint32_t p0_05 : 2; - uint32_t p0_06 : 2; - uint32_t p0_07 : 2; - uint32_t p0_08 : 2; - uint32_t p0_09 : 2; - uint32_t p0_10 : 2; - uint32_t p0_11 : 2; - uint32_t reserved1 : 6; - uint32_t p0_15 : 2; - }; - static_assert(sizeof(pinsel0_reg_t) == 4, "invalid size of LPC pinsel0_reg_t"); - - struct pinsel1_reg_t { - uint32_t p0_16 : 2; - uint32_t p0_17 : 2; - uint32_t p0_18 : 2; - uint32_t p0_19 : 2; - uint32_t p0_20 : 2; - uint32_t p0_21 : 2; - uint32_t p0_22 : 2; - uint32_t p0_23 : 2; - uint32_t p0_24 : 2; - uint32_t p0_25 : 2; - uint32_t p0_26 : 2; - uint32_t p0_27 : 2; - uint32_t p0_28 : 2; - uint32_t p0_29 : 2; - uint32_t p0_30 : 2; - uint32_t reserved1 : 2; - }; - static_assert(sizeof(pinsel1_reg_t) == 4, "invalid size of LPC pinsel1_reg_t"); - - struct pinsel2_reg_t { - uint32_t p1_00 : 2; - uint32_t p1_01 : 2; - uint32_t reserved1 : 4; - uint32_t p1_04 : 2; - uint32_t reserved2 : 6; - uint32_t p1_08 : 2; - uint32_t p1_09 : 2; - uint32_t p1_10 : 2; - uint32_t reserved3 : 6; - uint32_t p1_14 : 2; - uint32_t p1_15 : 2; - }; - static_assert(sizeof(pinsel2_reg_t) == 4, "invalid size of LPC pinsel2_reg_t"); - - struct pinsel3_reg_t { - uint32_t p1_16 : 2; - uint32_t p1_17 : 2; - uint32_t p1_18 : 2; - uint32_t p1_19 : 2; - uint32_t p1_20 : 2; - uint32_t p1_21 : 2; - uint32_t p1_22 : 2; - uint32_t p1_23 : 2; - uint32_t p1_24 : 2; - uint32_t p1_25 : 2; - uint32_t p1_26 : 2; - uint32_t p1_27 : 2; - uint32_t p1_28 : 2; - uint32_t p1_29 : 2; - uint32_t p1_30 : 2; - uint32_t p1_31 : 2; - }; - static_assert(sizeof(pinsel3_reg_t) == 4, "invalid size of LPC pinsel3_reg_t"); - - struct pinsel4_reg_t { - uint32_t p2_00 : 2; - uint32_t p2_01 : 2; - uint32_t p2_02 : 2; - uint32_t p2_03 : 2; - uint32_t p2_04 : 2; - uint32_t p2_05 : 2; - uint32_t p2_06 : 2; - uint32_t p2_07 : 2; - uint32_t p2_08 : 2; - uint32_t p2_09 : 2; - uint32_t p2_10 : 2; - uint32_t p2_11 : 2; - uint32_t p2_12 : 2; - uint32_t p2_13 : 2; - uint32_t p2_14 : 2; - uint32_t p2_15 : 2; - }; - static_assert(sizeof(pinsel4_reg_t) == 4, "invalid size of LPC pinsel4_reg_t"); - - struct pinsel7_reg_t { - uint32_t reserved1 : 18; - uint32_t p3_25 : 2; - uint32_t p3_26 : 2; - uint32_t reserved2 : 10; - }; - static_assert(sizeof(pinsel7_reg_t) == 4, "invalid size of LPC pinsel7_reg_t"); - - struct pinsel9_reg_t { - uint32_t reserved1 : 24; - uint32_t p4_28 : 2; - uint32_t p4_29 : 2; - uint32_t reserved2 : 4; - }; - static_assert(sizeof(pinsel9_reg_t) == 4, "invalid size of LPC pinsel9_reg_t"); + else if constexpr ( sizeof(T) == sizeof(uint16_t) ) { + (volatile uint16_t&)v = (const uint16_t&)V; + } + else if constexpr ( sizeof(T) == sizeof(uint32_t) ) { + (volatile uint32_t&)v = (const uint32_t&)V; + } + else { + v = V; + } + } +} // namespace LPCHelpers + +namespace MarlinLPC { + + #define __LPC_DEFREG(tn, n, l) static volatile tn& n = *(tn*)l + + // NXP UM10360 date: 20th of November, 2022 + + // There are pins for each "port" on the LPC1768. Do not be confused with other architectures + // where there is GPIO_0 .. GPIO_n linearly numbered. The naming convention on the LPC1768 is + // very unique. + + struct pinsel0_reg_t { + uint32_t p0_00 : 2; + uint32_t p0_01 : 2; + uint32_t p0_02 : 2; + uint32_t p0_03 : 2; + uint32_t p0_04 : 2; + uint32_t p0_05 : 2; + uint32_t p0_06 : 2; + uint32_t p0_07 : 2; + uint32_t p0_08 : 2; + uint32_t p0_09 : 2; + uint32_t p0_10 : 2; + uint32_t p0_11 : 2; + uint32_t reserved1 : 6; + uint32_t p0_15 : 2; + }; + static_assert(sizeof(pinsel0_reg_t) == 4, "invalid size of LPC pinsel0_reg_t"); + + struct pinsel1_reg_t { + uint32_t p0_16 : 2; + uint32_t p0_17 : 2; + uint32_t p0_18 : 2; + uint32_t p0_19 : 2; + uint32_t p0_20 : 2; + uint32_t p0_21 : 2; + uint32_t p0_22 : 2; + uint32_t p0_23 : 2; + uint32_t p0_24 : 2; + uint32_t p0_25 : 2; + uint32_t p0_26 : 2; + uint32_t p0_27 : 2; + uint32_t p0_28 : 2; + uint32_t p0_29 : 2; + uint32_t p0_30 : 2; + uint32_t reserved1 : 2; + }; + static_assert(sizeof(pinsel1_reg_t) == 4, "invalid size of LPC pinsel1_reg_t"); + + struct pinsel2_reg_t { + uint32_t p1_00 : 2; + uint32_t p1_01 : 2; + uint32_t reserved1 : 4; + uint32_t p1_04 : 2; + uint32_t reserved2 : 6; + uint32_t p1_08 : 2; + uint32_t p1_09 : 2; + uint32_t p1_10 : 2; + uint32_t reserved3 : 6; + uint32_t p1_14 : 2; + uint32_t p1_15 : 2; + }; + static_assert(sizeof(pinsel2_reg_t) == 4, "invalid size of LPC pinsel2_reg_t"); + + struct pinsel3_reg_t { + uint32_t p1_16 : 2; + uint32_t p1_17 : 2; + uint32_t p1_18 : 2; + uint32_t p1_19 : 2; + uint32_t p1_20 : 2; + uint32_t p1_21 : 2; + uint32_t p1_22 : 2; + uint32_t p1_23 : 2; + uint32_t p1_24 : 2; + uint32_t p1_25 : 2; + uint32_t p1_26 : 2; + uint32_t p1_27 : 2; + uint32_t p1_28 : 2; + uint32_t p1_29 : 2; + uint32_t p1_30 : 2; + uint32_t p1_31 : 2; + }; + static_assert(sizeof(pinsel3_reg_t) == 4, "invalid size of LPC pinsel3_reg_t"); + + struct pinsel4_reg_t { + uint32_t p2_00 : 2; + uint32_t p2_01 : 2; + uint32_t p2_02 : 2; + uint32_t p2_03 : 2; + uint32_t p2_04 : 2; + uint32_t p2_05 : 2; + uint32_t p2_06 : 2; + uint32_t p2_07 : 2; + uint32_t p2_08 : 2; + uint32_t p2_09 : 2; + uint32_t p2_10 : 2; + uint32_t p2_11 : 2; + uint32_t p2_12 : 2; + uint32_t p2_13 : 2; + uint32_t p2_14 : 2; + uint32_t p2_15 : 2; + }; + static_assert(sizeof(pinsel4_reg_t) == 4, "invalid size of LPC pinsel4_reg_t"); - struct pinsel10_reg_t { - uint32_t reserved1 : 2; - uint32_t gpio_trace : 1; - uint32_t reserved2 : 29; - }; - static_assert(sizeof(pinsel10_reg_t) == 4, "invalid size of LPC pinsel10_reg_t"); - - #define LPC_PINMODE_PULLUP 0 - #define LPC_PINMODE_REPEATER 1 - #define LPC_PINMODE_NONE 2 - #define LPC_PINMODE_PULLDOWN 3 - - struct pinmode0_reg_t { - uint32_t p0_00mode : 2; - uint32_t p0_01mode : 2; - uint32_t p0_02mode : 2; - uint32_t p0_03mode : 2; - uint32_t p0_04mode : 2; - uint32_t p0_05mode : 2; - uint32_t p0_06mode : 2; - uint32_t p0_07mode : 2; - uint32_t p0_08mode : 2; - uint32_t p0_09mode : 2; - uint32_t p0_10mode : 2; - uint32_t p0_11mode : 2; - uint32_t reserved1 : 6; - uint32_t p0_15mode : 2; - }; - static_assert(sizeof(pinmode0_reg_t) == 4, "invalid size of LPC pinmode0_reg_t"); - - struct pinmode1_reg_t { - uint32_t p0_16mode : 2; - uint32_t p0_17mode : 2; - uint32_t p0_18mode : 2; - uint32_t p0_19mode : 2; - uint32_t p0_20mode : 2; - uint32_t p0_21mode : 2; - uint32_t p0_22mode : 2; - uint32_t p0_23mode : 2; - uint32_t p0_24mode : 2; - uint32_t p0_25mode : 2; - uint32_t p0_26mode : 2; - uint32_t reserved1 : 10; - }; - static_assert(sizeof(pinmode1_reg_t) == 4, "invalid size of pinmode1_reg_t"); - - struct pinmode2_reg_t { - uint32_t p1_00mode : 2; - uint32_t p1_01mode : 2; - uint32_t reserved1 : 4; - uint32_t p1_04mode : 2; - uint32_t reserved2 : 6; - uint32_t p1_08mode : 2; - uint32_t p1_09mode : 2; - uint32_t p1_10mode : 2; - uint32_t reserved3 : 6; - uint32_t p1_14mode : 2; - uint32_t p1_15mode : 2; - }; - static_assert(sizeof(pinmode2_reg_t) == 4, "invalid size of pinmode2_reg_t"); - - struct pinmode3_reg_t { - uint32_t p1_16mode : 2; - uint32_t p1_17mode : 2; - uint32_t p1_18mode : 2; - uint32_t p1_19mode : 2; - uint32_t p1_20mode : 2; - uint32_t p1_21mode : 2; - uint32_t p1_22mode : 2; - uint32_t p1_23mode : 2; - uint32_t p1_24mode : 2; - uint32_t p1_25mode : 2; - uint32_t p1_26mode : 2; - uint32_t p1_27mode : 2; - uint32_t p1_28mode : 2; - uint32_t p1_29mode : 2; - uint32_t p1_30mode : 2; - uint32_t p1_31mode : 2; - }; - static_assert(sizeof(pinmode3_reg_t) == 4, "invalid size of pinmode3_reg_t"); - - struct pinmode4_reg_t { - uint32_t p2_00mode : 2; - uint32_t p2_01mode : 2; - uint32_t p2_02mode : 2; - uint32_t p2_03mode : 2; - uint32_t p2_04mode : 2; - uint32_t p2_05mode : 2; - uint32_t p2_06mode : 2; - uint32_t p2_07mode : 2; - uint32_t p2_08mode : 2; - uint32_t p2_09mode : 2; - uint32_t p2_10mode : 2; - uint32_t p2_11mode : 2; - uint32_t p2_12mode : 2; - uint32_t p2_13mode : 2; - uint32_t reserved1 : 4; - }; - static_assert(sizeof(pinmode4_reg_t) == 4, "invalid size of pinmode4_reg_t"); + struct pinsel7_reg_t { + uint32_t reserved1 : 18; + uint32_t p3_25 : 2; + uint32_t p3_26 : 2; + uint32_t reserved2 : 10; + }; + static_assert(sizeof(pinsel7_reg_t) == 4, "invalid size of LPC pinsel7_reg_t"); - struct pinmode7_reg_t { - uint32_t reserved1 : 18; - uint32_t p3_25mode : 2; - uint32_t p3_26mode : 2; - uint32_t reserved2 : 10; - }; - static_assert(sizeof(pinmode7_reg_t) == 4, "invalid size of pinmode7_reg_t"); + struct pinsel9_reg_t { + uint32_t reserved1 : 24; + uint32_t p4_28 : 2; + uint32_t p4_29 : 2; + uint32_t reserved2 : 4; + }; + static_assert(sizeof(pinsel9_reg_t) == 4, "invalid size of LPC pinsel9_reg_t"); - struct pinmode9_reg_t { - uint32_t reserved1 : 24; - uint32_t p4_28mode : 2; - uint32_t p4_29mode : 2; - uint32_t reserved2 : 4; - }; - static_assert(sizeof(pinmode9_reg_t) == 4, "invalid size of pinmode9_reg_t"); - - __LPC_DEFREG(pinsel0_reg_t, PINSEL0, 0x4002C000); - __LPC_DEFREG(pinsel1_reg_t, PINSEL1, 0x4002C004); - __LPC_DEFREG(pinsel2_reg_t, PINSEL2, 0x4002C008); - __LPC_DEFREG(pinsel3_reg_t, PINSEL3, 0x4002C00C); - __LPC_DEFREG(pinsel4_reg_t, PINSEL4, 0x4002C010); - __LPC_DEFREG(pinsel7_reg_t, PINSEL7, 0x4002C01C); - //__LPC_DEFREG(pinsel8_reg_t, PINSEL8, 0x4002C020); - __LPC_DEFREG(pinsel9_reg_t, PINSEL9, 0x4002C024); - __LPC_DEFREG(pinsel10_reg_t, PINSEL10, 0x4002C028); - - __LPC_DEFREG(pinmode0_reg_t, PINMODE0, 0x4002C040); - __LPC_DEFREG(pinmode1_reg_t, PINMODE1, 0x4002C044); - __LPC_DEFREG(pinmode2_reg_t, PINMODE2, 0x4002C048); - __LPC_DEFREG(pinmode3_reg_t, PINMODE3, 0x4002C04C); - __LPC_DEFREG(pinmode4_reg_t, PINMODE4, 0x4002C050); - //__LPC_DEFREG(pinmode5_reg_t, PINMODE5, 0x4002C054); - //__LPC_DEFREG(pinmode6_reg_t, PINMODE6, 0x4002C058); - __LPC_DEFREG(pinmode7_reg_t, PINMODE7, 0x4002C05C); - __LPC_DEFREG(pinmode9_reg_t, PINMODE9, 0x4002C064); - - // Left out OD and I2C-specific. - // UM10360 page 103: I am only taking the pin descriptions for LPC176x - // but support could (easily) be enabled for LPC175x aswell, if the community demands it. + struct pinsel10_reg_t { + uint32_t reserved1 : 2; + uint32_t gpio_trace : 1; + uint32_t reserved2 : 29; + }; + static_assert(sizeof(pinsel10_reg_t) == 4, "invalid size of LPC pinsel10_reg_t"); + + #define LPC_PINMODE_PULLUP 0 + #define LPC_PINMODE_REPEATER 1 + #define LPC_PINMODE_NONE 2 + #define LPC_PINMODE_PULLDOWN 3 + + struct pinmode0_reg_t { + uint32_t p0_00mode : 2; + uint32_t p0_01mode : 2; + uint32_t p0_02mode : 2; + uint32_t p0_03mode : 2; + uint32_t p0_04mode : 2; + uint32_t p0_05mode : 2; + uint32_t p0_06mode : 2; + uint32_t p0_07mode : 2; + uint32_t p0_08mode : 2; + uint32_t p0_09mode : 2; + uint32_t p0_10mode : 2; + uint32_t p0_11mode : 2; + uint32_t reserved1 : 6; + uint32_t p0_15mode : 2; + }; + static_assert(sizeof(pinmode0_reg_t) == 4, "invalid size of LPC pinmode0_reg_t"); + + struct pinmode1_reg_t { + uint32_t p0_16mode : 2; + uint32_t p0_17mode : 2; + uint32_t p0_18mode : 2; + uint32_t p0_19mode : 2; + uint32_t p0_20mode : 2; + uint32_t p0_21mode : 2; + uint32_t p0_22mode : 2; + uint32_t p0_23mode : 2; + uint32_t p0_24mode : 2; + uint32_t p0_25mode : 2; + uint32_t p0_26mode : 2; + uint32_t reserved1 : 10; + }; + static_assert(sizeof(pinmode1_reg_t) == 4, "invalid size of pinmode1_reg_t"); + + struct pinmode2_reg_t { + uint32_t p1_00mode : 2; + uint32_t p1_01mode : 2; + uint32_t reserved1 : 4; + uint32_t p1_04mode : 2; + uint32_t reserved2 : 6; + uint32_t p1_08mode : 2; + uint32_t p1_09mode : 2; + uint32_t p1_10mode : 2; + uint32_t reserved3 : 6; + uint32_t p1_14mode : 2; + uint32_t p1_15mode : 2; + }; + static_assert(sizeof(pinmode2_reg_t) == 4, "invalid size of pinmode2_reg_t"); + + struct pinmode3_reg_t { + uint32_t p1_16mode : 2; + uint32_t p1_17mode : 2; + uint32_t p1_18mode : 2; + uint32_t p1_19mode : 2; + uint32_t p1_20mode : 2; + uint32_t p1_21mode : 2; + uint32_t p1_22mode : 2; + uint32_t p1_23mode : 2; + uint32_t p1_24mode : 2; + uint32_t p1_25mode : 2; + uint32_t p1_26mode : 2; + uint32_t p1_27mode : 2; + uint32_t p1_28mode : 2; + uint32_t p1_29mode : 2; + uint32_t p1_30mode : 2; + uint32_t p1_31mode : 2; + }; + static_assert(sizeof(pinmode3_reg_t) == 4, "invalid size of pinmode3_reg_t"); + + struct pinmode4_reg_t { + uint32_t p2_00mode : 2; + uint32_t p2_01mode : 2; + uint32_t p2_02mode : 2; + uint32_t p2_03mode : 2; + uint32_t p2_04mode : 2; + uint32_t p2_05mode : 2; + uint32_t p2_06mode : 2; + uint32_t p2_07mode : 2; + uint32_t p2_08mode : 2; + uint32_t p2_09mode : 2; + uint32_t p2_10mode : 2; + uint32_t p2_11mode : 2; + uint32_t p2_12mode : 2; + uint32_t p2_13mode : 2; + uint32_t reserved1 : 4; + }; + static_assert(sizeof(pinmode4_reg_t) == 4, "invalid size of pinmode4_reg_t"); - #if 0 + struct pinmode7_reg_t { + uint32_t reserved1 : 18; + uint32_t p3_25mode : 2; + uint32_t p3_26mode : 2; + uint32_t reserved2 : 10; + }; + static_assert(sizeof(pinmode7_reg_t) == 4, "invalid size of pinmode7_reg_t"); - #define LPC_GPIODIR_INPUT 0 - #define LPC_GPIODIR_OUTPUT 1 + struct pinmode9_reg_t { + uint32_t reserved1 : 24; + uint32_t p4_28mode : 2; + uint32_t p4_29mode : 2; + uint32_t reserved2 : 4; + }; + static_assert(sizeof(pinmode9_reg_t) == 4, "invalid size of pinmode9_reg_t"); + + __LPC_DEFREG(pinsel0_reg_t, PINSEL0, 0x4002C000); + __LPC_DEFREG(pinsel1_reg_t, PINSEL1, 0x4002C004); + __LPC_DEFREG(pinsel2_reg_t, PINSEL2, 0x4002C008); + __LPC_DEFREG(pinsel3_reg_t, PINSEL3, 0x4002C00C); + __LPC_DEFREG(pinsel4_reg_t, PINSEL4, 0x4002C010); + __LPC_DEFREG(pinsel7_reg_t, PINSEL7, 0x4002C01C); + //__LPC_DEFREG(pinsel8_reg_t, PINSEL8, 0x4002C020); + __LPC_DEFREG(pinsel9_reg_t, PINSEL9, 0x4002C024); + __LPC_DEFREG(pinsel10_reg_t, PINSEL10, 0x4002C028); + + __LPC_DEFREG(pinmode0_reg_t, PINMODE0, 0x4002C040); + __LPC_DEFREG(pinmode1_reg_t, PINMODE1, 0x4002C044); + __LPC_DEFREG(pinmode2_reg_t, PINMODE2, 0x4002C048); + __LPC_DEFREG(pinmode3_reg_t, PINMODE3, 0x4002C04C); + __LPC_DEFREG(pinmode4_reg_t, PINMODE4, 0x4002C050); + //__LPC_DEFREG(pinmode5_reg_t, PINMODE5, 0x4002C054); + //__LPC_DEFREG(pinmode6_reg_t, PINMODE6, 0x4002C058); + __LPC_DEFREG(pinmode7_reg_t, PINMODE7, 0x4002C05C); + __LPC_DEFREG(pinmode9_reg_t, PINMODE9, 0x4002C064); + + // Left out OD and I2C-specific. + // UM10360 page 103: I am only taking the pin descriptions for LPC176x + // but support could (easily) be enabled for LPC175x aswell, if the community demands it. + + #if 0 + + #define LPC_GPIODIR_INPUT 0 + #define LPC_GPIODIR_OUTPUT 1 + + struct fioXdir_reg_t { + uint32_t val; + + inline void set(uint8_t reg, uint8_t val) { + if (val == LPC_GPIODIR_INPUT) + val &= ~(1<> reg ); + } + }; - struct fioXmask_reg_t { - uint32_t val; + struct fioXpin_reg_t { + uint32_t val; - inline void set(uint8_t reg, bool enable) { - if (enable) - val |= (1<> reg ); - } - }; + inline void set(uint8_t reg, bool high) { + if (high) + val |= (1<> reg ); + } + }; - struct fioXpin_reg_t { - uint32_t val; + __LPC_DEFREG(fioXdir_reg_t, FIO0DIR, 0x2009C000); + __LPC_DEFREG(fioXdir_reg_t, FIO1DIR, 0x2009C020); + __LPC_DEFREG(fioXdir_reg_t, FIO2DIR, 0x2009C040); + __LPC_DEFREG(fioXdir_reg_t, FIO3DIR, 0x2009C060); + __LPC_DEFREG(fioXdir_reg_t, FIO4DIR, 0x2009C080); - inline void set(uint8_t reg, bool high) { - if (high) - val |= (1<> reg ); - } - }; + __LPC_DEFREG(fioXmask_reg_t, FIO0MASK, 0x2009C010); + __LPC_DEFREG(fioXmask_reg_t, FIO1MASK, 0x2009C030); + __LPC_DEFREG(fioXmask_reg_t, FIO2MASK, 0x2009C050); + __LPC_DEFREG(fioXmask_reg_t, FIO3MASK, 0x2009C070); + __LPC_DEFREG(fioXmask_reg_t, FIO4MASK, 0x2009C090); - __LPC_DEFREG(fioXdir_reg_t, FIO0DIR, 0x2009C000); - __LPC_DEFREG(fioXdir_reg_t, FIO1DIR, 0x2009C020); - __LPC_DEFREG(fioXdir_reg_t, FIO2DIR, 0x2009C040); - __LPC_DEFREG(fioXdir_reg_t, FIO3DIR, 0x2009C060); - __LPC_DEFREG(fioXdir_reg_t, FIO4DIR, 0x2009C080); + __LPC_DEFREG(fioXpin_reg_t, FIO0PIN, 0x2009C014); + __LPC_DEFREG(fioXpin_reg_t, FIO1PIN, 0x2009C034); + __LPC_DEFREG(fioXpin_reg_t, FIO2PIN, 0x2009C054); + __LPC_DEFREG(fioXpin_reg_t, FIO3PIN, 0x2009C074); + __LPC_DEFREG(fioXpin_reg_t, FIO4PIN, 0x2009C094); - __LPC_DEFREG(fioXmask_reg_t, FIO0MASK, 0x2009C010); - __LPC_DEFREG(fioXmask_reg_t, FIO1MASK, 0x2009C030); - __LPC_DEFREG(fioXmask_reg_t, FIO2MASK, 0x2009C050); - __LPC_DEFREG(fioXmask_reg_t, FIO3MASK, 0x2009C070); - __LPC_DEFREG(fioXmask_reg_t, FIO4MASK, 0x2009C090); + #endif - __LPC_DEFREG(fioXpin_reg_t, FIO0PIN, 0x2009C014); - __LPC_DEFREG(fioXpin_reg_t, FIO1PIN, 0x2009C034); - __LPC_DEFREG(fioXpin_reg_t, FIO2PIN, 0x2009C054); - __LPC_DEFREG(fioXpin_reg_t, FIO3PIN, 0x2009C074); - __LPC_DEFREG(fioXpin_reg_t, FIO4PIN, 0x2009C094); + // Find a valid port-mapping for the given GPIO to a SPI bus peripheral. + // If it fails then a recommended SPI bus with a recommended set of GPIO + // pins should be used. + // The LPC1768 is a really good architecture, even though in comparison + // to the ESP32 it does not support mapping any peripheral signal to any + // GPIO pin. + struct portMapResult_t { + inline portMapResult_t() { + func = 0xFF; + } + inline bool isMapped() const { + return ( func != 0xFF ); + } + uint8_t func; + }; - #endif + static bool SPIFindPortMapping( + int gpio_sck, int gpio_miso, int gpio_mosi, int gpio_cs, + uint8_t &sspBusOut, portMapResult_t &map_sck_out, portMapResult_t &map_miso_out, portMapResult_t &map_mosi_out, portMapResult_t &map_cs_out + ) { + portMapResult_t map_sck, map_miso, map_mosi, map_cs; + bool found = false; - // Find a valid port-mapping for the given GPIO to a SPI bus peripheral. - // If it fails then a recommended SPI bus with a recommended set of GPIO - // pins should be used. - // The LPC1768 is a really good architecture, even though in comparison - // to the ESP32 it does not support mapping any peripheral signal to any - // GPIO pin. - struct portMapResult_t { - inline portMapResult_t() { - func = 0xFF; + if ((gpio_sck == P0_15 || gpio_sck == P1_20) || (gpio_miso == P0_17 || gpio_miso == P1_23) || (gpio_mosi == P0_18 || gpio_mosi == P1_24) || (gpio_cs == P0_16 || gpio_cs == P1_21)) { + sspBusOut = 0; + if (gpio_sck == P0_15) { + map_sck.func = 2; } - inline bool isMapped() const { - return ( func != 0xFF ); + else if (gpio_sck == P1_20) { + map_sck.func = 3; } - uint8_t func; - }; - - static bool SPIFindPortMapping( - int gpio_sck, int gpio_miso, int gpio_mosi, int gpio_cs, - uint8_t &sspBusOut, portMapResult_t &map_sck_out, portMapResult_t &map_miso_out, portMapResult_t &map_mosi_out, portMapResult_t &map_cs_out - ) { - portMapResult_t map_sck, map_miso, map_mosi, map_cs; - bool found = false; - - if ((gpio_sck == P0_15 || gpio_sck == P1_20) || (gpio_miso == P0_17 || gpio_miso == P1_23) || (gpio_mosi == P0_18 || gpio_mosi == P1_24) || (gpio_cs == P0_16 || gpio_cs == P1_21)) { - sspBusOut = 0; - if (gpio_sck == P0_15) { - map_sck.func = 2; - } - else if (gpio_sck == P1_20) { - map_sck.func = 3; - } - if (gpio_miso == P0_17) { - map_miso.func = 2; - } - else if (gpio_miso == P1_23) { - map_miso.func = 3; - } - if (gpio_mosi == P0_18) { - map_mosi.func = 2; - } - else if (gpio_mosi == P1_24) { - map_mosi.func = 3; - } - if (gpio_cs == P0_16) { - map_cs.func = 2; - } - else if (gpio_cs == P1_21) { - map_cs.func = 3; - } - found = true; + if (gpio_miso == P0_17) { + map_miso.func = 2; } - else if ((gpio_sck == P0_07 || gpio_sck == P1_31) || gpio_miso == P0_08 || gpio_mosi == P0_09 || gpio_cs == P0_06) { - sspBusOut = 1; - if (gpio_sck == P0_07) { - map_sck.func = 2; - } - else if (gpio_sck == P1_31) { - map_sck.func = 2; - } - if (gpio_miso == P0_08) { - map_miso.func = 2; - } - if (gpio_mosi == P0_09) { - map_mosi.func = 2; - } - if (gpio_cs == P0_06) { - map_cs.func = 2; - } - found = true; + else if (gpio_miso == P1_23) { + map_miso.func = 3; } - if (found) { - map_sck_out = map_sck; - map_miso_out = map_miso; - map_mosi_out = map_mosi; - map_cs_out = map_cs; + if (gpio_mosi == P0_18) { + map_mosi.func = 2; } - return found; - } - - struct gpioMapResult_t { - uint8_t sspBusIdx; - int gpio_sck; - int gpio_miso; - int gpio_mosi; - int gpio_cs; - }; - - static void MapPortPinFunc(int pin, uint8_t func) { - #define _SWENT_MPPF(PS,PT,PN) case P##PT##_##PN: PINSEL##PS.p##PT##_##PN = func; break; - switch (pin) { - _SWENT_MPPF(0,0,00)_SWENT_MPPF(0,0,01)_SWENT_MPPF(0,0,02)_SWENT_MPPF(0,0,03)_SWENT_MPPF(0,0,04)_SWENT_MPPF(0,0,05)_SWENT_MPPF(0,0,06)_SWENT_MPPF(0,0,07) - _SWENT_MPPF(0,0,08)_SWENT_MPPF(0,0,09)_SWENT_MPPF(0,0,10)_SWENT_MPPF(0,0,11)_SWENT_MPPF(0,0,15) - _SWENT_MPPF(1,0,16)_SWENT_MPPF(1,0,17)_SWENT_MPPF(1,0,18)_SWENT_MPPF(1,0,19)_SWENT_MPPF(1,0,20) - _SWENT_MPPF(1,0,21)_SWENT_MPPF(1,0,22)_SWENT_MPPF(1,0,23)_SWENT_MPPF(1,0,24)_SWENT_MPPF(1,0,25) - _SWENT_MPPF(1,0,26)_SWENT_MPPF(1,0,27)_SWENT_MPPF(1,0,28)_SWENT_MPPF(1,0,29)_SWENT_MPPF(1,0,30) - _SWENT_MPPF(2,1,00)_SWENT_MPPF(2,1,01)_SWENT_MPPF(2,1,04)_SWENT_MPPF(2,1,08)_SWENT_MPPF(2,1,09)_SWENT_MPPF(2,1,10) - _SWENT_MPPF(2,1,14)_SWENT_MPPF(2,1,15) - _SWENT_MPPF(3,1,16)_SWENT_MPPF(3,1,17)_SWENT_MPPF(3,1,18)_SWENT_MPPF(3,1,19)_SWENT_MPPF(3,1,20) - _SWENT_MPPF(3,1,21)_SWENT_MPPF(3,1,22)_SWENT_MPPF(3,1,23)_SWENT_MPPF(3,1,24)_SWENT_MPPF(3,1,25) - _SWENT_MPPF(3,1,26)_SWENT_MPPF(3,1,27)_SWENT_MPPF(3,1,28)_SWENT_MPPF(3,1,29)_SWENT_MPPF(3,1,30) - _SWENT_MPPF(3,1,31) - _SWENT_MPPF(4,2,00)_SWENT_MPPF(4,2,01)_SWENT_MPPF(4,2,02)_SWENT_MPPF(4,2,03)_SWENT_MPPF(4,2,04) - _SWENT_MPPF(4,2,05)_SWENT_MPPF(4,2,06)_SWENT_MPPF(4,2,07)_SWENT_MPPF(4,2,08)_SWENT_MPPF(4,2,09) - _SWENT_MPPF(4,2,10)_SWENT_MPPF(4,2,11)_SWENT_MPPF(4,2,12)_SWENT_MPPF(4,2,13) - _SWENT_MPPF(7,3,25)_SWENT_MPPF(7,3,26) - _SWENT_MPPF(9,4,28)_SWENT_MPPF(9,4,29) + else if (gpio_mosi == P1_24) { + map_mosi.func = 3; } - #undef _SWENT_MPPF - } - - static void SetPortPinMode(int pin, uint8_t mode) { - #define _SWENT_MPPM(PM,PT,PN) case P##PT##_##PN: PINMODE##PM.p##PT##_##PN##mode = mode; break; - switch (pin) { - _SWENT_MPPM(0,0,00)_SWENT_MPPM(0,0,01)_SWENT_MPPM(0,0,02)_SWENT_MPPM(0,0,03)_SWENT_MPPM(0,0,04)_SWENT_MPPM(0,0,05) - _SWENT_MPPM(0,0,06)_SWENT_MPPM(0,0,07)_SWENT_MPPM(0,0,08)_SWENT_MPPM(0,0,09)_SWENT_MPPM(0,0,10)_SWENT_MPPM(0,0,11) - _SWENT_MPPM(0,0,15) - _SWENT_MPPM(1,0,16)_SWENT_MPPM(1,0,17)_SWENT_MPPM(1,0,18)_SWENT_MPPM(1,0,19)_SWENT_MPPM(1,0,20)_SWENT_MPPM(1,0,21) - _SWENT_MPPM(1,0,22)_SWENT_MPPM(1,0,23)_SWENT_MPPM(1,0,24)_SWENT_MPPM(1,0,25)_SWENT_MPPM(1,0,26) - _SWENT_MPPM(2,1,00)_SWENT_MPPM(2,1,01)_SWENT_MPPM(2,1,04)_SWENT_MPPM(2,1,08)_SWENT_MPPM(2,1,09)_SWENT_MPPM(2,1,10) - _SWENT_MPPM(2,1,14)_SWENT_MPPM(2,1,15) - _SWENT_MPPM(3,1,16)_SWENT_MPPM(3,1,17)_SWENT_MPPM(3,1,18)_SWENT_MPPM(3,1,19)_SWENT_MPPM(3,1,20)_SWENT_MPPM(3,1,21) - _SWENT_MPPM(3,1,22)_SWENT_MPPM(3,1,23)_SWENT_MPPM(3,1,24)_SWENT_MPPM(3,1,25)_SWENT_MPPM(3,1,26)_SWENT_MPPM(3,1,27) - _SWENT_MPPM(3,1,28)_SWENT_MPPM(3,1,29)_SWENT_MPPM(3,1,30)_SWENT_MPPM(3,1,31) - _SWENT_MPPM(4,2,00)_SWENT_MPPM(4,2,01)_SWENT_MPPM(4,2,02)_SWENT_MPPM(4,2,03)_SWENT_MPPM(4,2,04)_SWENT_MPPM(4,2,05) - _SWENT_MPPM(4,2,06)_SWENT_MPPM(4,2,07)_SWENT_MPPM(4,2,08)_SWENT_MPPM(4,2,09)_SWENT_MPPM(4,2,10)_SWENT_MPPM(4,2,11) - _SWENT_MPPM(4,2,12)_SWENT_MPPM(4,2,13) - _SWENT_MPPM(7,3,25)_SWENT_MPPM(7,3,26) - _SWENT_MPPM(9,4,28)_SWENT_MPPM(9,4,29) + if (gpio_cs == P0_16) { + map_cs.func = 2; } - #undef _SWENT_MPPM - } - - #if 0 - static void SetPortPinDirection(int pin, uint8_t dir) { - #define _SWENT_SPPD_(PT,PNN,PN) case P##PT##_##PNN: FIO##PT##DIR.set(PN, dir); break; - #define _SWENT_SPPD(PT,PN) case P##PT##_##PN: FIO##PT##DIR.set(PN, dir); break; - switch (pin) { - _SWENT_SPPD_(0,00,0)_SWENT_SPPD_(0,01,1)_SWENT_SPPD_(0,02,2)_SWENT_SPPD_(0,03,3)_SWENT_SPPD_(0,04,4)_SWENT_SPPD_(0,05,5)_SWENT_SPPD_(0,06,6) - _SWENT_SPPD_(0,07,7)_SWENT_SPPD_(0,08,8)_SWENT_SPPD_(0,09,9)_SWENT_SPPD(0,10)_SWENT_SPPD(0,11)_SWENT_SPPD(0,15)_SWENT_SPPD(0,16) - _SWENT_SPPD(0,17)_SWENT_SPPD(0,18)_SWENT_SPPD(0,19)_SWENT_SPPD(0,20)_SWENT_SPPD(0,21)_SWENT_SPPD(0,22)_SWENT_SPPD(0,23) - _SWENT_SPPD(0,24)_SWENT_SPPD(0,25)_SWENT_SPPD(0,26)_SWENT_SPPD(0,27)_SWENT_SPPD(0,28)_SWENT_SPPD(0,29)_SWENT_SPPD(0,30) - _SWENT_SPPD_(1,00,0)_SWENT_SPPD_(1,01,1)_SWENT_SPPD_(1,04,4)_SWENT_SPPD_(1,08,8)_SWENT_SPPD_(1,09,9)_SWENT_SPPD(1,10)_SWENT_SPPD(1,14) - _SWENT_SPPD(1,15)_SWENT_SPPD(1,16)_SWENT_SPPD(1,17)_SWENT_SPPD(1,18)_SWENT_SPPD(1,19)_SWENT_SPPD(1,20)_SWENT_SPPD(1,21) - _SWENT_SPPD(1,22)_SWENT_SPPD(1,23)_SWENT_SPPD(1,24)_SWENT_SPPD(1,25)_SWENT_SPPD(1,26)_SWENT_SPPD(1,27)_SWENT_SPPD(1,28) - _SWENT_SPPD(1,29)_SWENT_SPPD(1,30)_SWENT_SPPD(1,31) - _SWENT_SPPD_(2,00,0)_SWENT_SPPD_(2,01,1)_SWENT_SPPD_(2,02,2)_SWENT_SPPD_(2,03,3)_SWENT_SPPD_(2,04,4)_SWENT_SPPD_(2,05,5)_SWENT_SPPD_(2,06,6)_SWENT_SPPD_(2,07,7) - _SWENT_SPPD_(2,08,8)_SWENT_SPPD_(2,09,9)_SWENT_SPPD(2,10)_SWENT_SPPD(2,11)_SWENT_SPPD(2,12)_SWENT_SPPD(2,13) - _SWENT_SPPD(3,25)_SWENT_SPPD(3,26) - _SWENT_SPPD(4,28)_SWENT_SPPD(4,29) + else if (gpio_cs == P1_21) { + map_cs.func = 3; } - #undef _SWENT_SPPD - #undef _SWENT_SPPD_ + found = true; } - #endif - - static gpioMapResult_t SPIMapGPIO(int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { - // First try to find a direct mapping to SSP peripheral based on the given pin hints. - uint8_t sspBusIdx; - portMapResult_t map_sck, map_miso, map_mosi, map_cs; - - bool foundPortMap = SPIFindPortMapping(hint_sck, hint_miso, hint_mosi, hint_cs, sspBusIdx, map_sck, map_miso, map_mosi, map_cs); - - if (!foundPortMap) { - // Just select the default SSP config. - sspBusIdx = 0; - hint_sck = P0_15; + else if ((gpio_sck == P0_07 || gpio_sck == P1_31) || gpio_miso == P0_08 || gpio_mosi == P0_09 || gpio_cs == P0_06) { + sspBusOut = 1; + if (gpio_sck == P0_07) { + map_sck.func = 2; + } + else if (gpio_sck == P1_31) { map_sck.func = 2; - hint_miso = P0_17; + } + if (gpio_miso == P0_08) { map_miso.func = 2; - hint_mosi = P0_18; + } + if (gpio_mosi == P0_09) { map_mosi.func = 2; - hint_cs = P0_16; + } + if (gpio_cs == P0_06) { map_cs.func = 2; } + found = true; + } + if (found) { + map_sck_out = map_sck; + map_miso_out = map_miso; + map_mosi_out = map_mosi; + map_cs_out = map_cs; + } + return found; + } - // Map the functions that exist. - if (map_sck.isMapped()) { - MapPortPinFunc(hint_sck, map_sck.func); - SetPortPinMode(hint_sck, LPC_PINMODE_NONE); - } - if (map_miso.isMapped()) { - MapPortPinFunc(hint_miso, map_miso.func); - SetPortPinMode(hint_miso, LPC_PINMODE_PULLDOWN); - } - if (map_mosi.isMapped()) { - MapPortPinFunc(hint_mosi, map_mosi.func); - SetPortPinMode(hint_mosi, LPC_PINMODE_NONE); - } - #if 0 - if (map_cs.isMapped()) { - MapPortPinFunc(hint_cs, map_cs.func); - SetPortPinMode(hint_cs, LPC_PINMODE_NONE); - } - #endif + struct gpioMapResult_t { + uint8_t sspBusIdx; + int gpio_sck; + int gpio_miso; + int gpio_mosi; + int gpio_cs; + }; - gpioMapResult_t res; - res.sspBusIdx = sspBusIdx; - res.gpio_sck = ( map_sck.isMapped() ? hint_sck : -1 ); - res.gpio_miso = ( map_miso.isMapped() ? hint_miso : -1 ); - res.gpio_mosi = ( map_mosi.isMapped() ? hint_mosi : -1 ); - res.gpio_cs = ( map_cs.isMapped() ? hint_cs : -1 ); - return res; + static void MapPortPinFunc(int pin, uint8_t func) { + #define _SWENT_MPPF(PS,PT,PN) case P##PT##_##PN: PINSEL##PS.p##PT##_##PN = func; break; + switch (pin) { + _SWENT_MPPF(0,0,00)_SWENT_MPPF(0,0,01)_SWENT_MPPF(0,0,02)_SWENT_MPPF(0,0,03)_SWENT_MPPF(0,0,04)_SWENT_MPPF(0,0,05)_SWENT_MPPF(0,0,06)_SWENT_MPPF(0,0,07) + _SWENT_MPPF(0,0,08)_SWENT_MPPF(0,0,09)_SWENT_MPPF(0,0,10)_SWENT_MPPF(0,0,11)_SWENT_MPPF(0,0,15) + _SWENT_MPPF(1,0,16)_SWENT_MPPF(1,0,17)_SWENT_MPPF(1,0,18)_SWENT_MPPF(1,0,19)_SWENT_MPPF(1,0,20) + _SWENT_MPPF(1,0,21)_SWENT_MPPF(1,0,22)_SWENT_MPPF(1,0,23)_SWENT_MPPF(1,0,24)_SWENT_MPPF(1,0,25) + _SWENT_MPPF(1,0,26)_SWENT_MPPF(1,0,27)_SWENT_MPPF(1,0,28)_SWENT_MPPF(1,0,29)_SWENT_MPPF(1,0,30) + _SWENT_MPPF(2,1,00)_SWENT_MPPF(2,1,01)_SWENT_MPPF(2,1,04)_SWENT_MPPF(2,1,08)_SWENT_MPPF(2,1,09)_SWENT_MPPF(2,1,10) + _SWENT_MPPF(2,1,14)_SWENT_MPPF(2,1,15) + _SWENT_MPPF(3,1,16)_SWENT_MPPF(3,1,17)_SWENT_MPPF(3,1,18)_SWENT_MPPF(3,1,19)_SWENT_MPPF(3,1,20) + _SWENT_MPPF(3,1,21)_SWENT_MPPF(3,1,22)_SWENT_MPPF(3,1,23)_SWENT_MPPF(3,1,24)_SWENT_MPPF(3,1,25) + _SWENT_MPPF(3,1,26)_SWENT_MPPF(3,1,27)_SWENT_MPPF(3,1,28)_SWENT_MPPF(3,1,29)_SWENT_MPPF(3,1,30) + _SWENT_MPPF(3,1,31) + _SWENT_MPPF(4,2,00)_SWENT_MPPF(4,2,01)_SWENT_MPPF(4,2,02)_SWENT_MPPF(4,2,03)_SWENT_MPPF(4,2,04) + _SWENT_MPPF(4,2,05)_SWENT_MPPF(4,2,06)_SWENT_MPPF(4,2,07)_SWENT_MPPF(4,2,08)_SWENT_MPPF(4,2,09) + _SWENT_MPPF(4,2,10)_SWENT_MPPF(4,2,11)_SWENT_MPPF(4,2,12)_SWENT_MPPF(4,2,13) + _SWENT_MPPF(7,3,25)_SWENT_MPPF(7,3,26) + _SWENT_MPPF(9,4,28)_SWENT_MPPF(9,4,29) } + #undef _SWENT_MPPF + } - static void SPIUnmapGPIO(const gpioMapResult_t &res) { - // Reset to architecture default configs on the pins that we previously mapped. - if (res.gpio_sck >= 0) { - MapPortPinFunc(res.gpio_sck, 0); - SetPortPinMode(res.gpio_sck, LPC_PINMODE_PULLDOWN); - } - if (res.gpio_miso >= 0) { - MapPortPinFunc(res.gpio_miso, 0); - SetPortPinMode(res.gpio_miso, LPC_PINMODE_PULLDOWN); - } - if (res.gpio_mosi >= 0) { - MapPortPinFunc(res.gpio_mosi, 0); - SetPortPinMode(res.gpio_mosi, LPC_PINMODE_PULLDOWN); - } - #if 0 - if (res.gpio_cs >= 0) { - MapPortPinFunc(res.gpio_cs, 0); - SetPortPinMode(res.gpio_cs, LPC_PINMODE_PULLDOWN); - } - #endif + static void SetPortPinMode(int pin, uint8_t mode) { + #define _SWENT_MPPM(PM,PT,PN) case P##PT##_##PN: PINMODE##PM.p##PT##_##PN##mode = mode; break; + switch (pin) { + _SWENT_MPPM(0,0,00)_SWENT_MPPM(0,0,01)_SWENT_MPPM(0,0,02)_SWENT_MPPM(0,0,03)_SWENT_MPPM(0,0,04)_SWENT_MPPM(0,0,05) + _SWENT_MPPM(0,0,06)_SWENT_MPPM(0,0,07)_SWENT_MPPM(0,0,08)_SWENT_MPPM(0,0,09)_SWENT_MPPM(0,0,10)_SWENT_MPPM(0,0,11) + _SWENT_MPPM(0,0,15) + _SWENT_MPPM(1,0,16)_SWENT_MPPM(1,0,17)_SWENT_MPPM(1,0,18)_SWENT_MPPM(1,0,19)_SWENT_MPPM(1,0,20)_SWENT_MPPM(1,0,21) + _SWENT_MPPM(1,0,22)_SWENT_MPPM(1,0,23)_SWENT_MPPM(1,0,24)_SWENT_MPPM(1,0,25)_SWENT_MPPM(1,0,26) + _SWENT_MPPM(2,1,00)_SWENT_MPPM(2,1,01)_SWENT_MPPM(2,1,04)_SWENT_MPPM(2,1,08)_SWENT_MPPM(2,1,09)_SWENT_MPPM(2,1,10) + _SWENT_MPPM(2,1,14)_SWENT_MPPM(2,1,15) + _SWENT_MPPM(3,1,16)_SWENT_MPPM(3,1,17)_SWENT_MPPM(3,1,18)_SWENT_MPPM(3,1,19)_SWENT_MPPM(3,1,20)_SWENT_MPPM(3,1,21) + _SWENT_MPPM(3,1,22)_SWENT_MPPM(3,1,23)_SWENT_MPPM(3,1,24)_SWENT_MPPM(3,1,25)_SWENT_MPPM(3,1,26)_SWENT_MPPM(3,1,27) + _SWENT_MPPM(3,1,28)_SWENT_MPPM(3,1,29)_SWENT_MPPM(3,1,30)_SWENT_MPPM(3,1,31) + _SWENT_MPPM(4,2,00)_SWENT_MPPM(4,2,01)_SWENT_MPPM(4,2,02)_SWENT_MPPM(4,2,03)_SWENT_MPPM(4,2,04)_SWENT_MPPM(4,2,05) + _SWENT_MPPM(4,2,06)_SWENT_MPPM(4,2,07)_SWENT_MPPM(4,2,08)_SWENT_MPPM(4,2,09)_SWENT_MPPM(4,2,10)_SWENT_MPPM(4,2,11) + _SWENT_MPPM(4,2,12)_SWENT_MPPM(4,2,13) + _SWENT_MPPM(7,3,25)_SWENT_MPPM(7,3,26) + _SWENT_MPPM(9,4,28)_SWENT_MPPM(9,4,29) } + #undef _SWENT_MPPM + } - #define LPC_OSCRANGE_1_20_MHZ 0 - #define LPC_OSCRANGE_15_25_MHZ 1 + #if 0 + static void SetPortPinDirection(int pin, uint8_t dir) { + #define _SWENT_SPPD_(PT,PNN,PN) case P##PT##_##PNN: FIO##PT##DIR.set(PN, dir); break; + #define _SWENT_SPPD(PT,PN) case P##PT##_##PN: FIO##PT##DIR.set(PN, dir); break; + switch (pin) { + _SWENT_SPPD_(0,00,0)_SWENT_SPPD_(0,01,1)_SWENT_SPPD_(0,02,2)_SWENT_SPPD_(0,03,3)_SWENT_SPPD_(0,04,4)_SWENT_SPPD_(0,05,5)_SWENT_SPPD_(0,06,6) + _SWENT_SPPD_(0,07,7)_SWENT_SPPD_(0,08,8)_SWENT_SPPD_(0,09,9)_SWENT_SPPD(0,10)_SWENT_SPPD(0,11)_SWENT_SPPD(0,15)_SWENT_SPPD(0,16) + _SWENT_SPPD(0,17)_SWENT_SPPD(0,18)_SWENT_SPPD(0,19)_SWENT_SPPD(0,20)_SWENT_SPPD(0,21)_SWENT_SPPD(0,22)_SWENT_SPPD(0,23) + _SWENT_SPPD(0,24)_SWENT_SPPD(0,25)_SWENT_SPPD(0,26)_SWENT_SPPD(0,27)_SWENT_SPPD(0,28)_SWENT_SPPD(0,29)_SWENT_SPPD(0,30) + _SWENT_SPPD_(1,00,0)_SWENT_SPPD_(1,01,1)_SWENT_SPPD_(1,04,4)_SWENT_SPPD_(1,08,8)_SWENT_SPPD_(1,09,9)_SWENT_SPPD(1,10)_SWENT_SPPD(1,14) + _SWENT_SPPD(1,15)_SWENT_SPPD(1,16)_SWENT_SPPD(1,17)_SWENT_SPPD(1,18)_SWENT_SPPD(1,19)_SWENT_SPPD(1,20)_SWENT_SPPD(1,21) + _SWENT_SPPD(1,22)_SWENT_SPPD(1,23)_SWENT_SPPD(1,24)_SWENT_SPPD(1,25)_SWENT_SPPD(1,26)_SWENT_SPPD(1,27)_SWENT_SPPD(1,28) + _SWENT_SPPD(1,29)_SWENT_SPPD(1,30)_SWENT_SPPD(1,31) + _SWENT_SPPD_(2,00,0)_SWENT_SPPD_(2,01,1)_SWENT_SPPD_(2,02,2)_SWENT_SPPD_(2,03,3)_SWENT_SPPD_(2,04,4)_SWENT_SPPD_(2,05,5)_SWENT_SPPD_(2,06,6)_SWENT_SPPD_(2,07,7) + _SWENT_SPPD_(2,08,8)_SWENT_SPPD_(2,09,9)_SWENT_SPPD(2,10)_SWENT_SPPD(2,11)_SWENT_SPPD(2,12)_SWENT_SPPD(2,13) + _SWENT_SPPD(3,25)_SWENT_SPPD(3,26) + _SWENT_SPPD(4,28)_SWENT_SPPD(4,29) + } + #undef _SWENT_SPPD + #undef _SWENT_SPPD_ + } + #endif - struct scs_reg_t { - uint32_t reserved1 : 4; - uint32_t OSCRANGE : 1; - uint32_t OSCEN : 1; - uint32_t OSCSTAT : 1; - uint32_t reserved2 : 25; - }; - static_assert(sizeof(scs_reg_t) == 4, "invalid size of LPC scs_reg_t"); + static gpioMapResult_t SPIMapGPIO(int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { + // First try to find a direct mapping to SSP peripheral based on the given pin hints. + uint8_t sspBusIdx; + portMapResult_t map_sck, map_miso, map_mosi, map_cs; + + bool foundPortMap = SPIFindPortMapping(hint_sck, hint_miso, hint_mosi, hint_cs, sspBusIdx, map_sck, map_miso, map_mosi, map_cs); + + if (!foundPortMap) { + // Just select the default SSP config. + sspBusIdx = 0; + hint_sck = P0_15; + map_sck.func = 2; + hint_miso = P0_17; + map_miso.func = 2; + hint_mosi = P0_18; + map_mosi.func = 2; + hint_cs = P0_16; + map_cs.func = 2; + } - __LPC_DEFREG(scs_reg_t, SCS, 0x400FC1A0); + // Map the functions that exist. + if (map_sck.isMapped()) { + MapPortPinFunc(hint_sck, map_sck.func); + SetPortPinMode(hint_sck, LPC_PINMODE_NONE); + } + if (map_miso.isMapped()) { + MapPortPinFunc(hint_miso, map_miso.func); + SetPortPinMode(hint_miso, LPC_PINMODE_PULLDOWN); + } + if (map_mosi.isMapped()) { + MapPortPinFunc(hint_mosi, map_mosi.func); + SetPortPinMode(hint_mosi, LPC_PINMODE_NONE); + } + #if 0 + if (map_cs.isMapped()) { + MapPortPinFunc(hint_cs, map_cs.func); + SetPortPinMode(hint_cs, LPC_PINMODE_NONE); + } + #endif - #define LPC_CLKSRC_IRC 0 // 4MHz - #define LPC_CLKSRC_MAINOSC 1 // depending on OSCRANGE - #define LPC_CLKSRC_RTCOSC 2 // 32kHz + gpioMapResult_t res; + res.sspBusIdx = sspBusIdx; + res.gpio_sck = ( map_sck.isMapped() ? hint_sck : -1 ); + res.gpio_miso = ( map_miso.isMapped() ? hint_miso : -1 ); + res.gpio_mosi = ( map_mosi.isMapped() ? hint_mosi : -1 ); + res.gpio_cs = ( map_cs.isMapped() ? hint_cs : -1 ); + return res; + } - struct clksrcsel_reg_t { - uint32_t CLKSRC : 2; - uint32_t reserved1 : 30; - }; - static_assert(sizeof(clksrcsel_reg_t) == 4, "invalid size of LPC clksrcsel_reg_t"); - - __LPC_DEFREG(clksrcsel_reg_t, CLKSRCSEL, 0x400FC10C); - - struct pll0stat_reg_t { - uint32_t MSEL0 : 15; // M - 1 - uint32_t reserved1 : 1; - uint32_t NSEL0 : 8; // N - 1 - uint32_t PLLE0_STAT : 1; // enable bit - uint32_t PLLC0_STAT : 1; // connect bit - uint32_t PLOCK0 : 1; // ready bit - uint32_t reserved2 : 5; - }; - static_assert(sizeof(pll0stat_reg_t) == 4, "invalid size of LPC pll0stat_reg_t"); + static void SPIUnmapGPIO(const gpioMapResult_t &res) { + // Reset to architecture default configs on the pins that we previously mapped. + if (res.gpio_sck >= 0) { + MapPortPinFunc(res.gpio_sck, 0); + SetPortPinMode(res.gpio_sck, LPC_PINMODE_PULLDOWN); + } + if (res.gpio_miso >= 0) { + MapPortPinFunc(res.gpio_miso, 0); + SetPortPinMode(res.gpio_miso, LPC_PINMODE_PULLDOWN); + } + if (res.gpio_mosi >= 0) { + MapPortPinFunc(res.gpio_mosi, 0); + SetPortPinMode(res.gpio_mosi, LPC_PINMODE_PULLDOWN); + } + #if 0 + if (res.gpio_cs >= 0) { + MapPortPinFunc(res.gpio_cs, 0); + SetPortPinMode(res.gpio_cs, LPC_PINMODE_PULLDOWN); + } + #endif + } - __LPC_DEFREG(pll0stat_reg_t, PLL0STAT, 0x400FC088); + #define LPC_OSCRANGE_1_20_MHZ 0 + #define LPC_OSCRANGE_15_25_MHZ 1 - struct cclkcfg_reg_t { - uint32_t CCLKSEL : 8; - uint32_t reserved1 : 24; - }; - static_assert(sizeof(cclkcfg_reg_t) == 4, "invalid size of LPC cclkcfg_reg_t"); + struct scs_reg_t { + uint32_t reserved1 : 4; + uint32_t OSCRANGE : 1; + uint32_t OSCEN : 1; + uint32_t OSCSTAT : 1; + uint32_t reserved2 : 25; + }; + static_assert(sizeof(scs_reg_t) == 4, "invalid size of LPC scs_reg_t"); - __LPC_DEFREG(cclkcfg_reg_t, CCLKCFG, 0x400FC104); + __LPC_DEFREG(scs_reg_t, SCS, 0x400FC1A0); - #define LPC_PCLKSEL_QUARTER 0 - #define LPC_PCLKSEL_ONE 1 - #define LPC_PCLKSEL_HALF 2 - #define LPC_PCLKSEL_8_6 3 // 1/8 for generic, 1/6 for CAN1/2 + #define LPC_CLKSRC_IRC 0 // 4MHz + #define LPC_CLKSRC_MAINOSC 1 // depending on OSCRANGE + #define LPC_CLKSRC_RTCOSC 2 // 32kHz - struct pclksel0_reg_t { - uint32_t PCLK_WDT : 2; - uint32_t PCLK_TIMER0 : 2; - uint32_t PCLK_TIMER1 : 2; - uint32_t PCLK_UART0 : 2; - uint32_t PCLK_UART1 : 2; - uint32_t reserved1 : 2; - uint32_t PCLK_PWM1 : 2; - uint32_t PCLK_I2C0 : 2; - uint32_t PCLK_SPI : 2; - uint32_t reserved2 : 2; - uint32_t PCLK_SSP1 : 2; - uint32_t PCLK_DAC : 2; - uint32_t PCLK_ADC : 2; - uint32_t PCLK_CAN1 : 2; - uint32_t PCLK_CAN2 : 2; - uint32_t PCLK_ACF : 2; - }; - static_assert(sizeof(pclksel0_reg_t) == 4, "invalid size of LPC pclksel0_reg_t"); + struct clksrcsel_reg_t { + uint32_t CLKSRC : 2; + uint32_t reserved1 : 30; + }; + static_assert(sizeof(clksrcsel_reg_t) == 4, "invalid size of LPC clksrcsel_reg_t"); + + __LPC_DEFREG(clksrcsel_reg_t, CLKSRCSEL, 0x400FC10C); + + struct pll0stat_reg_t { + uint32_t MSEL0 : 15; // M - 1 + uint32_t reserved1 : 1; + uint32_t NSEL0 : 8; // N - 1 + uint32_t PLLE0_STAT : 1; // enable bit + uint32_t PLLC0_STAT : 1; // connect bit + uint32_t PLOCK0 : 1; // ready bit + uint32_t reserved2 : 5; + }; + static_assert(sizeof(pll0stat_reg_t) == 4, "invalid size of LPC pll0stat_reg_t"); - __LPC_DEFREG(pclksel0_reg_t, PCLKSEL0, 0x400FC1A8); + __LPC_DEFREG(pll0stat_reg_t, PLL0STAT, 0x400FC088); - struct pclksel1_reg_t { - uint32_t PCLK_QEI : 2; - uint32_t PCLK_GPIOINT : 2; - uint32_t PCLK_PCB : 2; - uint32_t PCLK_I2C1 : 2; - uint32_t reserved1 : 2; - uint32_t PCLK_SSP0 : 2; - uint32_t PCLK_TIMER2 : 2; - uint32_t PCLK_TIMER3 : 2; - uint32_t PCLK_UART2 : 2; - uint32_t PCLK_UART3 : 2; - uint32_t PCLK_I2C2 : 2; - uint32_t PCLK_I2S : 2; - uint32_t reserved2 : 2; - uint32_t PCLK_RIT : 2; - uint32_t PCLK_SYSCON : 2; - uint32_t PCLK_MC : 2; - }; - static_assert(sizeof(pclksel1_reg_t) == 4, "invalid size of LPC pclksel1_reg_t"); - - __LPC_DEFREG(pclksel1_reg_t, PCLKSEL1, 0x400FC1AC); - - // Enables or disables peripherals (power control for peripherals). - struct pconp_reg_t { - uint32_t reserved1 : 1; - uint32_t PCTIM0 : 1; - uint32_t PCTIM1 : 1; - uint32_t PCUART0 : 1; - uint32_t PCUART1 : 1; - uint32_t reserved2 : 1; - uint32_t PCPWM1 : 1; - uint32_t PCI2C0 : 1; - uint32_t PCSPI : 1; - uint32_t PCRTC : 1; - uint32_t PCSSP1 : 1; - uint32_t reserved3 : 1; - uint32_t PCADC : 1; - uint32_t PCCAN1 : 1; - uint32_t PCCAN2 : 1; - uint32_t PCGPIO : 1; - uint32_t PCRIT : 1; - uint32_t PCMCPWM : 1; - uint32_t PCQEI : 1; - uint32_t PCI2C1 : 1; - uint32_t reserved4 : 1; - uint32_t PCSSP0 : 1; - uint32_t PCTIM2 : 1; - uint32_t PCTIM3 : 1; - uint32_t PCUART2 : 1; - uint32_t PCUART3 : 1; - uint32_t PCI2C2 : 1; - uint32_t PC12S : 1; - uint32_t reserved5 : 1; - uint32_t PCGPDMA : 1; - uint32_t PCENET : 1; - uint32_t PCUSB : 1; - }; - static_assert(sizeof(pconp_reg_t) == 4, "invalid size of LPC pconp_reg_t"); + struct cclkcfg_reg_t { + uint32_t CCLKSEL : 8; + uint32_t reserved1 : 24; + }; + static_assert(sizeof(cclkcfg_reg_t) == 4, "invalid size of LPC cclkcfg_reg_t"); + + __LPC_DEFREG(cclkcfg_reg_t, CCLKCFG, 0x400FC104); + + #define LPC_PCLKSEL_QUARTER 0 + #define LPC_PCLKSEL_ONE 1 + #define LPC_PCLKSEL_HALF 2 + #define LPC_PCLKSEL_8_6 3 // 1/8 for generic, 1/6 for CAN1/2 + + struct pclksel0_reg_t { + uint32_t PCLK_WDT : 2; + uint32_t PCLK_TIMER0 : 2; + uint32_t PCLK_TIMER1 : 2; + uint32_t PCLK_UART0 : 2; + uint32_t PCLK_UART1 : 2; + uint32_t reserved1 : 2; + uint32_t PCLK_PWM1 : 2; + uint32_t PCLK_I2C0 : 2; + uint32_t PCLK_SPI : 2; + uint32_t reserved2 : 2; + uint32_t PCLK_SSP1 : 2; + uint32_t PCLK_DAC : 2; + uint32_t PCLK_ADC : 2; + uint32_t PCLK_CAN1 : 2; + uint32_t PCLK_CAN2 : 2; + uint32_t PCLK_ACF : 2; + }; + static_assert(sizeof(pclksel0_reg_t) == 4, "invalid size of LPC pclksel0_reg_t"); + + __LPC_DEFREG(pclksel0_reg_t, PCLKSEL0, 0x400FC1A8); + + struct pclksel1_reg_t { + uint32_t PCLK_QEI : 2; + uint32_t PCLK_GPIOINT : 2; + uint32_t PCLK_PCB : 2; + uint32_t PCLK_I2C1 : 2; + uint32_t reserved1 : 2; + uint32_t PCLK_SSP0 : 2; + uint32_t PCLK_TIMER2 : 2; + uint32_t PCLK_TIMER3 : 2; + uint32_t PCLK_UART2 : 2; + uint32_t PCLK_UART3 : 2; + uint32_t PCLK_I2C2 : 2; + uint32_t PCLK_I2S : 2; + uint32_t reserved2 : 2; + uint32_t PCLK_RIT : 2; + uint32_t PCLK_SYSCON : 2; + uint32_t PCLK_MC : 2; + }; + static_assert(sizeof(pclksel1_reg_t) == 4, "invalid size of LPC pclksel1_reg_t"); + + __LPC_DEFREG(pclksel1_reg_t, PCLKSEL1, 0x400FC1AC); + + // Enables or disables peripherals (power control for peripherals). + struct pconp_reg_t { + uint32_t reserved1 : 1; + uint32_t PCTIM0 : 1; + uint32_t PCTIM1 : 1; + uint32_t PCUART0 : 1; + uint32_t PCUART1 : 1; + uint32_t reserved2 : 1; + uint32_t PCPWM1 : 1; + uint32_t PCI2C0 : 1; + uint32_t PCSPI : 1; + uint32_t PCRTC : 1; + uint32_t PCSSP1 : 1; + uint32_t reserved3 : 1; + uint32_t PCADC : 1; + uint32_t PCCAN1 : 1; + uint32_t PCCAN2 : 1; + uint32_t PCGPIO : 1; + uint32_t PCRIT : 1; + uint32_t PCMCPWM : 1; + uint32_t PCQEI : 1; + uint32_t PCI2C1 : 1; + uint32_t reserved4 : 1; + uint32_t PCSSP0 : 1; + uint32_t PCTIM2 : 1; + uint32_t PCTIM3 : 1; + uint32_t PCUART2 : 1; + uint32_t PCUART3 : 1; + uint32_t PCI2C2 : 1; + uint32_t PC12S : 1; + uint32_t reserved5 : 1; + uint32_t PCGPDMA : 1; + uint32_t PCENET : 1; + uint32_t PCUSB : 1; + }; + static_assert(sizeof(pconp_reg_t) == 4, "invalid size of LPC pconp_reg_t"); - __LPC_DEFREG(pconp_reg_t, PCONP, 0x400FC0C4); + __LPC_DEFREG(pconp_reg_t, PCONP, 0x400FC0C4); - static uint32_t GetCPUClockFrequency() { - if (!PLL0STAT.PLLE0_STAT || !PLL0STAT.PLLC0_STAT) { - // The CPU is running on the IRC. - return 4000000; - } + static uint32_t GetCPUClockFrequency() { + if (!PLL0STAT.PLLE0_STAT || !PLL0STAT.PLLC0_STAT) { + // The CPU is running on the IRC. + return 4000000; + } - uint32_t clksrc = 0; + uint32_t clksrc = 0; - switch (CLKSRCSEL.CLKSRC) { - case LPC_CLKSRC_IRC: clksrc = 4000000; break; - case LPC_CLKSRC_MAINOSC: clksrc = LPC_MAINOSCILLATOR_FREQ; break; - case LPC_CLKSRC_RTCOSC: clksrc = 32000; break; - } + switch (CLKSRCSEL.CLKSRC) { + case LPC_CLKSRC_IRC: clksrc = 4000000; break; + case LPC_CLKSRC_MAINOSC: clksrc = LPC_MAINOSCILLATOR_FREQ; break; + case LPC_CLKSRC_RTCOSC: clksrc = 32000; break; + } - uint32_t M = PLL0STAT.MSEL0 + 1; // M = 25 - uint32_t N = PLL0STAT.NSEL0 + 1; // N = 2 + uint32_t M = PLL0STAT.MSEL0 + 1; // M = 25 + uint32_t N = PLL0STAT.NSEL0 + 1; // N = 2 - uint32_t f_cco = (2 * M * clksrc) / N; + uint32_t f_cco = (2 * M * clksrc) / N; - uint32_t cclkdiv = CCLKCFG.CCLKSEL + 1; + uint32_t cclkdiv = CCLKCFG.CCLKSEL + 1; - return (f_cco / cclkdiv); - } + return (f_cco / cclkdiv); + } - struct sspClockResult_t { - uint32_t pclk_ssp : 2; - uint32_t scr : 8; - uint32_t cpsdvsr : 8; // value between 2 and 254 - }; + struct sspClockResult_t { + uint32_t pclk_ssp : 2; + uint32_t scr : 8; + uint32_t cpsdvsr : 8; // value between 2 and 254 + }; - static sspClockResult_t SPICalculateClock(uint32_t maxClockFreq) { - uint32_t cpuFreq = GetCPUClockFrequency(); + static sspClockResult_t SPICalculateClock(uint32_t maxClockFreq) { + uint32_t cpuFreq = GetCPUClockFrequency(); - if (maxClockFreq >= cpuFreq) { - // Return the fastest clock. - sspClockResult_t maxRes; - maxRes.pclk_ssp = LPC_PCLKSEL_ONE; - maxRes.scr = 0; - maxRes.cpsdvsr = 2; // minimum value. - return maxRes; - } + if (maxClockFreq >= cpuFreq) { + // Return the fastest clock. + sspClockResult_t maxRes; + maxRes.pclk_ssp = LPC_PCLKSEL_ONE; + maxRes.scr = 0; + maxRes.cpsdvsr = 2; // minimum value. + return maxRes; + } - uint32_t DIV_ceil = ((cpuFreq + (maxClockFreq - 1)) / maxClockFreq); + uint32_t DIV_ceil = ((cpuFreq + (maxClockFreq - 1)) / maxClockFreq); - if (/* DIV_ceil >= 1 && */ DIV_ceil <= 256) { - uint32_t rem_two = (DIV_ceil % 2); + if (/* DIV_ceil >= 1 && */ DIV_ceil <= 256) { + uint32_t rem_two = (DIV_ceil % 2); - if (rem_two == 0 && DIV_ceil >= 2 && DIV_ceil <= 254) { - sspClockResult_t accRes; - accRes.pclk_ssp = LPC_PCLKSEL_ONE; - accRes.scr = 0; - accRes.cpsdvsr = DIV_ceil; - return accRes; - } - else { - // Return a very accurate SCR representation. - sspClockResult_t accRes; - accRes.pclk_ssp = LPC_PCLKSEL_ONE; - accRes.scr = (DIV_ceil+rem_two)/2 - 1; - accRes.cpsdvsr = 2; // minimum value. - return accRes; - } + if (rem_two == 0 && DIV_ceil >= 2 && DIV_ceil <= 254) { + sspClockResult_t accRes; + accRes.pclk_ssp = LPC_PCLKSEL_ONE; + accRes.scr = 0; + accRes.cpsdvsr = DIV_ceil; + return accRes; } + else { + // Return a very accurate SCR representation. + sspClockResult_t accRes; + accRes.pclk_ssp = LPC_PCLKSEL_ONE; + accRes.scr = (DIV_ceil+rem_two)/2 - 1; + accRes.cpsdvsr = 2; // minimum value. + return accRes; + } + } - // Brute-force find the clock result. - // Still very fast, optimized using math. - sspClockResult_t best; - best.pclk_ssp = LPC_PCLKSEL_8_6; - best.scr = 255; - best.cpsdvsr = 254; - uint32_t last_best_clockfreq = 0; - bool has_result = false; - - uint32_t ps_ssp = 2; - - while (ps_ssp <= 8) { - uint32_t ps_dvsr = (1<<7)*ps_ssp; - - while (ps_dvsr <= (254u*ps_ssp)) { - uint32_t presc = (ps_dvsr*ps_ssp); - uint32_t scr = (DIV_ceil/presc); - uint32_t freq = (cpuFreq/(presc*scr)); - - if (freq <= maxClockFreq) { - if (!has_result || last_best_clockfreq < freq) { - last_best_clockfreq = freq; - if (ps_ssp == 2) - best.pclk_ssp = LPC_PCLKSEL_HALF; - else if (ps_ssp == 4) - best.pclk_ssp = LPC_PCLKSEL_QUARTER; - else - best.pclk_ssp = LPC_PCLKSEL_8_6; - best.scr = (scr-1); - best.cpsdvsr = ps_dvsr; - has_result = true; - } + // Brute-force find the clock result. + // Still very fast, optimized using math. + sspClockResult_t best; + best.pclk_ssp = LPC_PCLKSEL_8_6; + best.scr = 255; + best.cpsdvsr = 254; + uint32_t last_best_clockfreq = 0; + bool has_result = false; + + uint32_t ps_ssp = 2; + + while (ps_ssp <= 8) { + uint32_t ps_dvsr = (1<<7)*ps_ssp; + + while (ps_dvsr <= (254u*ps_ssp)) { + uint32_t presc = (ps_dvsr*ps_ssp); + uint32_t scr = (DIV_ceil/presc); + uint32_t freq = (cpuFreq/(presc*scr)); + + if (freq <= maxClockFreq) { + if (!has_result || last_best_clockfreq < freq) { + last_best_clockfreq = freq; + if (ps_ssp == 2) + best.pclk_ssp = LPC_PCLKSEL_HALF; + else if (ps_ssp == 4) + best.pclk_ssp = LPC_PCLKSEL_QUARTER; + else + best.pclk_ssp = LPC_PCLKSEL_8_6; + best.scr = (scr-1); + best.cpsdvsr = ps_dvsr; + has_result = true; } - - ps_dvsr += ps_ssp*2; } - ps_ssp *= 2; + ps_dvsr += ps_ssp*2; } - return best; + ps_ssp *= 2; } - struct sspNcr0_reg_t { - uint32_t DSS : 4; - uint32_t FRF : 2; - uint32_t CPOL : 1; - uint32_t CPHA : 1; - uint32_t SCR : 8; - uint32_t reserved1 : 16; - }; - static_assert(sizeof(sspNcr0_reg_t) == 4, "invalid size of LPC sspNcr0_reg_t"); - - struct sspNcr1_reg_t { - uint32_t LBM : 1; - uint32_t SSE : 1; - uint32_t MS : 1; - uint32_t SOD : 1; - uint32_t reserved1 : 28; - }; - static_assert(sizeof(sspNcr1_reg_t) == 4, "invalid size of LPC sspNcr1_reg_t"); + return best; + } - struct sspNdr_reg_t { - uint32_t DATA : 16; - uint32_t reserved1 : 16; - }; - static_assert(sizeof(sspNdr_reg_t) == 4, "invalid size of LPC sspNdr_reg_t"); - - struct sspNsr_reg_t { - uint32_t TFE : 1; - uint32_t TNF : 1; - uint32_t RNE : 1; - uint32_t RFF : 1; - uint32_t BSY : 1; - uint32_t reserved1 : 27; - }; - static_assert(sizeof(sspNsr_reg_t) == 4, "invalid size of LPC sspNsr_reg_t"); + struct sspNcr0_reg_t { + uint32_t DSS : 4; + uint32_t FRF : 2; + uint32_t CPOL : 1; + uint32_t CPHA : 1; + uint32_t SCR : 8; + uint32_t reserved1 : 16; + }; + static_assert(sizeof(sspNcr0_reg_t) == 4, "invalid size of LPC sspNcr0_reg_t"); + + struct sspNcr1_reg_t { + uint32_t LBM : 1; + uint32_t SSE : 1; + uint32_t MS : 1; + uint32_t SOD : 1; + uint32_t reserved1 : 28; + }; + static_assert(sizeof(sspNcr1_reg_t) == 4, "invalid size of LPC sspNcr1_reg_t"); + + struct sspNdr_reg_t { + uint32_t DATA : 16; + uint32_t reserved1 : 16; + }; + static_assert(sizeof(sspNdr_reg_t) == 4, "invalid size of LPC sspNdr_reg_t"); + + struct sspNsr_reg_t { + uint32_t TFE : 1; + uint32_t TNF : 1; + uint32_t RNE : 1; + uint32_t RFF : 1; + uint32_t BSY : 1; + uint32_t reserved1 : 27; + }; + static_assert(sizeof(sspNsr_reg_t) == 4, "invalid size of LPC sspNsr_reg_t"); + + struct sspNcpsr_reg_t { + uint32_t CPSDVSR : 8; + uint32_t reserved1 : 24; + }; + static_assert(sizeof(sspNcpsr_reg_t) == 4, "invalid size of LPC sspNcpsr_reg_t"); + + struct sspNimsc_reg_t { + uint32_t RORIM : 1; + uint32_t RTIM : 1; + uint32_t RXIM : 1; + uint32_t TXIM : 1; + uint32_t reserved1 : 28; + }; + static_assert(sizeof(sspNimsc_reg_t) == 4, "invalid size of LPC sspNimsc_reg_t"); + + struct sspNris_reg_t { + uint32_t RORRIS : 1; + uint32_t RTRIS : 1; + uint32_t RXRIS : 1; + uint32_t TXRIS : 1; + uint32_t reserved1 : 28; + }; + static_assert(sizeof(sspNris_reg_t) == 4, "invalid size of LPC sspNris_reg_t"); + + struct sspNmis_reg_t { + uint32_t RORMIS : 1; + uint32_t RTMIS : 1; + uint32_t RXMIS : 1; + uint32_t TXMIS : 1; + uint32_t reserved1 : 28; + }; + static_assert(sizeof(sspNmis_reg_t) == 4, "invalid size of LPC sspNmis_reg_t"); + + struct sspNicr_reg_t { + uint32_t RORIC : 1; + uint32_t RTIC : 1; + uint32_t reserved1 : 30; + }; + static_assert(sizeof(sspNicr_reg_t) == 4, "invalid size of LPC sspNicr_reg_t"); + + struct sspNdmacr_reg_t { + uint32_t RXDMAE : 1; + uint32_t TXDMAE : 1; + uint32_t reserved1 : 30; + }; + static_assert(sizeof(sspNdmacr_reg_t) == 4, "invalid size of LPC sspNdmacr_reg_t"); + + struct ssp_dev_t { + sspNcr0_reg_t CR0; + sspNcr1_reg_t CR1; + sspNdr_reg_t DR; + sspNsr_reg_t SR; + sspNcpsr_reg_t CPSR; + sspNimsc_reg_t IMSC; + sspNris_reg_t RIS; + sspNmis_reg_t MIS; + sspNicr_reg_t ICR; + sspNdmacr_reg_t DMACR; + }; + static_assert(sizeof(ssp_dev_t) == 40, "invalid size of LPC ssp_dev_t"); + + __LPC_DEFREG(ssp_dev_t, SSP0, 0x40088000); + __LPC_DEFREG(ssp_dev_t, SSP1, 0x40030000); + + inline volatile ssp_dev_t &SPIGetBusFromIndex(uint8_t idx) { + if (idx == 0) return SSP0; + if (idx == 1) return SSP1; + return SSP0; // default + } - struct sspNcpsr_reg_t { - uint32_t CPSDVSR : 8; + inline uint8_t SPIGetBusIndex(volatile ssp_dev_t &SSP) { + if (&SSP == &SSP0) return 0; + if (&SSP == &SSP1) return 1; + return 0; // default + } + + #ifndef HALSPI_DISABLE_DMA + + struct DMACIntStat_reg_t { + uint32_t IntStat : 8; uint32_t reserved1 : 24; }; - static_assert(sizeof(sspNcpsr_reg_t) == 4, "invalid size of LPC sspNcpsr_reg_t"); - - struct sspNimsc_reg_t { - uint32_t RORIM : 1; - uint32_t RTIM : 1; - uint32_t RXIM : 1; - uint32_t TXIM : 1; - uint32_t reserved1 : 28; - }; - static_assert(sizeof(sspNimsc_reg_t) == 4, "invalid size of LPC sspNimsc_reg_t"); - - struct sspNris_reg_t { - uint32_t RORRIS : 1; - uint32_t RTRIS : 1; - uint32_t RXRIS : 1; - uint32_t TXRIS : 1; - uint32_t reserved1 : 28; - }; - static_assert(sizeof(sspNris_reg_t) == 4, "invalid size of LPC sspNris_reg_t"); - - struct sspNmis_reg_t { - uint32_t RORMIS : 1; - uint32_t RTMIS : 1; - uint32_t RXMIS : 1; - uint32_t TXMIS : 1; - uint32_t reserved1 : 28; + static_assert(sizeof(DMACIntStat_reg_t) == 4, "invalid size of LPC DMACIntStat_reg_t"); + + __LPC_DEFREG(DMACIntStat_reg_t, DMACIntStat, 0x50004000); + + struct DMACIntTCStat_reg_t { + uint32_t IntTCStat : 8; + uint32_t reserved1 : 24; }; - static_assert(sizeof(sspNmis_reg_t) == 4, "invalid size of LPC sspNmis_reg_t"); + static_assert(sizeof(DMACIntTCStat_reg_t) == 4, "invalid size of LPC DMACIntTCStat_reg_t"); - struct sspNicr_reg_t { - uint32_t RORIC : 1; - uint32_t RTIC : 1; - uint32_t reserved1 : 30; + __LPC_DEFREG(DMACIntTCStat_reg_t, DMACIntTCStat, 0x50004004); + + struct DMACIntTCClear_reg_t { + uint32_t IntTCClear : 8; + uint32_t reserved1 : 24; }; - static_assert(sizeof(sspNicr_reg_t) == 4, "invalid size of LPC sspNicr_reg_t"); + static_assert(sizeof(DMACIntTCClear_reg_t) == 4, "invalid size of LPC DMACIntTCClear_reg_t"); - struct sspNdmacr_reg_t { - uint32_t RXDMAE : 1; - uint32_t TXDMAE : 1; - uint32_t reserved1 : 30; + __LPC_DEFREG(DMACIntTCClear_reg_t, DMACIntTCClear, 0x50004008); + + struct DMACIntErrStat_reg_t { + uint32_t IntErrStat : 8; + uint32_t reserved1 : 24; }; - static_assert(sizeof(sspNdmacr_reg_t) == 4, "invalid size of LPC sspNdmacr_reg_t"); - - struct ssp_dev_t { - sspNcr0_reg_t CR0; - sspNcr1_reg_t CR1; - sspNdr_reg_t DR; - sspNsr_reg_t SR; - sspNcpsr_reg_t CPSR; - sspNimsc_reg_t IMSC; - sspNris_reg_t RIS; - sspNmis_reg_t MIS; - sspNicr_reg_t ICR; - sspNdmacr_reg_t DMACR; + static_assert(sizeof(DMACIntErrStat_reg_t) == 4, "invalid size of LPC DMACIntErrStat_reg_t"); + + __LPC_DEFREG(DMACIntErrStat_reg_t, DMACIntErrStat, 0x5000400C); + + struct DMACIntErrClr_reg_t { + uint32_t IntErrClr : 8; + uint32_t reserved1 : 24; }; - static_assert(sizeof(ssp_dev_t) == 40, "invalid size of LPC ssp_dev_t"); + static_assert(sizeof(DMACIntErrClr_reg_t) == 4, "invalid size of LPC DMACIntErrClr_reg_t"); - __LPC_DEFREG(ssp_dev_t, SSP0, 0x40088000); - __LPC_DEFREG(ssp_dev_t, SSP1, 0x40030000); + __LPC_DEFREG(DMACIntErrClr_reg_t, DMACIntErrClr, 0x50004010); - inline volatile ssp_dev_t &SPIGetBusFromIndex(uint8_t idx) { - if (idx == 0) return SSP0; - if (idx == 1) return SSP1; - return SSP0; // default - } + struct DMACRawIntTCStat_reg_t { + uint32_t RawIntTCStat : 8; + uint32_t reserved1 : 24; + }; + static_assert(sizeof(DMACRawIntTCStat_reg_t) == 4, "invalid size of LPC DMACRawIntTCStat_reg_t"); - inline uint8_t SPIGetBusIndex(volatile ssp_dev_t &SSP) { - if (&SSP == &SSP0) return 0; - if (&SSP == &SSP1) return 1; - return 0; // default - } + __LPC_DEFREG(DMACRawIntTCStat_reg_t, DMACRawIntTCStat, 0x50004014); - #ifndef HALSPI_DISABLE_DMA + struct DMACRawIntErrStat_reg_t { + uint32_t RawIntErrStat : 8; + uint32_t reserved1 : 24; + }; + static_assert(sizeof(DMACRawIntErrStat_reg_t) == 4, "invalid size of LPC DMACRawIntErrStat_reg_t"); - struct DMACIntStat_reg_t { - uint32_t IntStat : 8; - uint32_t reserved1 : 24; - }; - static_assert(sizeof(DMACIntStat_reg_t) == 4, "invalid size of LPC DMACIntStat_reg_t"); + __LPC_DEFREG(DMACRawIntErrStat_reg_t, DMACRawIntErrStat, 0x50004018); - __LPC_DEFREG(DMACIntStat_reg_t, DMACIntStat, 0x50004000); + struct DMACEnbldChns_reg_t { + uint32_t EnabledChannels : 8; + uint32_t reserved1 : 24; + }; + static_assert(sizeof(DMACEnbldChns_reg_t) == 4, "invalid size of LPC DMACEnbldChns_reg_t"); - struct DMACIntTCStat_reg_t { - uint32_t IntTCStat : 8; - uint32_t reserved1 : 24; - }; - static_assert(sizeof(DMACIntTCStat_reg_t) == 4, "invalid size of LPC DMACIntTCStat_reg_t"); + __LPC_DEFREG(DMACEnbldChns_reg_t, DMACEnbldChns, 0x5000401C); - __LPC_DEFREG(DMACIntTCStat_reg_t, DMACIntTCStat, 0x50004004); + struct DMACSoftBReq_reg_t { + uint32_t SoftBReq : 16; + uint32_t reserved1 : 16; + }; + static_assert(sizeof(DMACSoftBReq_reg_t) == 4, "invalid size of LPC DMACSoftBReq_reg_t"); - struct DMACIntTCClear_reg_t { - uint32_t IntTCClear : 8; - uint32_t reserved1 : 24; - }; - static_assert(sizeof(DMACIntTCClear_reg_t) == 4, "invalid size of LPC DMACIntTCClear_reg_t"); + __LPC_DEFREG(DMACSoftBReq_reg_t, DMACSoftBReq, 0x50004020); - __LPC_DEFREG(DMACIntTCClear_reg_t, DMACIntTCClear, 0x50004008); + struct DMACSoftSReq_reg_t { + uint32_t SoftSReq : 16; + uint32_t reserved1 : 16; + }; + static_assert(sizeof(DMACSoftSReq_reg_t) == 4, "invalid size of LPC DMACSoftSReq_reg_t"); - struct DMACIntErrStat_reg_t { - uint32_t IntErrStat : 8; - uint32_t reserved1 : 24; - }; - static_assert(sizeof(DMACIntErrStat_reg_t) == 4, "invalid size of LPC DMACIntErrStat_reg_t"); + __LPC_DEFREG(DMACSoftSReq_reg_t, DMACSoftSReq, 0x50004024); - __LPC_DEFREG(DMACIntErrStat_reg_t, DMACIntErrStat, 0x5000400C); + struct DMACSoftLBReq_reg_t { + uint32_t SoftLBReq : 16; + uint32_t reserved1 : 16; + }; + static_assert(sizeof(DMACSoftLBReq_reg_t) == 4, "invalid size of LPC DMACSoftLBReq_reg_t"); - struct DMACIntErrClr_reg_t { - uint32_t IntErrClr : 8; - uint32_t reserved1 : 24; - }; - static_assert(sizeof(DMACIntErrClr_reg_t) == 4, "invalid size of LPC DMACIntErrClr_reg_t"); + __LPC_DEFREG(DMACSoftLBReq_reg_t, DMACSoftLBReq, 0x50004028); - __LPC_DEFREG(DMACIntErrClr_reg_t, DMACIntErrClr, 0x50004010); + struct DMACSoftLSReq_reg_t { + uint32_t SoftLSReq : 16; + uint32_t reserved1 : 16; + }; + static_assert(sizeof(DMACSoftLSReq_reg_t) == 4, "invalid size of LPC DMACSoftLSReq_reg_t"); - struct DMACRawIntTCStat_reg_t { - uint32_t RawIntTCStat : 8; - uint32_t reserved1 : 24; - }; - static_assert(sizeof(DMACRawIntTCStat_reg_t) == 4, "invalid size of LPC DMACRawIntTCStat_reg_t"); + __LPC_DEFREG(DMACSoftLSReq_reg_t, DMACSoftLSReq, 0x5000402C); - __LPC_DEFREG(DMACRawIntTCStat_reg_t, DMACRawIntTCStat, 0x50004014); + struct DMACConfig_reg_t { + uint32_t E : 1; + uint32_t M : 1; + uint32_t reserved1 : 30; + }; + static_assert(sizeof(DMACConfig_reg_t) == 4, "invalid size of LPC DMACConfig_reg_t"); - struct DMACRawIntErrStat_reg_t { - uint32_t RawIntErrStat : 8; - uint32_t reserved1 : 24; - }; - static_assert(sizeof(DMACRawIntErrStat_reg_t) == 4, "invalid size of LPC DMACRawIntErrStat_reg_t"); + __LPC_DEFREG(DMACConfig_reg_t, DMACConfig, 0x50004030); - __LPC_DEFREG(DMACRawIntErrStat_reg_t, DMACRawIntErrStat, 0x50004018); + struct DMACSync_reg_t { + uint32_t DMACSync : 16; + uint32_t reserved1 : 16; + }; + static_assert(sizeof(DMACSync_reg_t) == 4, "invalid size of LPC DMACSync_reg_t"); + + __LPC_DEFREG(DMACSync_reg_t, DMACSync, 0x50004034); + + struct DMAReqSel_reg_t { + uint32_t DMASEL08 : 1; + uint32_t DMASEL09 : 1; + uint32_t DMASEL10 : 1; + uint32_t DMASEL11 : 1; + uint32_t DMASEL12 : 1; + uint32_t DMASEL13 : 1; + uint32_t DMASEL14 : 1; + uint32_t DMASEL15 : 1; + uint32_t reserved : 24; + }; + static_assert(sizeof(DMAReqSel_reg_t) == 4, "invalid size of LPC DMAReqSel_reg_t"); - struct DMACEnbldChns_reg_t { - uint32_t EnabledChannels : 8; - uint32_t reserved1 : 24; - }; - static_assert(sizeof(DMACEnbldChns_reg_t) == 4, "invalid size of LPC DMACEnbldChns_reg_t"); + __LPC_DEFREG(DMAReqSel_reg_t, DMAReqSel, 0x400FC1C4); - __LPC_DEFREG(DMACEnbldChns_reg_t, DMACEnbldChns, 0x5000401C); + struct DMACCxLLI_reg_t { + uint32_t reserved1 : 2; + uint32_t LLI : 30; + }; + static_assert(sizeof(DMACCxLLI_reg_t) == 4, "invalid size of LPC DMACCxLLI_reg_t"); + + struct DMACCxControl_reg_t { + uint32_t TransferSize : 12; + uint32_t SBSize : 3; + uint32_t DBSize : 3; + uint32_t SWidth : 3; + uint32_t DWidth : 3; + uint32_t reserved1 : 2; + uint32_t SI : 1; + uint32_t DI : 1; + uint32_t Prot1 : 1; + uint32_t Prot2 : 1; + uint32_t Prot3 : 1; + uint32_t I : 1; + }; + static_assert(sizeof(DMACCxControl_reg_t) == 4, "invalid size of LPC DMACCxControl_reg_t"); + + struct DMACCxConfig_reg_t { + uint32_t E : 1; + uint32_t SrcPeripheral : 5; + uint32_t DestPeripheral : 5; + uint32_t TransferType : 3; + uint32_t IE : 1; + uint32_t ITC : 1; + uint32_t L : 1; + uint32_t A : 1; + uint32_t H : 1; + uint32_t reserved1 : 13; + }; + static_assert(sizeof(DMACCxConfig_reg_t) == 4, "invalid size of LPC DMACCxConfig_reg_t"); + + struct DMACChannel_dev_t { + uint32_t SrcAddr; + uint32_t DestAddr; + DMACCxLLI_reg_t LLI; + DMACCxControl_reg_t Control; + DMACCxConfig_reg_t Config; + }; + static_assert(sizeof(DMACChannel_dev_t) == 20, "invalid size of LPC DMACChannel_dev_t"); + + __LPC_DEFREG(DMACChannel_dev_t, DMACC0, 0x50004100); + __LPC_DEFREG(DMACChannel_dev_t, DMACC1, 0x50004120); + __LPC_DEFREG(DMACChannel_dev_t, DMACC2, 0x50004140); + __LPC_DEFREG(DMACChannel_dev_t, DMACC3, 0x50004160); + __LPC_DEFREG(DMACChannel_dev_t, DMACC4, 0x50004180); + __LPC_DEFREG(DMACChannel_dev_t, DMACC5, 0x500041A0); + __LPC_DEFREG(DMACChannel_dev_t, DMACC6, 0x500041C0); + __LPC_DEFREG(DMACChannel_dev_t, DMACC7, 0x500041E0); + + static volatile DMACChannel_dev_t& DMAGetChannel(const uint32_t idx) { + switch (idx) { + case 0: return DMACC0; + case 1: return DMACC1; + case 2: return DMACC2; + case 3: return DMACC3; + case 4: return DMACC4; + case 5: return DMACC5; + case 6: return DMACC6; + case 7: return DMACC7; + } + return DMACC0; // default. + } - struct DMACSoftBReq_reg_t { - uint32_t SoftBReq : 16; - uint32_t reserved1 : 16; - }; - static_assert(sizeof(DMACSoftBReq_reg_t) == 4, "invalid size of LPC DMACSoftBReq_reg_t"); + static uint32_t __attribute__((unused)) DMAGetChannelIndex(DMACChannel_dev_t &DMACC) { + if (&DMACC == &DMACC0) return 0; + if (&DMACC == &DMACC1) return 1; + if (&DMACC == &DMACC2) return 2; + if (&DMACC == &DMACC3) return 3; + if (&DMACC == &DMACC4) return 4; + if (&DMACC == &DMACC5) return 5; + if (&DMACC == &DMACC6) return 6; + if (&DMACC == &DMACC7) return 7; + return 0; // default. + } - __LPC_DEFREG(DMACSoftBReq_reg_t, DMACSoftBReq, 0x50004020); + #ifdef HAL_SPI_SUPPORTS_ASYNC - struct DMACSoftSReq_reg_t { - uint32_t SoftSReq : 16; - uint32_t reserved1 : 16; + struct DMACCxLLI_desc_t { + uint32_t SrcAddr; + uint32_t DestAddr; + volatile DMACCxLLI_desc_t *Next; + DMACCxControl_reg_t Control; }; - static_assert(sizeof(DMACSoftSReq_reg_t) == 4, "invalid size of LPC DMACSoftSReq_reg_t"); - - __LPC_DEFREG(DMACSoftSReq_reg_t, DMACSoftSReq, 0x50004024); + static_assert(sizeof(DMACCxLLI_desc_t) == 16, "invalid size of LPC DMACCxLLI_desc_t"); - struct DMACSoftLBReq_reg_t { - uint32_t SoftLBReq : 16; - uint32_t reserved1 : 16; + struct DMACCxLLI_desc_user_t : public DMACCxLLI_desc_t { + // User data by software. + bool available = true; }; - static_assert(sizeof(DMACSoftLBReq_reg_t) == 4, "invalid size of LPC DMACSoftLBReq_reg_t"); - __LPC_DEFREG(DMACSoftLBReq_reg_t, DMACSoftLBReq, 0x50004028); + #ifndef HALSPI_LPC_STATIC_DMADESCS + #define HALSPI_LPC_STATIC_DMADESCS 3 + #endif - struct DMACSoftLSReq_reg_t { - uint32_t SoftLSReq : 16; - uint32_t reserved1 : 16; - }; - static_assert(sizeof(DMACSoftLSReq_reg_t) == 4, "invalid size of LPC DMACSoftLSReq_reg_t"); + static volatile DMACCxLLI_desc_user_t _available_dma_descs[HALSPI_LPC_STATIC_DMADESCS]; - __LPC_DEFREG(DMACSoftLSReq_reg_t, DMACSoftLSReq, 0x5000402C); + static volatile DMACCxLLI_desc_user_t* DMAFindFreeChainLLI() { + for (auto &item : _available_dma_descs) + if (item.available) return &item; + return nullptr; + } - struct DMACConfig_reg_t { - uint32_t E : 1; - uint32_t M : 1; - uint32_t reserved1 : 30; + struct dma_process_t { + volatile DMACChannel_dev_t *current_DMACC; + const void *current_buffer; + size_t curoff; + size_t txlen; + uint8_t txunitsize; + void (*completeCallback)(void*); + void *complete_ud; + volatile DMACCxLLI_desc_user_t *last_chain; + bool is_active = false; }; - static_assert(sizeof(DMACConfig_reg_t) == 4, "invalid size of LPC DMACConfig_reg_t"); - __LPC_DEFREG(DMACConfig_reg_t, DMACConfig, 0x50004030); + static volatile dma_process_t _dma_async_proc; - struct DMACSync_reg_t { - uint32_t DMACSync : 16; - uint32_t reserved1 : 16; - }; - static_assert(sizeof(DMACSync_reg_t) == 4, "invalid size of LPC DMACSync_reg_t"); - - __LPC_DEFREG(DMACSync_reg_t, DMACSync, 0x50004034); - - struct DMAReqSel_reg_t { - uint32_t DMASEL08 : 1; - uint32_t DMASEL09 : 1; - uint32_t DMASEL10 : 1; - uint32_t DMASEL11 : 1; - uint32_t DMASEL12 : 1; - uint32_t DMASEL13 : 1; - uint32_t DMASEL14 : 1; - uint32_t DMASEL15 : 1; - uint32_t reserved : 24; - }; - static_assert(sizeof(DMAReqSel_reg_t) == 4, "invalid size of LPC DMAReqSel_reg_t"); + static void DMAProgramSSPChain(volatile ssp_dev_t &SSP, volatile dma_process_t &proc) { + // Martin says: Don't mess with this function, or else the compiler might generate wrong code. ;) + // The fight of priorities! Volatile versus whatever! The climax of the century! + // Don't worry! You will lose sleep when fighting compiler bugs! Promised! + volatile DMACCxLLI_desc_user_t *first = nullptr; + volatile DMACCxLLI_desc_user_t *last = nullptr; - __LPC_DEFREG(DMAReqSel_reg_t, DMAReqSel, 0x400FC1C4); + uint32_t txwidth = 0; - struct DMACCxLLI_reg_t { - uint32_t reserved1 : 2; - uint32_t LLI : 30; - }; - static_assert(sizeof(DMACCxLLI_reg_t) == 4, "invalid size of LPC DMACCxLLI_reg_t"); - - struct DMACCxControl_reg_t { - uint32_t TransferSize : 12; - uint32_t SBSize : 3; - uint32_t DBSize : 3; - uint32_t SWidth : 3; - uint32_t DWidth : 3; - uint32_t reserved1 : 2; - uint32_t SI : 1; - uint32_t DI : 1; - uint32_t Prot1 : 1; - uint32_t Prot2 : 1; - uint32_t Prot3 : 1; - uint32_t I : 1; - }; - static_assert(sizeof(DMACCxControl_reg_t) == 4, "invalid size of LPC DMACCxControl_reg_t"); - - struct DMACCxConfig_reg_t { - uint32_t E : 1; - uint32_t SrcPeripheral : 5; - uint32_t DestPeripheral : 5; - uint32_t TransferType : 3; - uint32_t IE : 1; - uint32_t ITC : 1; - uint32_t L : 1; - uint32_t A : 1; - uint32_t H : 1; - uint32_t reserved1 : 13; - }; - static_assert(sizeof(DMACCxConfig_reg_t) == 4, "invalid size of LPC DMACCxConfig_reg_t"); + if (proc.txunitsize == 1) txwidth = 0; + else if (proc.txunitsize == 2) txwidth = 1; + else if (proc.txunitsize == 4) txwidth = 2; + else _spi_on_error(4); - struct DMACChannel_dev_t { - uint32_t SrcAddr; - uint32_t DestAddr; - DMACCxLLI_reg_t LLI; DMACCxControl_reg_t Control; - DMACCxConfig_reg_t Config; - }; - static_assert(sizeof(DMACChannel_dev_t) == 20, "invalid size of LPC DMACChannel_dev_t"); - - __LPC_DEFREG(DMACChannel_dev_t, DMACC0, 0x50004100); - __LPC_DEFREG(DMACChannel_dev_t, DMACC1, 0x50004120); - __LPC_DEFREG(DMACChannel_dev_t, DMACC2, 0x50004140); - __LPC_DEFREG(DMACChannel_dev_t, DMACC3, 0x50004160); - __LPC_DEFREG(DMACChannel_dev_t, DMACC4, 0x50004180); - __LPC_DEFREG(DMACChannel_dev_t, DMACC5, 0x500041A0); - __LPC_DEFREG(DMACChannel_dev_t, DMACC6, 0x500041C0); - __LPC_DEFREG(DMACChannel_dev_t, DMACC7, 0x500041E0); - - static volatile DMACChannel_dev_t& DMAGetChannel(const uint32_t idx) { - switch (idx) { - case 0: return DMACC0; - case 1: return DMACC1; - case 2: return DMACC2; - case 3: return DMACC3; - case 4: return DMACC4; - case 5: return DMACC5; - case 6: return DMACC6; - case 7: return DMACC7; - } - return DMACC0; // default. - } - - static uint32_t __attribute__((unused)) DMAGetChannelIndex(DMACChannel_dev_t &DMACC) { - if (&DMACC == &DMACC0) return 0; - if (&DMACC == &DMACC1) return 1; - if (&DMACC == &DMACC2) return 2; - if (&DMACC == &DMACC3) return 3; - if (&DMACC == &DMACC4) return 4; - if (&DMACC == &DMACC5) return 5; - if (&DMACC == &DMACC6) return 6; - if (&DMACC == &DMACC7) return 7; - return 0; // default. - } - - #ifdef HAL_SPI_SUPPORTS_ASYNC + Control.SBSize = 1; // 4 bytes + Control.DBSize = 1; // 4 bytes + Control.SWidth = txwidth; + Control.DWidth = txwidth; + Control.reserved1 = 0; + Control.SI = true; + Control.DI = false; + Control.Prot1 = 0; + Control.Prot2 = 0; + Control.Prot3 = 0; + Control.I = false; - struct DMACCxLLI_desc_t { - uint32_t SrcAddr; - uint32_t DestAddr; - volatile DMACCxLLI_desc_t *Next; - DMACCxControl_reg_t Control; - }; - static_assert(sizeof(DMACCxLLI_desc_t) == 16, "invalid size of LPC DMACCxLLI_desc_t"); + bool init_ch_prog = false; - struct DMACCxLLI_desc_user_t : public DMACCxLLI_desc_t { - // User data by software. - bool available = true; - }; + auto &DMACC = *proc.current_DMACC; + DMACC.Config.ITC = true; - #ifndef HALSPI_LPC_STATIC_DMADESCS - #define HALSPI_LPC_STATIC_DMADESCS 3 - #endif + DMACCxControl_reg_t ChannelControl; - static volatile DMACCxLLI_desc_user_t _available_dma_descs[HALSPI_LPC_STATIC_DMADESCS]; + while (proc.curoff < proc.txlen) { + size_t left = (proc.txlen - proc.curoff); + size_t takecnt = (uint32_t)__MIN (left, (1<<12)-1); - static volatile DMACCxLLI_desc_user_t* DMAFindFreeChainLLI() { - for (auto &item : _available_dma_descs) - if (item.available) return &item; - return nullptr; - } + Control.TransferSize = takecnt; - struct dma_process_t { - volatile DMACChannel_dev_t *current_DMACC; - const void *current_buffer; - size_t curoff; - size_t txlen; - uint8_t txunitsize; - void (*completeCallback)(void*); - void *complete_ud; - volatile DMACCxLLI_desc_user_t *last_chain; - bool is_active = false; - }; - - static volatile dma_process_t _dma_async_proc; - - static void DMAProgramSSPChain(volatile ssp_dev_t &SSP, volatile dma_process_t &proc) { - // Martin says: Don't mess with this function, or else the compiler might generate wrong code. ;) - // The fight of priorities! Volatile versus whatever! The climax of the century! - // Don't worry! You will lose sleep when fighting compiler bugs! Promised! - volatile DMACCxLLI_desc_user_t *first = nullptr; - volatile DMACCxLLI_desc_user_t *last = nullptr; - - uint32_t txwidth = 0; - - if (proc.txunitsize == 1) txwidth = 0; - else if (proc.txunitsize == 2) txwidth = 1; - else if (proc.txunitsize == 4) txwidth = 2; - else _spi_on_error(4); - - DMACCxControl_reg_t Control; - Control.SBSize = 1; // 4 bytes - Control.DBSize = 1; // 4 bytes - Control.SWidth = txwidth; - Control.DWidth = txwidth; - Control.reserved1 = 0; - Control.SI = true; - Control.DI = false; - Control.Prot1 = 0; - Control.Prot2 = 0; - Control.Prot3 = 0; - Control.I = false; - - bool init_ch_prog = false; - - auto &DMACC = *proc.current_DMACC; - DMACC.Config.ITC = true; - - DMACCxControl_reg_t ChannelControl; - - while (proc.curoff < proc.txlen) { - size_t left = (proc.txlen - proc.curoff); - size_t takecnt = (uint32_t)__MIN (left, (1<<12)-1); - - Control.TransferSize = takecnt; - - uint32_t SrcAddr = ( (uint32_t)proc.current_buffer + proc.curoff * proc.txunitsize ); - uint32_t DestAddr = (uint32_t)&SSP.DR; - - if (!init_ch_prog) { - // We first have to program the channel itself. - DMACC.SrcAddr = SrcAddr; - DMACC.DestAddr = DestAddr; - DMACC.LLI.LLI = 0; - ChannelControl = Control; - init_ch_prog = true; - } - else { - auto *freelli = DMAFindFreeChainLLI(); + uint32_t SrcAddr = ( (uint32_t)proc.current_buffer + proc.curoff * proc.txunitsize ); + uint32_t DestAddr = (uint32_t)&SSP.DR; - if (freelli == nullptr) break; + if (!init_ch_prog) { + // We first have to program the channel itself. + DMACC.SrcAddr = SrcAddr; + DMACC.DestAddr = DestAddr; + DMACC.LLI.LLI = 0; + ChannelControl = Control; + init_ch_prog = true; + } + else { + auto *freelli = DMAFindFreeChainLLI(); - freelli->SrcAddr = SrcAddr; - freelli->DestAddr = DestAddr; - LPCHelpers::dwrite(freelli->Control, Control); - freelli->available = false; + if (freelli == nullptr) break; - if (first == nullptr) { - first = freelli; - DMACC.LLI.LLI = ( (uint32_t)freelli >> 2 ); - } + freelli->SrcAddr = SrcAddr; + freelli->DestAddr = DestAddr; + LPCHelpers::dwrite(freelli->Control, Control); + freelli->available = false; - if (last) last->Next = freelli; - last = freelli; + if (first == nullptr) { + first = freelli; + DMACC.LLI.LLI = ( (uint32_t)freelli >> 2 ); } - proc.curoff += takecnt; - } - - if (last) { - last->Control.I = true; - last->Next = nullptr; + if (last) last->Next = freelli; + last = freelli; } - else ChannelControl.I = true; - LPCHelpers::dwrite(DMACC.Control, ChannelControl); + proc.curoff += takecnt; + } - proc.last_chain = first; + if (last) { + last->Control.I = true; + last->Next = nullptr; } + else ChannelControl.I = true; - #endif // HAL_SPI_SUPPORTS_ASYNC + LPCHelpers::dwrite(DMACC.Control, ChannelControl); - #endif // !HALSPI_DISABLE_DMA + proc.last_chain = first; + } - } // namespace MarlinLPC + #endif // HAL_SPI_SUPPORTS_ASYNC - #ifndef HALSPI_LOOPBEEP_TIMEOUT - #define HALSPI_LOOPBEEP_TIMEOUT 3000 - #endif + #endif // !HALSPI_DISABLE_DMA - struct spi_monitored_loop { - private: +} // namespace MarlinLPC + +#ifndef HALSPI_LOOPBEEP_TIMEOUT + #define HALSPI_LOOPBEEP_TIMEOUT 3000 +#endif + +struct spi_monitored_loop { + private: + #if defined(HALSPI_DO_LOOPBEEPS) && PIN_EXISTS(BEEPER) + uint32_t _start_millis; + #endif + public: + inline spi_monitored_loop() { #if defined(HALSPI_DO_LOOPBEEPS) && PIN_EXISTS(BEEPER) - uint32_t _start_millis; + _start_millis = millis(); #endif - public: - inline spi_monitored_loop() { - #if defined(HALSPI_DO_LOOPBEEPS) && PIN_EXISTS(BEEPER) - _start_millis = millis(); - #endif - } - void update(unsigned int beep_code) { - #if defined(HALSPI_DO_LOOPBEEPS) && PIN_EXISTS(BEEPER) - if ((millis() - _start_millis) <= HALSPI_LOOPBEEP_TIMEOUT) return; - OUT_WRITE(BEEPER_PIN, HIGH); delay(500); - OUT_WRITE(BEEPER_PIN, LOW); delay(200); + } + void update(unsigned int beep_code) { + #if defined(HALSPI_DO_LOOPBEEPS) && PIN_EXISTS(BEEPER) + if ((millis() - _start_millis) <= HALSPI_LOOPBEEP_TIMEOUT) return; + OUT_WRITE(BEEPER_PIN, HIGH); delay(500); + OUT_WRITE(BEEPER_PIN, LOW); delay(200); + OUT_WRITE(BEEPER_PIN, HIGH); delay(200); + OUT_WRITE(BEEPER_PIN, LOW); delay(200); + OUT_WRITE(BEEPER_PIN, HIGH); delay(200); + OUT_WRITE(BEEPER_PIN, LOW); delay(1000); + for (unsigned int n = 0; n < beep_code; n++) { OUT_WRITE(BEEPER_PIN, HIGH); delay(200); OUT_WRITE(BEEPER_PIN, LOW); delay(200); - OUT_WRITE(BEEPER_PIN, HIGH); delay(200); - OUT_WRITE(BEEPER_PIN, LOW); delay(1000); - for (unsigned int n = 0; n < beep_code; n++) { - OUT_WRITE(BEEPER_PIN, HIGH); delay(200); - OUT_WRITE(BEEPER_PIN, LOW); delay(200); - } - delay(800); - OUT_WRITE(BEEPER_PIN, HIGH); delay(1000); - OUT_WRITE(BEEPER_PIN, LOW); delay(2000); - #endif - } + } + delay(800); + OUT_WRITE(BEEPER_PIN, HIGH); delay(1000); + OUT_WRITE(BEEPER_PIN, LOW); delay(2000); + #endif + } +}; + +static MarlinLPC::gpioMapResult_t _ssp_gpioMap; +static volatile bool _ssp_is_active = false; +static volatile bool _ssp_transaction_is_running = false; +static volatile int _ssp_cs_pin; +static volatile int _ssp_bitOrder; +static volatile int _ssp_clockMode; +static volatile uint8_t _ssp_framesize; +static volatile bool _ssp_dirty_rxbuffer; + +#ifdef HAL_SPI_SUPPORTS_ASYNC + + struct ssp_process_t { + volatile MarlinLPC::ssp_dev_t *current_ssp; + const void *current_buffer; + size_t curoff_bytes; + size_t txlen_bytes; + uint8_t txunitsize; + bool is_active = false; + void (*completeCallback)(void*); + void *complete_ud; }; - static MarlinLPC::gpioMapResult_t _ssp_gpioMap; - static volatile bool _ssp_is_active = false; - static volatile bool _ssp_transaction_is_running = false; - static volatile int _ssp_cs_pin; - static volatile int _ssp_bitOrder; - static volatile int _ssp_clockMode; - static volatile uint8_t _ssp_framesize; - static volatile bool _ssp_dirty_rxbuffer; - - #ifdef HAL_SPI_SUPPORTS_ASYNC - - struct ssp_process_t { - volatile MarlinLPC::ssp_dev_t *current_ssp; - const void *current_buffer; - size_t curoff_bytes; - size_t txlen_bytes; - uint8_t txunitsize; - bool is_active = false; - void (*completeCallback)(void*); - void *complete_ud; - }; - - static ssp_process_t _ssp_async_proc; + static ssp_process_t _ssp_async_proc; - #endif // HAL_SPI_SUPPORTS_ASYNC +#endif // HAL_SPI_SUPPORTS_ASYNC - static void _spiAsyncBarrier() { - #ifdef HAL_SPI_SUPPORTS_ASYNC - spi_monitored_loop asyncspiw; - while (_ssp_async_proc.is_active) { asyncspiw.update(10); /* wait for any async SPI TX to finish */ } - #ifndef HALSPI_DISABLE_DMA - spi_monitored_loop asyncdmaw; - while (MarlinLPC::_dma_async_proc.is_active) { asyncdmaw.update(11); /* wait for any async DMA TX to finish */ } - #endif +static void _spiAsyncBarrier() { + #ifdef HAL_SPI_SUPPORTS_ASYNC + spi_monitored_loop asyncspiw; + while (_ssp_async_proc.is_active) { asyncspiw.update(10); /* wait for any async SPI TX to finish */ } + #ifndef HALSPI_DISABLE_DMA + spi_monitored_loop asyncdmaw; + while (MarlinLPC::_dma_async_proc.is_active) { asyncdmaw.update(11); /* wait for any async DMA TX to finish */ } #endif - } + #endif +} - void spiBegin() { - #if PIN_EXISTS(SD_SS) - OUT_WRITE(SD_SS_PIN, HIGH); - #endif +void spiBegin() { + #if PIN_EXISTS(SD_SS) + OUT_WRITE(SD_SS_PIN, HIGH); + #endif - // Turn off peripherals by default. - MarlinLPC::PCONP.PCSPI = false; - MarlinLPC::PCONP.PCSSP0 = false; - MarlinLPC::PCONP.PCSSP1 = false; - MarlinLPC::PCONP.PCGPDMA = false; + // Turn off peripherals by default. + MarlinLPC::PCONP.PCSPI = false; + MarlinLPC::PCONP.PCSSP0 = false; + MarlinLPC::PCONP.PCSSP1 = false; + MarlinLPC::PCONP.PCGPDMA = false; +} + +void spiSetupChipSelect(int pin) { + OUT_WRITE(pin, HIGH); +} + +static void _spiConfigClock(volatile MarlinLPC::ssp_dev_t &SSP, int clockMode) { + if (clockMode == SPI_CLKMODE_0) { + SSP.CR0.CPOL = false; + SSP.CR0.CPHA = false; } - - void spiSetupChipSelect(int pin) { - OUT_WRITE(pin, HIGH); + else if (clockMode == SPI_CLKMODE_1) { + SSP.CR0.CPOL = false; + SSP.CR0.CPHA = true; } - - static void _spiConfigClock(volatile MarlinLPC::ssp_dev_t &SSP, int clockMode) { - if (clockMode == SPI_CLKMODE_0) { - SSP.CR0.CPOL = false; - SSP.CR0.CPHA = false; - } - else if (clockMode == SPI_CLKMODE_1) { - SSP.CR0.CPOL = false; - SSP.CR0.CPHA = true; - } - else if (clockMode == SPI_CLKMODE_2) { - SSP.CR0.CPOL = true; - SSP.CR0.CPHA = false; - } - else if (clockMode == SPI_CLKMODE_3) { - SSP.CR0.CPOL = true; - SSP.CR0.CPHA = true; - } - _ssp_clockMode = clockMode; + else if (clockMode == SPI_CLKMODE_2) { + SSP.CR0.CPOL = true; + SSP.CR0.CPHA = false; } + else if (clockMode == SPI_CLKMODE_3) { + SSP.CR0.CPOL = true; + SSP.CR0.CPHA = true; + } + _ssp_clockMode = clockMode; +} - void spiInitEx(uint32_t maxClockFreq, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { - #ifdef HAL_SPI_SUPPORTS_ASYNC - spi_monitored_loop initw; - while (_ssp_is_active) { initw.update(13); /* wait for any other SPI activity to finish */ } - #else - if (_ssp_is_active) _spi_on_error(1); - #endif - - _ssp_gpioMap = MarlinLPC::SPIMapGPIO(hint_sck, hint_miso, hint_mosi, -1); - _ssp_is_active = true; - _ssp_cs_pin = hint_cs; +void spiInitEx(uint32_t maxClockFreq, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { + #ifdef HAL_SPI_SUPPORTS_ASYNC + spi_monitored_loop initw; + while (_ssp_is_active) { initw.update(13); /* wait for any other SPI activity to finish */ } + #else + if (_ssp_is_active) _spi_on_error(1); + #endif - MarlinLPC::sspClockResult_t clockRes = MarlinLPC::SPICalculateClock(maxClockFreq); + _ssp_gpioMap = MarlinLPC::SPIMapGPIO(hint_sck, hint_miso, hint_mosi, -1); + _ssp_is_active = true; + _ssp_cs_pin = hint_cs; - uint8_t sspBusIdx = _ssp_gpioMap.sspBusIdx; - auto &SSP = MarlinLPC::SPIGetBusFromIndex(sspBusIdx); + MarlinLPC::sspClockResult_t clockRes = MarlinLPC::SPICalculateClock(maxClockFreq); - if (sspBusIdx == 0) { - MarlinLPC::PCONP.PCSSP0 = true; - MarlinLPC::PCLKSEL1.PCLK_SSP0 = clockRes.pclk_ssp; - } - else if (sspBusIdx == 1) { - MarlinLPC::PCONP.PCSSP1 = true; - MarlinLPC::PCLKSEL0.PCLK_SSP1 = clockRes.pclk_ssp; - } - SSP.CPSR.CPSDVSR = clockRes.cpsdvsr; - SSP.CR0.DSS = 7; // 8 bit transfer - SSP.CR0.SCR = clockRes.scr; - SSP.CR0.FRF = 0; // SPI - _spiConfigClock(SSP, SPI_CLKMODE_DEFAULT); - SSP.CR1.LBM = 0; - SSP.CR1.SSE = 0; - SSP.CR1.MS = 0; // master + uint8_t sspBusIdx = _ssp_gpioMap.sspBusIdx; + auto &SSP = MarlinLPC::SPIGetBusFromIndex(sspBusIdx); - _ssp_transaction_is_running = false; - _ssp_bitOrder = SPI_BITORDER_DEFAULT; // SSP peripheral has no bit-order specification support (legacy SPI peripheral only) - _ssp_dirty_rxbuffer = false; - _ssp_framesize = sizeof(uint8_t); // default (DSS = 7). + if (sspBusIdx == 0) { + MarlinLPC::PCONP.PCSSP0 = true; + MarlinLPC::PCLKSEL1.PCLK_SSP0 = clockRes.pclk_ssp; } - - void spiInit(uint8_t spiRate, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { - // Use datarates Marlin uses - uint32_t clock; - switch (spiRate) { - case SPI_FULL_SPEED: clock = 20000000; break; // 13.9mhz=20000000 6.75mhz=10000000 3.38mhz=5000000 .833mhz=1000000 - case SPI_HALF_SPEED: clock = 5000000; break; - case SPI_QUARTER_SPEED: clock = 2500000; break; - case SPI_EIGHTH_SPEED: clock = 1250000; break; - case SPI_SPEED_5: clock = 625000; break; - case SPI_SPEED_6: clock = 300000; break; - default: - clock = 4000000; // Default from the SPI library - } - spiInitEx(clock, hint_sck, hint_miso, hint_mosi, hint_cs); + else if (sspBusIdx == 1) { + MarlinLPC::PCONP.PCSSP1 = true; + MarlinLPC::PCLKSEL0.PCLK_SSP1 = clockRes.pclk_ssp; } - - static void _spiStart() { - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - SSP.CR1.SSE = true; - if (_ssp_cs_pin >= 0) { - MarlinLPC::MapPortPinFunc(_ssp_cs_pin, 0); // make sure that the CS pin is configured as GPIO. - OUT_WRITE(_ssp_cs_pin, LOW); - } + SSP.CPSR.CPSDVSR = clockRes.cpsdvsr; + SSP.CR0.DSS = 7; // 8 bit transfer + SSP.CR0.SCR = clockRes.scr; + SSP.CR0.FRF = 0; // SPI + _spiConfigClock(SSP, SPI_CLKMODE_DEFAULT); + SSP.CR1.LBM = 0; + SSP.CR1.SSE = 0; + SSP.CR1.MS = 0; // master + + _ssp_transaction_is_running = false; + _ssp_bitOrder = SPI_BITORDER_DEFAULT; // SSP peripheral has no bit-order specification support (legacy SPI peripheral only) + _ssp_dirty_rxbuffer = false; + _ssp_framesize = sizeof(uint8_t); // default (DSS = 7). +} + +void spiInit(uint8_t spiRate, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { + // Use Marlin datarates + uint32_t clock; + switch (spiRate) { + case SPI_FULL_SPEED: clock = 20000000; break; // 13.9mhz=20000000 6.75mhz=10000000 3.38mhz=5000000 .833mhz=1000000 + case SPI_HALF_SPEED: clock = 5000000; break; + case SPI_QUARTER_SPEED: clock = 2500000; break; + case SPI_EIGHTH_SPEED: clock = 1250000; break; + case SPI_SPEED_5: clock = 625000; break; + case SPI_SPEED_6: clock = 300000; break; + default: + clock = 4000000; // Default from the SPI library } - static void _spiEnd() { - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - spi_monitored_loop tfew; - while (!SSP.SR.TFE) { tfew.update(1); /* wait until all items from the TX queue were pushed */ } - spi_monitored_loop bsyw; - while (SSP.SR.BSY) { bsyw.update(2); /* wait until the current data transfer has finished (clean shutdown) */ } - if (_ssp_cs_pin >= 0) OUT_WRITE(_ssp_cs_pin, HIGH); - SSP.CR1.SSE = false; + spiInitEx(clock, hint_sck, hint_miso, hint_mosi, hint_cs); +} + +static void _spiStart() { + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); + SSP.CR1.SSE = true; + if (_ssp_cs_pin >= 0) { + MarlinLPC::MapPortPinFunc(_ssp_cs_pin, 0); // make sure that the CS pin is configured as GPIO. + OUT_WRITE(_ssp_cs_pin, LOW); } - - static void _maybe_start_transaction() { - if (!_ssp_transaction_is_running) { - _spiStart(); - _ssp_transaction_is_running = true; - } +} +static void _spiEnd() { + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); + spi_monitored_loop tfew; + while (!SSP.SR.TFE) { tfew.update(1); /* wait until all items from the TX queue were pushed */ } + spi_monitored_loop bsyw; + while (SSP.SR.BSY) { bsyw.update(2); /* wait until the current data transfer has finished (clean shutdown) */ } + if (_ssp_cs_pin >= 0) OUT_WRITE(_ssp_cs_pin, HIGH); + SSP.CR1.SSE = false; +} + +static void _maybe_start_transaction() { + if (!_ssp_transaction_is_running) { + _spiStart(); + _ssp_transaction_is_running = true; } +} - void spiClose() { - if (!_ssp_is_active) _spi_on_error(2); +void spiClose() { + if (!_ssp_is_active) _spi_on_error(2); - _spiAsyncBarrier(); + _spiAsyncBarrier(); - uint8_t sspBusIdx = _ssp_gpioMap.sspBusIdx; + uint8_t sspBusIdx = _ssp_gpioMap.sspBusIdx; - if (_ssp_transaction_is_running) { - _spiEnd(); - _ssp_transaction_is_running = false; - } + if (_ssp_transaction_is_running) { + _spiEnd(); + _ssp_transaction_is_running = false; + } - if (sspBusIdx == 0) - MarlinLPC::PCONP.PCSSP0 = false; - else if (sspBusIdx == 1) - MarlinLPC::PCONP.PCSSP1 = false; + if (sspBusIdx == 0) + MarlinLPC::PCONP.PCSSP0 = false; + else if (sspBusIdx == 1) + MarlinLPC::PCONP.PCSSP1 = false; - MarlinLPC::SPIUnmapGPIO(_ssp_gpioMap); + MarlinLPC::SPIUnmapGPIO(_ssp_gpioMap); - _ssp_is_active = false; - } + _ssp_is_active = false; +} - void spiSetBitOrder(int bitOrder) { - if (_ssp_bitOrder != bitOrder) { - _spiAsyncBarrier(); - if (_ssp_transaction_is_running) _spiEnd(); - _ssp_bitOrder = bitOrder; - if (_ssp_transaction_is_running) _spiStart(); - } +void spiSetBitOrder(int bitOrder) { + if (_ssp_bitOrder != bitOrder) { + _spiAsyncBarrier(); + if (_ssp_transaction_is_running) _spiEnd(); + _ssp_bitOrder = bitOrder; + if (_ssp_transaction_is_running) _spiStart(); } +} - void spiSetClockMode(int clockMode) { - if (_ssp_clockMode != clockMode) { - _spiAsyncBarrier(); - if (_ssp_transaction_is_running) _spiEnd(); - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - _spiConfigClock(SSP, clockMode); - if (_ssp_transaction_is_running) _spiStart(); - } +void spiSetClockMode(int clockMode) { + if (_ssp_clockMode != clockMode) { + _spiAsyncBarrier(); + if (_ssp_transaction_is_running) _spiEnd(); + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); + _spiConfigClock(SSP, clockMode); + if (_ssp_transaction_is_running) _spiStart(); } +} - void spiEstablish() { _maybe_start_transaction(); } +void spiEstablish() { _maybe_start_transaction(); } - // Internal. - inline void _spiSetFrameSize(uint8_t fsize) { - if (_ssp_framesize != fsize) { - _spiAsyncBarrier(); +// Internal. +inline void _spiSetFrameSize(uint8_t fsize) { + if (_ssp_framesize != fsize) { + _spiAsyncBarrier(); - if (_ssp_transaction_is_running) _spiEnd(); + if (_ssp_transaction_is_running) _spiEnd(); - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - SSP.CR0.DSS = (fsize * 8)-1; - _ssp_framesize = fsize; + SSP.CR0.DSS = (fsize * 8)-1; + _ssp_framesize = fsize; - if (_ssp_transaction_is_running) _spiStart(); - } + if (_ssp_transaction_is_running) _spiStart(); } - - // Unsigned integer only. - template - inline constexpr numberType __flip_bits_generic(numberType v) noexcept { - numberType result = 0; - for (unsigned int n = 0; n < sizeof(numberType) * 8; n++) { - result <<= 1; - bool bitval = ( v & (1< +inline constexpr numberType __flip_bits_generic(numberType v) noexcept { + numberType result = 0; + for (unsigned int n = 0; n < sizeof(numberType) * 8; n++) { + result <<= 1; + bool bitval = ( v & (1<> 24u ); - } + else { + asm("RBIT %k0,%k1" : "=r" (v) : "r" (v)); + return v; } - inline constexpr uint16_t _flip_bits(uint16_t v) noexcept { - if ( __builtin_is_constant_evaluated() ) { - return __flip_bits_generic(v); - } - else { - return (uint16_t)( _flip_bits((uint32_t)v) >> 16u ); - } +} +inline constexpr uint8_t _flip_bits(uint8_t v) noexcept { + if ( __builtin_is_constant_evaluated() ) { + return __flip_bits_generic(v); } + else { + return (uint8_t)( _flip_bits((uint32_t)v) >> 24u ); + } +} +inline constexpr uint16_t _flip_bits(uint16_t v) noexcept { + if ( __builtin_is_constant_evaluated() ) { + return __flip_bits_generic(v); + } + else { + return (uint16_t)( _flip_bits((uint32_t)v) >> 16u ); + } +} - template - inline void _spi_push_to_queue(volatile MarlinLPC::ssp_dev_t &SSP, numberType val) { - bool revbits = (_ssp_bitOrder == SPI_BITORDER_LSB); - if (_ssp_framesize == 1) { - // Push it byte-by-byte (DSS = 7). - const uint32_t num_bytes = sizeof(numberType); - - bool revbytes = (_ssp_bitOrder == SPI_BITORDER_MSB); - - for (uint32_t n = 0; n < num_bytes; n++) { - uint32_t byte_idx = revbytes ? (num_bytes - 1) - n : n; - uint32_t bitidx = byte_idx * 8; - - spi_monitored_loop tnfw; - while (!SSP.SR.TNF) { tnfw.update(3); /* wait for space on the TX FIFO */ } +template +inline void _spi_push_to_queue(volatile MarlinLPC::ssp_dev_t &SSP, numberType val) { + bool revbits = (_ssp_bitOrder == SPI_BITORDER_LSB); + if (_ssp_framesize == 1) { + // Push it byte-by-byte (DSS = 7). + const uint32_t num_bytes = sizeof(numberType); - uint8_t byteval = (val >> bitidx) & 0xFF; + bool revbytes = (_ssp_bitOrder == SPI_BITORDER_MSB); - if (revbits) byteval = _flip_bits(byteval); + for (uint32_t n = 0; n < num_bytes; n++) { + uint32_t byte_idx = revbytes ? (num_bytes - 1) - n : n; + uint32_t bitidx = byte_idx * 8; - SSP.DR.DATA = byteval; - } - } - else if (_ssp_framesize == 2) { spi_monitored_loop tnfw; while (!SSP.SR.TNF) { tnfw.update(3); /* wait for space on the TX FIFO */ } - if (revbits) val = _flip_bits(val); + uint8_t byteval = (val >> bitidx) & 0xFF; - // The number size must match the framesize. - SSP.DR.DATA = val; + if (revbits) byteval = _flip_bits(byteval); + + SSP.DR.DATA = byteval; } } + else if (_ssp_framesize == 2) { + spi_monitored_loop tnfw; + while (!SSP.SR.TNF) { tnfw.update(3); /* wait for space on the TX FIFO */ } - void spiSend(uint8_t val) { - if (_ssp_gpioMap.gpio_mosi < 0) return; - - _spiSetFrameSize(sizeof(val)); + if (revbits) val = _flip_bits(val); - _maybe_start_transaction(); + // The number size must match the framesize. + SSP.DR.DATA = val; + } +} - _spiAsyncBarrier(); +void spiSend(uint8_t val) { + if (_ssp_gpioMap.gpio_mosi < 0) return; - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); + _spiSetFrameSize(sizeof(val)); - _spi_push_to_queue(SSP, val); + _maybe_start_transaction(); - // Ignore read buffer; it will be flushed if required. - _ssp_dirty_rxbuffer = true; - } + _spiAsyncBarrier(); - void spiSend16(uint16_t val) { - if (_ssp_gpioMap.gpio_mosi < 0) return; + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - _spiSetFrameSize(sizeof(val)); + _spi_push_to_queue(SSP, val); - _maybe_start_transaction(); + // Ignore read buffer; it will be flushed if required. + _ssp_dirty_rxbuffer = true; +} - _spiAsyncBarrier(); +void spiSend16(uint16_t val) { + if (_ssp_gpioMap.gpio_mosi < 0) return; - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); + _spiSetFrameSize(sizeof(val)); - _spi_push_to_queue(SSP, val); + _maybe_start_transaction(); - // Ignore read buffer; it will be flushed if required. - _ssp_dirty_rxbuffer = true; - } + _spiAsyncBarrier(); - static void _spi_flush_rxqueue(volatile MarlinLPC::ssp_dev_t &SSP) { - if (!_ssp_dirty_rxbuffer) return; + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - spi_monitored_loop tfew; - while (!SSP.SR.TFE) { tfew.update(4); /* wait until any tx data has been acquired that is still left */ } - spi_monitored_loop bsyw; - while (SSP.SR.BSY) { bsyw.update(5); /* wait until transfers and their parallel receives have finished */ } - spi_monitored_loop rnew; - while (SSP.SR.RNE) { - rnew.update(6); - auto unused = SSP.DR.DATA; - (void)unused; - } - _ssp_dirty_rxbuffer = false; - } + _spi_push_to_queue(SSP, val); - template - inline numberType _spi_fetch_from_queue(volatile MarlinLPC::ssp_dev_t &SSP) { - numberType result = 0; - bool revbits = (_ssp_bitOrder == SPI_BITORDER_LSB); + // Ignore read buffer; it will be flushed if required. + _ssp_dirty_rxbuffer = true; +} - if (_ssp_framesize == 1) { - // Fetch it byte-by-byte (DSS = 7). - const uint32_t num_bytes = sizeof(numberType); +static void _spi_flush_rxqueue(volatile MarlinLPC::ssp_dev_t &SSP) { + if (!_ssp_dirty_rxbuffer) return; - bool revbytes = (_ssp_bitOrder == SPI_BITORDER_MSB); + spi_monitored_loop tfew; + while (!SSP.SR.TFE) { tfew.update(4); /* wait until any tx data has been acquired that is still left */ } + spi_monitored_loop bsyw; + while (SSP.SR.BSY) { bsyw.update(5); /* wait until transfers and their parallel receives have finished */ } + spi_monitored_loop rnew; + while (SSP.SR.RNE) { + rnew.update(6); + auto unused = SSP.DR.DATA; + (void)unused; + } + _ssp_dirty_rxbuffer = false; +} - for (uint32_t n = 0; n < num_bytes; n++) { - uint32_t byte_idx = revbytes ? (num_bytes - 1) - n : n; - uint32_t bitidx = byte_idx * 8; +template +inline numberType _spi_fetch_from_queue(volatile MarlinLPC::ssp_dev_t &SSP) { + numberType result = 0; + bool revbits = (_ssp_bitOrder == SPI_BITORDER_LSB); - spi_monitored_loop rnew; - while (!SSP.SR.RNE) { rnew.update(7); /* wait for any data */ } + if (_ssp_framesize == 1) { + // Fetch it byte-by-byte (DSS = 7). + const uint32_t num_bytes = sizeof(numberType); - uint8_t byteval = SSP.DR.DATA & 0xFF; + bool revbytes = (_ssp_bitOrder == SPI_BITORDER_MSB); - if (revbits) byteval = _flip_bits(byteval); + for (uint32_t n = 0; n < num_bytes; n++) { + uint32_t byte_idx = revbytes ? (num_bytes - 1) - n : n; + uint32_t bitidx = byte_idx * 8; - result |= ( (numberType)byteval << bitidx ); - } - } - else if (_ssp_framesize == 2) { spi_monitored_loop rnew; while (!SSP.SR.RNE) { rnew.update(7); /* wait for any data */ } - result = SSP.DR.DATA; + uint8_t byteval = SSP.DR.DATA & 0xFF; - if (revbits) result = _flip_bits(result); - } - return result; - } + if (revbits) byteval = _flip_bits(byteval); - uint8_t spiRec(uint8_t txval) { - if (_ssp_gpioMap.gpio_miso < 0) { - spiSend(txval); - return 0; + result |= ( (numberType)byteval << bitidx ); } - - _spiSetFrameSize(sizeof(uint8_t)); - - _maybe_start_transaction(); - - _spiAsyncBarrier(); - - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - - _spi_flush_rxqueue(SSP); - - _spi_push_to_queue(SSP, txval); - - return _spi_fetch_from_queue (SSP); } + else if (_ssp_framesize == 2) { + spi_monitored_loop rnew; + while (!SSP.SR.RNE) { rnew.update(7); /* wait for any data */ } - uint16_t spiRec16(uint16_t txval) { - if (_ssp_gpioMap.gpio_miso < 0) return 0; - - _spiSetFrameSize(sizeof(uint16_t)); - - _maybe_start_transaction(); - - _spiAsyncBarrier(); - - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - - _spi_flush_rxqueue(SSP); - - _spi_push_to_queue(SSP, txval); + result = SSP.DR.DATA; - return _spi_fetch_from_queue (SSP); + if (revbits) result = _flip_bits(result); } + return result; +} - void spiRead(uint8_t *buf, uint16_t cnt, uint8_t txval) { - if (cnt == 0) return; - if (_ssp_gpioMap.gpio_miso < 0) { - spiWriteRepeat(txval, cnt); - return; - } - - _spiSetFrameSize(sizeof(uint8_t)); - - _maybe_start_transaction(); - - _spiAsyncBarrier(); +uint8_t spiRec(uint8_t txval) { + if (_ssp_gpioMap.gpio_miso < 0) { + spiSend(txval); + return 0; + } - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); + _spiSetFrameSize(sizeof(uint8_t)); - _spi_flush_rxqueue(SSP); + _maybe_start_transaction(); - for (uint16_t n = 0; n < cnt; n++) { - _spi_push_to_queue(SSP, txval); - buf[n] = _spi_fetch_from_queue (SSP); - } - } + _spiAsyncBarrier(); - void spiSendBlock(uint8_t token, const uint8_t *buf) { - if (_ssp_gpioMap.gpio_mosi < 0) return; + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - _spiSetFrameSize(sizeof(uint8_t)); + _spi_flush_rxqueue(SSP); - _maybe_start_transaction(); + _spi_push_to_queue(SSP, txval); - _spiAsyncBarrier(); + return _spi_fetch_from_queue (SSP); +} - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); +uint16_t spiRec16(uint16_t txval) { + if (_ssp_gpioMap.gpio_miso < 0) return 0; - _spi_push_to_queue(SSP, token); + _spiSetFrameSize(sizeof(uint16_t)); - for (uint16_t n = 0; n < 512; n++) { - _spi_push_to_queue(SSP, buf[n]); - } + _maybe_start_transaction(); - _ssp_dirty_rxbuffer = true; - } + _spiAsyncBarrier(); - #ifndef HALSPI_DISABLE_DMA + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - static void _dmaStart() { - MarlinLPC::PCONP.PCGPDMA = true; - MarlinLPC::DMACConfig.E = true; - MarlinLPC::DMACConfig.M = 0; - } + _spi_flush_rxqueue(SSP); - static void _dmaEnd() { - MarlinLPC::DMACConfig.E = false; - MarlinLPC::PCONP.PCGPDMA = false; - } + _spi_push_to_queue(SSP, txval); - static void _dmacInitSSP(volatile MarlinLPC::DMACChannel_dev_t &DMACC, uint8_t sspBusIdx) { - if (sspBusIdx == 0) - DMACC.Config.DestPeripheral = 0; // SSP0 TX - else if (sspBusIdx == 1) - DMACC.Config.DestPeripheral = 2; // SSP1 TX - DMACC.Config.TransferType = 1; // memory to peripheral - DMACC.Config.IE = false; - DMACC.Config.ITC = false; - DMACC.Config.L = false; - DMACC.Config.H = false; - } + return _spi_fetch_from_queue (SSP); +} - template - inline void _dmaSendBlocking(const numberType *buf, uint32_t cnt) { - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); +void spiRead(uint8_t *buf, uint16_t cnt, uint8_t txval) { + if (cnt == 0) return; + if (_ssp_gpioMap.gpio_miso < 0) { + spiWriteRepeat(txval, cnt); + return; + } - uint32_t txwidth = 0; + _spiSetFrameSize(sizeof(uint8_t)); - if (sizeof(numberType) == 1) txwidth = 0; - else if (sizeof(numberType) == 2) txwidth = 1; - else if (sizeof(numberType) == 4) txwidth = 2; - else _spi_on_error(5); + _maybe_start_transaction(); - auto &DMACC = MarlinLPC::DMAGetChannel(0); - DMACC.DestAddr = (uint32_t)&SSP.DR; - DMACC.LLI.LLI = 0; - _dmacInitSSP(DMACC, _ssp_gpioMap.sspBusIdx); + _spiAsyncBarrier(); - // Enable DMA on the SSP. - SSP.DMACR.TXDMAE = true; - SSP.DMACR.RXDMAE = false; + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - uint32_t curoff = 0; + _spi_flush_rxqueue(SSP); - while (curoff < cnt) { - uint32_t left = (cnt - curoff); - uint32_t takecnt = __MIN (left, (1<<12)-1); + for (uint16_t n = 0; n < cnt; n++) { + _spi_push_to_queue(SSP, txval); + buf[n] = _spi_fetch_from_queue (SSP); + } +} - MarlinLPC::DMACCxControl_reg_t Control; - Control.TransferSize = takecnt; - Control.SBSize = 1; // 4 bytes - Control.DBSize = 1; // 4 bytes - Control.SWidth = txwidth; - Control.DWidth = txwidth; - Control.reserved1 = 0; - Control.SI = true; - Control.DI = false; - Control.Prot1 = 0; - Control.Prot2 = 0; - Control.Prot3 = 0; - Control.I = false; +void spiSendBlock(uint8_t token, const uint8_t *buf) { + if (_ssp_gpioMap.gpio_mosi < 0) return; - DMACC.SrcAddr = (uint32_t)( buf + curoff ); - LPCHelpers::dwrite(DMACC.Control, Control); + _spiSetFrameSize(sizeof(uint8_t)); - curoff += takecnt; + _maybe_start_transaction(); - // Kick off the DMA. - DMACC.Config.E = true; - spi_monitored_loop syncdmaw; - while (DMACC.Config.E) { syncdmaw.update(11); /* wait for the DMA TX to finish */ } - } + _spiAsyncBarrier(); - // Disable DMA on the SSP. - SSP.DMACR.TXDMAE = false; + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - _ssp_dirty_rxbuffer = true; - } + _spi_push_to_queue(SSP, token); - template - static void _dmaSendRepeatBlocking(numberType val, uint32_t repcnt) { - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); + for (uint16_t n = 0; n < 512; n++) { + _spi_push_to_queue(SSP, buf[n]); + } - uint32_t txwidth = 0; + _ssp_dirty_rxbuffer = true; +} - // Since the MCU transfers binary arrays from MSB-to-LSB, we have to flip the bitorder if we want - // a LSBFIRST repeat-transfer to happen. This works very fine, unlike massive-data-through-DMA which - // would need flipping on a large scale. - if (_ssp_bitOrder == SPI_BITORDER_LSB) { - val = _flip_bits(val); - } +#ifndef HALSPI_DISABLE_DMA - if (sizeof(numberType) == 1) txwidth = 0; - else if (sizeof(numberType) == 2) txwidth = 1; - else if (sizeof(numberType) == 4) txwidth = 2; - else _spi_on_error(5); + static void _dmaStart() { + MarlinLPC::PCONP.PCGPDMA = true; + MarlinLPC::DMACConfig.E = true; + MarlinLPC::DMACConfig.M = 0; + } - auto &DMACC = MarlinLPC::DMAGetChannel(0); - DMACC.SrcAddr = (uint32_t)&val; - DMACC.DestAddr = (uint32_t)&SSP.DR; - DMACC.LLI.LLI = 0; - _dmacInitSSP(DMACC, _ssp_gpioMap.sspBusIdx); + static void _dmaEnd() { + MarlinLPC::DMACConfig.E = false; + MarlinLPC::PCONP.PCGPDMA = false; + } - // Enable DMA on the SSP. - SSP.DMACR.TXDMAE = true; - SSP.DMACR.RXDMAE = false; + static void _dmacInitSSP(volatile MarlinLPC::DMACChannel_dev_t &DMACC, uint8_t sspBusIdx) { + if (sspBusIdx == 0) + DMACC.Config.DestPeripheral = 0; // SSP0 TX + else if (sspBusIdx == 1) + DMACC.Config.DestPeripheral = 2; // SSP1 TX + DMACC.Config.TransferType = 1; // memory to peripheral + DMACC.Config.IE = false; + DMACC.Config.ITC = false; + DMACC.Config.L = false; + DMACC.Config.H = false; + } - size_t curoff = 0; + template + inline void _dmaSendBlocking(const numberType *buf, uint32_t cnt) { + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - while (curoff < repcnt) { - uint32_t left = (repcnt - curoff); - uint32_t takecnt = __MIN (left, (1<<12)-1); + uint32_t txwidth = 0; + + if (sizeof(numberType) == 1) txwidth = 0; + else if (sizeof(numberType) == 2) txwidth = 1; + else if (sizeof(numberType) == 4) txwidth = 2; + else _spi_on_error(5); + + auto &DMACC = MarlinLPC::DMAGetChannel(0); + DMACC.DestAddr = (uint32_t)&SSP.DR; + DMACC.LLI.LLI = 0; + _dmacInitSSP(DMACC, _ssp_gpioMap.sspBusIdx); + + // Enable DMA on the SSP. + SSP.DMACR.TXDMAE = true; + SSP.DMACR.RXDMAE = false; + + uint32_t curoff = 0; + + while (curoff < cnt) { + uint32_t left = (cnt - curoff); + uint32_t takecnt = __MIN (left, (1<<12)-1); + + MarlinLPC::DMACCxControl_reg_t Control; + Control.TransferSize = takecnt; + Control.SBSize = 1; // 4 bytes + Control.DBSize = 1; // 4 bytes + Control.SWidth = txwidth; + Control.DWidth = txwidth; + Control.reserved1 = 0; + Control.SI = true; + Control.DI = false; + Control.Prot1 = 0; + Control.Prot2 = 0; + Control.Prot3 = 0; + Control.I = false; + + DMACC.SrcAddr = (uint32_t)( buf + curoff ); + LPCHelpers::dwrite(DMACC.Control, Control); + + curoff += takecnt; + + // Kick off the DMA. + DMACC.Config.E = true; + spi_monitored_loop syncdmaw; + while (DMACC.Config.E) { syncdmaw.update(11); /* wait for the DMA TX to finish */ } + } - MarlinLPC::DMACCxControl_reg_t Control; - Control.TransferSize = takecnt; - Control.SBSize = 1; // 4 bytes - Control.DBSize = 1; // 4 bytes - Control.SWidth = txwidth; - Control.DWidth = txwidth; - Control.reserved1 = 0; - Control.SI = false; - Control.DI = false; - Control.Prot1 = 0; - Control.Prot2 = 0; - Control.Prot3 = 0; - Control.I = false; + // Disable DMA on the SSP. + SSP.DMACR.TXDMAE = false; - LPCHelpers::dwrite(DMACC.Control, Control); + _ssp_dirty_rxbuffer = true; + } - curoff += takecnt; + template + static void _dmaSendRepeatBlocking(numberType val, uint32_t repcnt) { + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - // Kick off the DMA. - DMACC.Config.E = true; - spi_monitored_loop syncdmaw; - while (DMACC.Config.E) { syncdmaw.update(12); /* wait for the DMA TX to finish */ } - } + uint32_t txwidth = 0; - // Disable DMA on the SSP. - SSP.DMACR.TXDMAE = false; + // Since the MCU transfers binary arrays from MSB-to-LSB, we have to flip the bitorder if we want + // a LSBFIRST repeat-transfer to happen. This works very fine, unlike massive-data-through-DMA which + // would need flipping on a large scale. + if (_ssp_bitOrder == SPI_BITORDER_LSB) { + val = _flip_bits(val); + } - _ssp_dirty_rxbuffer = true; + if (sizeof(numberType) == 1) txwidth = 0; + else if (sizeof(numberType) == 2) txwidth = 1; + else if (sizeof(numberType) == 4) txwidth = 2; + else _spi_on_error(5); + + auto &DMACC = MarlinLPC::DMAGetChannel(0); + DMACC.SrcAddr = (uint32_t)&val; + DMACC.DestAddr = (uint32_t)&SSP.DR; + DMACC.LLI.LLI = 0; + _dmacInitSSP(DMACC, _ssp_gpioMap.sspBusIdx); + + // Enable DMA on the SSP. + SSP.DMACR.TXDMAE = true; + SSP.DMACR.RXDMAE = false; + + size_t curoff = 0; + + while (curoff < repcnt) { + uint32_t left = (repcnt - curoff); + uint32_t takecnt = __MIN (left, (1<<12)-1); + + MarlinLPC::DMACCxControl_reg_t Control; + Control.TransferSize = takecnt; + Control.SBSize = 1; // 4 bytes + Control.DBSize = 1; // 4 bytes + Control.SWidth = txwidth; + Control.DWidth = txwidth; + Control.reserved1 = 0; + Control.SI = false; + Control.DI = false; + Control.Prot1 = 0; + Control.Prot2 = 0; + Control.Prot3 = 0; + Control.I = false; + + LPCHelpers::dwrite(DMACC.Control, Control); + + curoff += takecnt; + + // Kick off the DMA. + DMACC.Config.E = true; + spi_monitored_loop syncdmaw; + while (DMACC.Config.E) { syncdmaw.update(12); /* wait for the DMA TX to finish */ } } - #endif // !HALSPI_DISABLE_DMA + // Disable DMA on the SSP. + SSP.DMACR.TXDMAE = false; - #ifndef HALSPI_DMA_THRESHOLD - // The amount of transfer units (either 8bit or 16bit numbers) that have to be overshot to trigger a DMA - // operation. Sometimes it is impractical to perform DMA due to MCU design limitations. - #define HALSPI_DMA_THRESHOLD 32 - #endif // !HALSPI_DMA_THRESHOLD + _ssp_dirty_rxbuffer = true; + } - void spiWrite(const uint8_t *buf, uint16_t cnt) { - if (cnt == 0) return; - if (_ssp_gpioMap.gpio_mosi < 0) return; +#endif // !HALSPI_DISABLE_DMA - _spiSetFrameSize(sizeof(uint8_t)); +#ifndef HALSPI_DMA_THRESHOLD + // The amount of transfer units (either 8bit or 16bit numbers) that have to be overshot to trigger a DMA + // operation. Sometimes it is impractical to perform DMA due to MCU design limitations. + #define HALSPI_DMA_THRESHOLD 32 +#endif // !HALSPI_DMA_THRESHOLD - _maybe_start_transaction(); +void spiWrite(const uint8_t *buf, uint16_t cnt) { + if (cnt == 0) return; + if (_ssp_gpioMap.gpio_mosi < 0) return; - _spiAsyncBarrier(); + _spiSetFrameSize(sizeof(uint8_t)); - #ifndef HALSPI_DISABLE_DMA - // The LPC176x does only support DMA transfer using MSBFIRST bitorder. - // For LSBFIRST we must unfortunately fall back to the (slower) generic SPI. - if (_ssp_bitOrder == SPI_BITORDER_MSB && cnt > HALSPI_DMA_THRESHOLD) { - _dmaStart(); - _dmaSendBlocking(buf, cnt); - _dmaEnd(); - return; - } - #endif + _maybe_start_transaction(); - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); + _spiAsyncBarrier(); + + #ifndef HALSPI_DISABLE_DMA + // The LPC176x does only support DMA transfer using MSBFIRST bitorder. + // For LSBFIRST we must unfortunately fall back to the (slower) generic SPI. + if (_ssp_bitOrder == SPI_BITORDER_MSB && cnt > HALSPI_DMA_THRESHOLD) { + _dmaStart(); + _dmaSendBlocking(buf, cnt); + _dmaEnd(); + return; + } + #endif - for (uint16_t n = 0; n < cnt; n++) _spi_push_to_queue(SSP, buf[n]); + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - _ssp_dirty_rxbuffer = true; - } + for (uint16_t n = 0; n < cnt; n++) _spi_push_to_queue(SSP, buf[n]); - void spiWrite16(const uint16_t *buf, uint16_t cnt) { - if (cnt == 0) return; - if (_ssp_gpioMap.gpio_mosi < 0) return; + _ssp_dirty_rxbuffer = true; +} - _spiSetFrameSize(sizeof(uint16_t)); +void spiWrite16(const uint16_t *buf, uint16_t cnt) { + if (cnt == 0) return; + if (_ssp_gpioMap.gpio_mosi < 0) return; - _maybe_start_transaction(); + _spiSetFrameSize(sizeof(uint16_t)); - _spiAsyncBarrier(); + _maybe_start_transaction(); - #ifndef HALSPI_DISABLE_DMA - // The LPC176x does only support DMA transfer using MSBFIRST bitorder. - // For LSBFIRST we must unfortunately fall back to the (slower) generic SPI. - if (_ssp_bitOrder == SPI_BITORDER_MSB && cnt > HALSPI_DMA_THRESHOLD) { - _dmaStart(); - _dmaSendBlocking(buf, cnt); - _dmaEnd(); - return; - } - #endif + _spiAsyncBarrier(); - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); + #ifndef HALSPI_DISABLE_DMA + // The LPC176x does only support DMA transfer using MSBFIRST bitorder. + // For LSBFIRST we must unfortunately fall back to the (slower) generic SPI. + if (_ssp_bitOrder == SPI_BITORDER_MSB && cnt > HALSPI_DMA_THRESHOLD) { + _dmaStart(); + _dmaSendBlocking(buf, cnt); + _dmaEnd(); + return; + } + #endif - for (uint16_t n = 0; n < cnt; n++) _spi_push_to_queue(SSP, buf[n]); + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - _ssp_dirty_rxbuffer = true; - } + for (uint16_t n = 0; n < cnt; n++) _spi_push_to_queue(SSP, buf[n]); - void spiWriteRepeat(uint8_t val, uint16_t repcnt) { - if (repcnt == 0) return; - if (_ssp_gpioMap.gpio_mosi < 0) return; + _ssp_dirty_rxbuffer = true; +} - _spiSetFrameSize(sizeof(uint8_t)); +void spiWriteRepeat(uint8_t val, uint16_t repcnt) { + if (repcnt == 0) return; + if (_ssp_gpioMap.gpio_mosi < 0) return; - _maybe_start_transaction(); + _spiSetFrameSize(sizeof(uint8_t)); - _spiAsyncBarrier(); + _maybe_start_transaction(); - #ifndef HALSPI_DISABLE_DMA - if (repcnt > HALSPI_DMA_THRESHOLD) { - _dmaStart(); - _dmaSendRepeatBlocking(val, repcnt); - _dmaEnd(); - return; - } - #endif + _spiAsyncBarrier(); - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); + #ifndef HALSPI_DISABLE_DMA + if (repcnt > HALSPI_DMA_THRESHOLD) { + _dmaStart(); + _dmaSendRepeatBlocking(val, repcnt); + _dmaEnd(); + return; + } + #endif - for (uint16_t n = 0; n < repcnt; n++) _spi_push_to_queue(SSP, val); + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - _ssp_dirty_rxbuffer = true; - } + for (uint16_t n = 0; n < repcnt; n++) _spi_push_to_queue(SSP, val); - void spiWriteRepeat16(uint16_t val, uint16_t repcnt) { - if (repcnt == 0) return; - if (_ssp_gpioMap.gpio_mosi < 0) return; + _ssp_dirty_rxbuffer = true; +} - _spiSetFrameSize(sizeof(uint16_t)); +void spiWriteRepeat16(uint16_t val, uint16_t repcnt) { + if (repcnt == 0) return; + if (_ssp_gpioMap.gpio_mosi < 0) return; - _maybe_start_transaction(); + _spiSetFrameSize(sizeof(uint16_t)); - _spiAsyncBarrier(); + _maybe_start_transaction(); - #ifndef HALSPI_DISABLE_DMA - if (repcnt > HALSPI_DMA_THRESHOLD) { - _dmaStart(); - _dmaSendRepeatBlocking(val, repcnt); - _dmaEnd(); - return; - } - #endif + _spiAsyncBarrier(); - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); + #ifndef HALSPI_DISABLE_DMA + if (repcnt > HALSPI_DMA_THRESHOLD) { + _dmaStart(); + _dmaSendRepeatBlocking(val, repcnt); + _dmaEnd(); + return; + } + #endif - for (uint16_t n = 0; n < repcnt; n++) _spi_push_to_queue(SSP, val); + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - _ssp_dirty_rxbuffer = true; - } + for (uint16_t n = 0; n < repcnt; n++) _spi_push_to_queue(SSP, val); - #ifdef HAL_SPI_SUPPORTS_ASYNC + _ssp_dirty_rxbuffer = true; +} - #ifndef HALSPI_DISABLE_DMA +#ifdef HAL_SPI_SUPPORTS_ASYNC + + #ifndef HALSPI_DISABLE_DMA - static void _dmaUninstallInterrupt(); + static void _dmaUninstallInterrupt(); - static void _dmacAdvance(volatile MarlinLPC::dma_process_t &proc) { - // If there is any last chain that was used then clear it. - if (auto *last_chain = proc.last_chain) { - volatile MarlinLPC::DMACCxLLI_desc_user_t *iter = last_chain; + static void _dmacAdvance(volatile MarlinLPC::dma_process_t &proc) { + // If there is any last chain that was used then clear it. + if (auto *last_chain = proc.last_chain) { + volatile MarlinLPC::DMACCxLLI_desc_user_t *iter = last_chain; - while (iter) { - iter->available = true; - iter = (volatile MarlinLPC::DMACCxLLI_desc_user_t*)iter->Next; - } - proc.last_chain = nullptr; + while (iter) { + iter->available = true; + iter = (volatile MarlinLPC::DMACCxLLI_desc_user_t*)iter->Next; } + proc.last_chain = nullptr; + } - auto &DMACC = *proc.current_DMACC; + auto &DMACC = *proc.current_DMACC; - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - if (proc.curoff == proc.txlen) { - // Disable the SSP DMA TX. - SSP.DMACR.TXDMAE = false; + if (proc.curoff == proc.txlen) { + // Disable the SSP DMA TX. + SSP.DMACR.TXDMAE = false; - // Disable the terminal count interrupt. - DMACC.Control.I = false; - DMACC.Config.ITC = false; + // Disable the terminal count interrupt. + DMACC.Control.I = false; + DMACC.Config.ITC = false; - _dmaUninstallInterrupt(); - _dmaEnd(); + _dmaUninstallInterrupt(); + _dmaEnd(); - auto completeCallback = proc.completeCallback; - void *complete_ud = proc.complete_ud; + auto completeCallback = proc.completeCallback; + void *complete_ud = proc.complete_ud; - // Finished. - proc.current_DMACC = nullptr; - proc.current_buffer = nullptr; - proc.curoff = 0; - proc.txlen = 0; - proc.txunitsize = 0; - proc.completeCallback = nullptr; - proc.complete_ud = nullptr; - proc.is_active = false; + // Finished. + proc.current_DMACC = nullptr; + proc.current_buffer = nullptr; + proc.curoff = 0; + proc.txlen = 0; + proc.txunitsize = 0; + proc.completeCallback = nullptr; + proc.complete_ud = nullptr; + proc.is_active = false; - _ssp_dirty_rxbuffer = true; + _ssp_dirty_rxbuffer = true; - if (completeCallback) { - completeCallback(complete_ud); - } - return; + if (completeCallback) { + completeCallback(complete_ud); } + return; + } - MarlinLPC::DMAProgramSSPChain(SSP, proc); + MarlinLPC::DMAProgramSSPChain(SSP, proc); - // Kick-off another async TX. - DMACC.Config.E = true; - } + // Kick-off another async TX. + DMACC.Config.E = true; + } - static void __attribute__((interrupt)) _dma_interrupt() { - for (uint8_t n = 0; n < 8; n++) { - uint32_t chmask = (1< - inline void _dmaSendAsync(const numberType *buf, uint32_t cnt, void (*completeCallback)(void*), void *ud) { - auto &DMACC = MarlinLPC::DMAGetChannel(0); + static void _dmaUninstallInterrupt() { + NVIC_SetPriority((IRQn_Type)26, 255); + NVIC_DisableIRQ((IRQn_Type)26); + nvicUninstallRedirect(); + nvicResetIRQHandler((IRQn_Type)26); + } - auto &proc = MarlinLPC::_dma_async_proc; - proc.current_DMACC = &DMACC; - proc.current_buffer = buf; - proc.curoff = 0; - proc.txlen = cnt; - proc.txunitsize = sizeof(numberType); - proc.completeCallback = completeCallback; - proc.complete_ud = ud; - proc.last_chain = nullptr; - proc.is_active = true; - - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - - _dmaStart(); - MarlinLPC::DMACIntTCClear.IntTCClear |= (1<<0); // clear pending interrupts. - _dmaInstallInterrupt(); - _dmacInitSSP(DMACC, _ssp_gpioMap.sspBusIdx); - // Enable the TX DMA on the SSP side. - SSP.DMACR.TXDMAE = true; - SSP.DMACR.RXDMAE = false; - _dmacAdvance(proc); - } + template + inline void _dmaSendAsync(const numberType *buf, uint32_t cnt, void (*completeCallback)(void*), void *ud) { + auto &DMACC = MarlinLPC::DMAGetChannel(0); - #endif // !HALSPI_DISABLE_DMA + auto &proc = MarlinLPC::_dma_async_proc; + proc.current_DMACC = &DMACC; + proc.current_buffer = buf; + proc.curoff = 0; + proc.txlen = cnt; + proc.txunitsize = sizeof(numberType); + proc.completeCallback = completeCallback; + proc.complete_ud = ud; + proc.last_chain = nullptr; + proc.is_active = true; - #include "../shared/SPI/bufmgmt.h" + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - static void _spiDisableInterrupt(uint8_t sspBusIdx); + _dmaStart(); + MarlinLPC::DMACIntTCClear.IntTCClear |= (1<<0); // clear pending interrupts. + _dmaInstallInterrupt(); + _dmacInitSSP(DMACC, _ssp_gpioMap.sspBusIdx); + // Enable the TX DMA on the SSP side. + SSP.DMACR.TXDMAE = true; + SSP.DMACR.RXDMAE = false; + _dmacAdvance(proc); + } - template - inline void _spi_interrupt( void ) { - auto &SSP = MarlinLPC::SPIGetBusFromIndex(sspBusIdx); + #endif // !HALSPI_DISABLE_DMA - ssp_process_t &proc = _ssp_async_proc; + #include "../shared/SPI/bufmgmt.h" - if (!proc.is_active || proc.current_ssp != &SSP) - _spi_on_error(3); + static void _spiDisableInterrupt(uint8_t sspBusIdx); - using namespace ::bufmgmt; + template + inline void _spi_interrupt( void ) { + auto &SSP = MarlinLPC::SPIGetBusFromIndex(sspBusIdx); - // Check interrupt type. - if (SSP.MIS.TXMIS) { - bool revbits = (_ssp_bitOrder == SPI_BITORDER_LSB); - bool revbytes = (_ssp_bitOrder == SPI_BITORDER_MSB); + ssp_process_t &proc = _ssp_async_proc; - uint8_t txunitsize = proc.txunitsize; - size_t txmax = proc.txlen_bytes; - const void *current_buffer = proc.current_buffer; - uint8_t framesize = _ssp_framesize; + if (!proc.is_active || proc.current_ssp != &SSP) + _spi_on_error(3); - uint32_t curoff_bytes = proc.curoff_bytes; + using namespace ::bufmgmt; - // Write as much data as possible. - while (SSP.SR.TNF) { - bool has_more_data = false; + // Check interrupt type. + if (SSP.MIS.TXMIS) { + bool revbits = (_ssp_bitOrder == SPI_BITORDER_LSB); + bool revbytes = (_ssp_bitOrder == SPI_BITORDER_MSB); - if (framesize == 1) { - uint8_t byteval; - if (txunitsize == 1) { - if (curoff_bytes < txmax) { - const uint8_t *buf = (const uint8_t*)current_buffer; - byteval = GetByteFromNumber( - buf[ GetNumberIndexFromTotalByteIndex (curoff_bytes) ], - GetLocalByteIndexFromTotalByteIndex (curoff_bytes), - !revbytes - ); - has_more_data = true; - } + uint8_t txunitsize = proc.txunitsize; + size_t txmax = proc.txlen_bytes; + const void *current_buffer = proc.current_buffer; + uint8_t framesize = _ssp_framesize; + + uint32_t curoff_bytes = proc.curoff_bytes; + + // Write as much data as possible. + while (SSP.SR.TNF) { + bool has_more_data = false; + + if (framesize == 1) { + uint8_t byteval; + if (txunitsize == 1) { + if (curoff_bytes < txmax) { + const uint8_t *buf = (const uint8_t*)current_buffer; + byteval = GetByteFromNumber( + buf[ GetNumberIndexFromTotalByteIndex (curoff_bytes) ], + GetLocalByteIndexFromTotalByteIndex (curoff_bytes), + !revbytes + ); + has_more_data = true; } - else if (txunitsize == 2) { - if (curoff_bytes < txmax) { - const uint16_t *buf = (const uint16_t*)current_buffer; - byteval = GetByteFromNumber( - buf[ GetNumberIndexFromTotalByteIndex (curoff_bytes) ], - GetLocalByteIndexFromTotalByteIndex (curoff_bytes), - !revbytes - ); - has_more_data = true; - } + } + else if (txunitsize == 2) { + if (curoff_bytes < txmax) { + const uint16_t *buf = (const uint16_t*)current_buffer; + byteval = GetByteFromNumber( + buf[ GetNumberIndexFromTotalByteIndex (curoff_bytes) ], + GetLocalByteIndexFromTotalByteIndex (curoff_bytes), + !revbytes + ); + has_more_data = true; } + } - if (has_more_data) { - if (revbits) { - byteval = _flip_bits(byteval); - } + if (has_more_data) { + if (revbits) byteval = _flip_bits(byteval); - // Push the data onto the (not-full) queue, byte-by-byte (DSS = 7). - SSP.DR.DATA = byteval; + // Push the data onto the (not-full) queue, byte-by-byte (DSS = 7). + SSP.DR.DATA = byteval; - curoff_bytes += sizeof(uint8_t); - } + curoff_bytes += sizeof(uint8_t); } - else if (framesize == 2) { - uint16_t val; - if (txunitsize == 2) { - if (curoff_bytes < txmax) { - const uint16_t *buf = (const uint16_t*)current_buffer; - val = buf[ curoff_bytes / sizeof(uint16_t) ]; - has_more_data = true; - } + } + else if (framesize == 2) { + uint16_t val; + if (txunitsize == 2) { + if (curoff_bytes < txmax) { + const uint16_t *buf = (const uint16_t*)current_buffer; + val = buf[ curoff_bytes / sizeof(uint16_t) ]; + has_more_data = true; } + } - if (has_more_data) { - if (revbits) { - val = _flip_bits(val); - } + if (has_more_data) { + if (revbits) val = _flip_bits(val); - SSP.DR.DATA = val; + SSP.DR.DATA = val; - curoff_bytes += sizeof(uint16_t); - } + curoff_bytes += sizeof(uint16_t); } + } - if (has_more_data) { - // We are ignoring the reception part. - _ssp_dirty_rxbuffer = true; - } - else { - // Disable the interrupt. - _spiDisableInterrupt(sspBusIdx); - - SSP.IMSC.TXIM = false; - - auto completeCallback = proc.completeCallback; - auto complete_ud = proc.complete_ud; - - // We have finished the transfer, thus dismantle. - proc.current_ssp = nullptr; - proc.current_buffer = nullptr; - proc.curoff_bytes = 0; - proc.txlen_bytes = 0; - proc.txunitsize = 0; - proc.completeCallback = nullptr; - proc.complete_ud = nullptr; - proc.is_active = false; - - // Call any completion routine. - if (completeCallback) { - completeCallback(complete_ud); - } + if (has_more_data) { + // We are ignoring the reception part. + _ssp_dirty_rxbuffer = true; + } + else { + // Disable the interrupt. + _spiDisableInterrupt(sspBusIdx); + + SSP.IMSC.TXIM = false; + + auto completeCallback = proc.completeCallback; + auto complete_ud = proc.complete_ud; + + // We have finished the transfer, thus dismantle. + proc.current_ssp = nullptr; + proc.current_buffer = nullptr; + proc.curoff_bytes = 0; + proc.txlen_bytes = 0; + proc.txunitsize = 0; + proc.completeCallback = nullptr; + proc.complete_ud = nullptr; + proc.is_active = false; - goto finished; + // Call any completion routine. + if (completeCallback) { + completeCallback(complete_ud); } - } - // Save progress. - proc.curoff_bytes = curoff_bytes; - finished:; + goto finished; + } } + // Save progress. + proc.curoff_bytes = curoff_bytes; + + finished:; } + } + + static void __attribute__((interrupt)) _spi_interrupt_sspbus0() { + _spi_interrupt <0> (); + } + static void __attribute__((interrupt)) _spi_interrupt_sspbus1() { + _spi_interrupt <1> (); + } - static void __attribute__((interrupt)) _spi_interrupt_sspbus0() { - _spi_interrupt <0> (); + static void _spiEnableInterrupt(uint8_t sspBusIdx) { + if (sspBusIdx == 0) { + nvicSetIRQHandler((IRQn_Type)14, _spi_interrupt_sspbus0); + } + else if (sspBusIdx == 1) { + nvicSetIRQHandler((IRQn_Type)15, _spi_interrupt_sspbus1); } - static void __attribute__((interrupt)) _spi_interrupt_sspbus1() { - _spi_interrupt <1> (); + nvicInstallRedirect(); + if (sspBusIdx == 0) { + NVIC_EnableIRQ((IRQn_Type)14); + NVIC_SetPriority((IRQn_Type)14, 5); + } + else if (sspBusIdx == 1) { + NVIC_EnableIRQ((IRQn_Type)15); + NVIC_SetPriority((IRQn_Type)15, 5); } + } - static void _spiEnableInterrupt(uint8_t sspBusIdx) { - if (sspBusIdx == 0) { - nvicSetIRQHandler((IRQn_Type)14, _spi_interrupt_sspbus0); - } - else if (sspBusIdx == 1) { - nvicSetIRQHandler((IRQn_Type)15, _spi_interrupt_sspbus1); - } - nvicInstallRedirect(); - if (sspBusIdx == 0) { - NVIC_EnableIRQ((IRQn_Type)14); - NVIC_SetPriority((IRQn_Type)14, 5); - } - else if (sspBusIdx == 1) { - NVIC_EnableIRQ((IRQn_Type)15); - NVIC_SetPriority((IRQn_Type)15, 5); - } + static void _spiDisableInterrupt(uint8_t sspBusIdx) { + if (sspBusIdx == 0) { + NVIC_SetPriority((IRQn_Type)14, 255); + NVIC_DisableIRQ((IRQn_Type)14); + } + else if (sspBusIdx == 1) { + NVIC_SetPriority((IRQn_Type)15, 255); + NVIC_DisableIRQ((IRQn_Type)15); } + nvicUninstallRedirect(); + if (sspBusIdx == 0) { + nvicResetIRQHandler((IRQn_Type)14); + } + else if (sspBusIdx == 1) { + nvicResetIRQHandler((IRQn_Type)15); + } + } - static void _spiDisableInterrupt(uint8_t sspBusIdx) { - if (sspBusIdx == 0) { - NVIC_SetPriority((IRQn_Type)14, 255); - NVIC_DisableIRQ((IRQn_Type)14); - } - else if (sspBusIdx == 1) { - NVIC_SetPriority((IRQn_Type)15, 255); - NVIC_DisableIRQ((IRQn_Type)15); - } - nvicUninstallRedirect(); - if (sspBusIdx == 0) { - nvicResetIRQHandler((IRQn_Type)14); - } - else if (sspBusIdx == 1) { - nvicResetIRQHandler((IRQn_Type)15); + template + static void _spiStartAsyncTX(const numberType *buf, uint16_t cnt, void (*completeCallback)(void*), void *ud) { + auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); + + // Start the async process. + auto &proc = _ssp_async_proc; + proc.current_ssp = &SSP; + proc.current_buffer = buf; + proc.curoff_bytes = 0; + proc.txlen_bytes = cnt * sizeof(numberType); + proc.txunitsize = sizeof(numberType); + proc.completeCallback = completeCallback; + proc.complete_ud = ud; + proc.is_active = true; + + // Register the interrupt. + _spiEnableInterrupt(_ssp_gpioMap.sspBusIdx); + + // Enable the interrupt. This should kick it off. + SSP.IMSC.TXIM = true; + } + + void spiWriteAsync(const uint8_t *buf, uint16_t cnt, void (*completeCallback)(void*), void *ud) { + if (cnt == 0 || _ssp_gpioMap.gpio_mosi < 0) { + if (completeCallback) { + completeCallback(ud); } + return; } - template - static void _spiStartAsyncTX(const numberType *buf, uint16_t cnt, void (*completeCallback)(void*), void *ud) { - auto &SSP = MarlinLPC::SPIGetBusFromIndex(_ssp_gpioMap.sspBusIdx); - - // Start the async process. - auto &proc = _ssp_async_proc; - proc.current_ssp = &SSP; - proc.current_buffer = buf; - proc.curoff_bytes = 0; - proc.txlen_bytes = cnt * sizeof(numberType); - proc.txunitsize = sizeof(numberType); - proc.completeCallback = completeCallback; - proc.complete_ud = ud; - proc.is_active = true; + _spiSetFrameSize(sizeof(uint8_t)); - // Register the interrupt. - _spiEnableInterrupt(_ssp_gpioMap.sspBusIdx); + _maybe_start_transaction(); - // Enable the interrupt. This should kick it off. - SSP.IMSC.TXIM = true; - } + _spiAsyncBarrier(); - void spiWriteAsync(const uint8_t *buf, uint16_t cnt, void (*completeCallback)(void*), void *ud) { - if (cnt == 0 || _ssp_gpioMap.gpio_mosi < 0) { - if (completeCallback) { - completeCallback(ud); - } + #ifndef HALSPI_DISABLE_DMA + // The LPC176x DMAC does only support MSBFIRST bit-order, thus we have to assert that. + // Otherwise must fall back to async SPI using interrupts. + if (_ssp_bitOrder == SPI_BITORDER_MSB && cnt > HALSPI_DMA_THRESHOLD) { + _dmaSendAsync(buf, cnt, completeCallback, ud); return; } + #endif - _spiSetFrameSize(sizeof(uint8_t)); + _spiStartAsyncTX(buf, cnt, completeCallback, ud); + } - _maybe_start_transaction(); + void spiWriteAsync16(const uint16_t *buf, uint16_t cnt, void (*completeCallback)(void*), void *ud) { + if (cnt == 0 || _ssp_gpioMap.gpio_mosi < 0) { + if (completeCallback) completeCallback(ud); + return; + } - _spiAsyncBarrier(); + _spiSetFrameSize(sizeof(uint16_t)); - #ifndef HALSPI_DISABLE_DMA - // The LPC176x DMAC does only support MSBFIRST bit-order, thus we have to assert that. - // Otherwise must fall back to async SPI using interrupts. - if (_ssp_bitOrder == SPI_BITORDER_MSB && cnt > HALSPI_DMA_THRESHOLD) { - _dmaSendAsync(buf, cnt, completeCallback, ud); - return; - } - #endif + _maybe_start_transaction(); - _spiStartAsyncTX(buf, cnt, completeCallback, ud); - } + _spiAsyncBarrier(); - void spiWriteAsync16(const uint16_t *buf, uint16_t cnt, void (*completeCallback)(void*), void *ud) { - if (cnt == 0 || _ssp_gpioMap.gpio_mosi < 0) { - if (completeCallback) completeCallback(ud); + #ifndef HALSPI_DISABLE_DMA + // The LPC176x DMAC does only support MSBFIRST bit-order, thus we have to assert that. + // Otherwise must fall back to async SPI using interrupts. + if (_ssp_bitOrder == SPI_BITORDER_MSB && cnt > HALSPI_DMA_THRESHOLD) { + _dmaSendAsync(buf, cnt, completeCallback, ud); return; } + #endif - _spiSetFrameSize(sizeof(uint16_t)); - - _maybe_start_transaction(); - - _spiAsyncBarrier(); - - #ifndef HALSPI_DISABLE_DMA - // The LPC176x DMAC does only support MSBFIRST bit-order, thus we have to assert that. - // Otherwise must fall back to async SPI using interrupts. - if (_ssp_bitOrder == SPI_BITORDER_MSB && cnt > HALSPI_DMA_THRESHOLD) { - _dmaSendAsync(buf, cnt, completeCallback, ud); - return; - } - #endif - - _spiStartAsyncTX(buf, cnt, completeCallback, ud); - } - - void spiAsyncAbort() { - cli(); - { - auto &proc = _ssp_async_proc; + _spiStartAsyncTX(buf, cnt, completeCallback, ud); + } - if (proc.is_active) { - auto &SSP = *proc.current_ssp; + void spiAsyncAbort() { + cli(); + { + auto &proc = _ssp_async_proc; - // Disable the interrupt processing. - SSP.IMSC.TXIM = false; + if (proc.is_active) { + auto &SSP = *proc.current_ssp; - // Unregister the interrupt. - _spiDisableInterrupt(MarlinLPC::SPIGetBusIndex(SSP)); + // Disable the interrupt processing. + SSP.IMSC.TXIM = false; - // Cancel the process. - proc.is_active = false; - } - } - #ifndef HALSPI_DISABLE_DMA - { - auto &proc = MarlinLPC::_dma_async_proc; + // Unregister the interrupt. + _spiDisableInterrupt(MarlinLPC::SPIGetBusIndex(SSP)); - if (proc.is_active) { - auto &DMACC = *proc.current_DMACC; + // Cancel the process. + proc.is_active = false; + } + } + #ifndef HALSPI_DISABLE_DMA + { + auto &proc = MarlinLPC::_dma_async_proc; - DMACC.Config.H = true; - spi_monitored_loop abw; - while (DMACC.Config.A) { abw.update(9); /* wait until the DMA channel has no more data to process */ } - DMACC.Config.E = false; + if (proc.is_active) { + auto &DMACC = *proc.current_DMACC; - DMACC.Config.ITC = false; - DMACC.Control.I = false; + DMACC.Config.H = true; + spi_monitored_loop abw; + while (DMACC.Config.A) { abw.update(9); /* wait until the DMA channel has no more data to process */ } + DMACC.Config.E = false; - // Cancel the process. - proc.is_active = false; - } - } - #endif + DMACC.Config.ITC = false; + DMACC.Control.I = false; - sei(); + // Cancel the process. + proc.is_active = false; } + } + #endif + + sei(); + } - void spiAsyncJoin() { _spiAsyncBarrier(); } + void spiAsyncJoin() { _spiAsyncBarrier(); } - bool spiAsyncIsRunning() { - if (_ssp_async_proc.is_active) return true; - #ifndef HALSPI_DISABLE_DMA - if (MarlinLPC::_dma_async_proc.is_active) return true; - #endif - return false; - } + bool spiAsyncIsRunning() { + if (_ssp_async_proc.is_active) return true; + #ifndef HALSPI_DISABLE_DMA + if (MarlinLPC::_dma_async_proc.is_active) return true; + #endif + return false; + } - #endif // HAL_SPI_SUPPORTS_ASYNC +#endif // HAL_SPI_SUPPORTS_ASYNC #endif // !SOFTWARE_SPI - #endif // TARGET_LPC1768 diff --git a/Marlin/src/HAL/LPC1768/HAL_SPI_SW.cpp b/Marlin/src/HAL/LPC1768/HAL_SPI_SW.cpp index 17a0a109c957..03b9cf1c79b9 100644 --- a/Marlin/src/HAL/LPC1768/HAL_SPI_SW.cpp +++ b/Marlin/src/HAL/LPC1768/HAL_SPI_SW.cpp @@ -1,6 +1,6 @@ /** * Marlin 3D Printer Firmware - * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * Based on Sprinter and grbl. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm @@ -25,7 +25,7 @@ */ /** - * Hardware SPI and Software SPI implementations are included in this file. + * Software SPI * * Control of the slave select pin(s) is handled by the calling routines. * @@ -40,101 +40,82 @@ #include "../../inc/MarlinConfig.h" -#include "../shared/HAL_SPI.h" - -// ------------------------ -// Public functions -// ------------------------ #if ENABLED(SOFTWARE_SPI) - // Software SPI - - #include - - static uint8_t SPI_speed = SPI_FULL_SPEED; - static int _spi_bit_order = SPI_BITORDER_DEFAULT; - static int _spi_sck_pin, _spi_miso_pin, _spi_mosi_pin; - static int _spi_cs_pin; - - static uint8_t spiTransfer(uint8_t b) { - return swSpiTransfer(b, SPI_speed, _spi_sck_pin, _spi_miso_pin, _spi_mosi_pin); - } - - void spiBegin() { - //swSpiBegin(SD_SCK_PIN, SD_MISO_PIN, SD_MOSI_PIN); - } - - void spiSetupChipSelect(int pin) { - OUT_WRITE(pin, HIGH); - } - - void spiInit(uint8_t spiRate, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { - int use_sck = ( ( hint_sck >= 0 ) ? hint_sck : SD_SCK_PIN ); - int use_miso = ( ( hint_miso >= 0 ) ? hint_miso : SD_MISO_PIN ); - int use_mosi = ( ( hint_mosi >= 0 ) ? hint_mosi : SD_MOSI_PIN ); - _spi_sck_pin = use_sck; - _spi_miso_pin = use_miso; - _spi_mosi_pin = use_mosi; - swSpiBegin(use_sck, use_miso, use_mosi); - SPI_speed = swSpiInit(spiRate, use_sck, use_mosi); - _spi_bit_order = SPI_BITORDER_DEFAULT; - _spi_cs_pin = hint_cs; - if (hint_cs >= 0) - OUT_WRITE(hint_cs, LOW); - } - - void spiInitEx(uint32_t maxClockFreq, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { - // Use datarates Marlin uses - uint8_t spiRate; - if (maxClockFreq >= 20000000) { - spiRate = SPI_FULL_SPEED; - } - else if (maxClockFreq >= 5000000) { - spiRate = SPI_HALF_SPEED; - } - else if (maxClockFreq >= 2500000) { - spiRate = SPI_QUARTER_SPEED; - } - else if (maxClockFreq >= 1250000) { - spiRate = SPI_EIGHTH_SPEED; - } - else if (maxClockFreq >= 625000) { - spiRate = SPI_SPEED_5; - } - else if (maxClockFreq >= 300000) { - spiRate = SPI_SPEED_6; - } - else - spiRate = SPI_SPEED_6; - - spiInit(spiRate, hint_sck, hint_miso, hint_mosi, hint_cs); - } - - void spiClose() { - if (_spi_cs_pin >= 0) - OUT_WRITE(_spi_cs_pin, HIGH); - } - - static inline uint8_t _flip_bits_8(uint8_t v) { - uint8_t result = 0; - for (int n = 0; n < 8; n++) - { - result <<= 1; - bool bitval = ( v & ( 1 << n ) ) != 0; - result |= bitval; - } - return result; - } - - void spiSetBitOrder(int bitOrder) { - _spi_bit_order = bitOrder; - } +#include "../shared/HAL_SPI.h" - void spiSetClockMode(int mode) { - if (mode != SPI_CLKMODE_0) { - // FATAL ERROR: not supported. - while (true) { -#if ENABLED(HALSPI_DO_ERRORBEEPS) && PIN_EXISTS(BEEPER) +#include + +static uint8_t SPI_speed = SPI_FULL_SPEED; +static int _spi_bit_order = SPI_BITORDER_DEFAULT; +static int _spi_sck_pin, _spi_miso_pin, _spi_mosi_pin; +static int _spi_cs_pin; + +static uint8_t spiTransfer(uint8_t b) { + return swSpiTransfer(b, SPI_speed, _spi_sck_pin, _spi_miso_pin, _spi_mosi_pin); +} + +void spiBegin() { + //swSpiBegin(SD_SCK_PIN, SD_MISO_PIN, SD_MOSI_PIN); +} + +void spiSetupChipSelect(int pin) { + OUT_WRITE(pin, HIGH); +} + +void spiInit(uint8_t spiRate, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { + int use_sck = ( ( hint_sck >= 0 ) ? hint_sck : SD_SCK_PIN ); + int use_miso = ( ( hint_miso >= 0 ) ? hint_miso : SD_MISO_PIN ); + int use_mosi = ( ( hint_mosi >= 0 ) ? hint_mosi : SD_MOSI_PIN ); + _spi_sck_pin = use_sck; + _spi_miso_pin = use_miso; + _spi_mosi_pin = use_mosi; + swSpiBegin(use_sck, use_miso, use_mosi); + SPI_speed = swSpiInit(spiRate, use_sck, use_mosi); + _spi_bit_order = SPI_BITORDER_DEFAULT; + _spi_cs_pin = hint_cs; + if (hint_cs >= 0) + OUT_WRITE(hint_cs, LOW); +} + +void spiInitEx(uint32_t maxClockFreq, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { + // Use Marlin datarates + uint8_t spiRate; + if (maxClockFreq >= 20000000) spiRate = SPI_FULL_SPEED; + else if (maxClockFreq >= 5000000) spiRate = SPI_HALF_SPEED; + else if (maxClockFreq >= 2500000) spiRate = SPI_QUARTER_SPEED; + else if (maxClockFreq >= 1250000) spiRate = SPI_EIGHTH_SPEED; + else if (maxClockFreq >= 625000) spiRate = SPI_SPEED_5; + else if (maxClockFreq >= 300000) spiRate = SPI_SPEED_6; + else spiRate = SPI_SPEED_6; + + spiInit(spiRate, hint_sck, hint_miso, hint_mosi, hint_cs); +} + +void spiClose() { + if (_spi_cs_pin >= 0) + OUT_WRITE(_spi_cs_pin, HIGH); +} + +static inline uint8_t _flip_bits_8(uint8_t v) { + uint8_t result = 0; + for (int n = 0; n < 8; n++) { + result <<= 1; + bool bitval = ( v & ( 1 << n ) ) != 0; + result |= bitval; + } + return result; +} + +void spiSetBitOrder(int bitOrder) { + _spi_bit_order = bitOrder; +} + +void spiSetClockMode(int mode) { + if (mode != SPI_CLKMODE_0) { + // FATAL ERROR: not supported. + for (;;) { + #if ENABLED(HALSPI_DO_ERRORBEEPS) && PIN_EXISTS(BEEPER) OUT_WRITE(BEEPER_PIN, HIGH); delay(500); OUT_WRITE(BEEPER_PIN, LOW); @@ -155,76 +136,76 @@ delay(1000); OUT_WRITE(BEEPER_PIN, LOW); delay(2000); -#endif - } + #endif } } +} - void spiEstablish() { /* do nothing */ } - - uint8_t spiRec(uint8_t txval) { return (_spi_bit_order == SPI_BITORDER_MSB) ? spiTransfer(txval) : _flip_bits_8(spiTransfer(_flip_bits_8(txval))); } +void spiEstablish() { /* do nothing */ } - uint16_t spiRec16(uint16_t txval) { - bool msb = (_spi_bit_order == SPI_BITORDER_MSB); - uint8_t tx_first, tx_second; - if (msb) { - tx_first = ( txval >> 8 ); - tx_second = ( txval & 0xFF ); - } - else { - tx_first = ( txval & 0xFF ); - tx_second = ( txval >> 8 ); - } +uint8_t spiRec(uint8_t txval) { return (_spi_bit_order == SPI_BITORDER_MSB) ? spiTransfer(txval) : _flip_bits_8(spiTransfer(_flip_bits_8(txval))); } - uint16_t v = ( msb ? ( (uint16_t)spiRec(tx_first) << 8 ) : spiRec(tx_first) ); - v |= ( msb ? spiRec(tx_second) : ( (uint16_t)spiRec(tx_second) << 8 ) ); - return v; +uint16_t spiRec16(uint16_t txval) { + bool msb = (_spi_bit_order == SPI_BITORDER_MSB); + uint8_t tx_first, tx_second; + if (msb) { + tx_first = txval >> 8; + tx_second = txval & 0xFF; } - - void spiRead(uint8_t*buf, uint16_t nbyte, uint8_t txval) { - for (int i = 0; i < nbyte; i++) - buf[i] = spiRec(txval); + else { + tx_first = txval & 0xFF; + tx_second = txval >> 8; } - void spiSend(uint8_t b) { (void)spiTransfer((_spi_bit_order == SPI_BITORDER_MSB) ? b : _flip_bits_8(b)); } + uint16_t v = ( msb ? ( (uint16_t)spiRec(tx_first) << 8 ) : spiRec(tx_first) ); + v |= ( msb ? spiRec(tx_second) : ( (uint16_t)spiRec(tx_second) << 8 ) ); + return v; +} - void spiSend16(uint16_t v) { - bool msb = (_spi_bit_order == SPI_BITORDER_MSB); - spiSend(msb ? (v >> 8) : (v&0xFF)); - spiSend(msb ? (v&0xFF) : (v >> 8)); - } +void spiRead(uint8_t*buf, uint16_t nbyte, uint8_t txval) { + for (int i = 0; i < nbyte; i++) + buf[i] = spiRec(txval); +} - void spiSend(const uint8_t *buf, size_t nbyte) { - for (uint16_t i = 0; i < nbyte; i++) - spiSend(buf[i]); - } +void spiSend(uint8_t b) { (void)spiTransfer((_spi_bit_order == SPI_BITORDER_MSB) ? b : _flip_bits_8(b)); } - void spiSendBlock(uint8_t token, const uint8_t *buf) { - spiSend(token); - for (uint16_t i = 0; i < 512; i++) - spiSend(buf[i]); - } +void spiSend16(uint16_t v) { + bool msb = (_spi_bit_order == SPI_BITORDER_MSB); + spiSend(msb ? (v >> 8) : (v&0xFF)); + spiSend(msb ? (v&0xFF) : (v >> 8)); +} - void spiWrite(const uint8_t *buf, uint16_t cnt) { - for (uint16_t n = 0; n < cnt; n++) - spiSend(buf[n]); - } +void spiSend(const uint8_t *buf, size_t nbyte) { + for (uint16_t i = 0; i < nbyte; i++) + spiSend(buf[i]); +} - void spiWrite16(const uint16_t *buf, uint16_t cnt) { - for (uint16_t n = 0; n < cnt; n++) - spiSend16(buf[n]); - } +void spiSendBlock(uint8_t token, const uint8_t *buf) { + spiSend(token); + for (uint16_t i = 0; i < 512; i++) + spiSend(buf[i]); +} - void spiWriteRepeat(uint8_t val, uint16_t repcnt) { - for (uint16_t n = 0; n < repcnt; n++) - spiSend(val); - } +void spiWrite(const uint8_t *buf, uint16_t cnt) { + for (uint16_t n = 0; n < cnt; n++) + spiSend(buf[n]); +} - void spiWriteRepeat16(uint16_t val, uint16_t repcnt) { - for (uint16_t n = 0; n < repcnt; n++) - spiSend16(val); - } +void spiWrite16(const uint16_t *buf, uint16_t cnt) { + for (uint16_t n = 0; n < cnt; n++) + spiSend16(buf[n]); +} + +void spiWriteRepeat(uint8_t val, uint16_t repcnt) { + for (uint16_t n = 0; n < repcnt; n++) + spiSend(val); +} + +void spiWriteRepeat16(uint16_t val, uint16_t repcnt) { + for (uint16_t n = 0; n < repcnt; n++) + spiSend16(val); +} -#endif +#endif // SOFTWARE_SPI #endif // TARGET_LPC1768 diff --git a/Marlin/src/HAL/NATIVE_SIM/spi_pins.h b/Marlin/src/HAL/NATIVE_SIM/spi_pins.h index 93e420590fec..fd3378b33759 100644 --- a/Marlin/src/HAL/NATIVE_SIM/spi_pins.h +++ b/Marlin/src/HAL/NATIVE_SIM/spi_pins.h @@ -25,7 +25,7 @@ #include "../../inc/MarlinConfigPre.h" #if BOTH(HAS_MARLINUI_U8GLIB, SDSUPPORT) && (LCD_PINS_D4 == SD_SCK_PIN || LCD_PINS_ENABLE == SD_MOSI_PIN || DOGLCD_SCK == SD_SCK_PIN || DOGLCD_MOSI == SD_MOSI_PIN) - #define SOFTWARE_SPI // If the SD card and LCD adapter share the same SPI pins, then software SPI is currently + #define SOFTWARE_SPI // If the SD card and LCD adapter share the same SPI pins, then software SPI is currently // needed due to the speed and mode required for communicating with each device being different. // This requirement can be removed if the SPI access to these devices is updated to use // spiBeginTransaction. diff --git a/Marlin/src/HAL/SAMD21/HAL_SPI.cpp b/Marlin/src/HAL/SAMD21/HAL_SPI.cpp index 0fc530cdb231..69c6a43af835 100644 --- a/Marlin/src/HAL/SAMD21/HAL_SPI.cpp +++ b/Marlin/src/HAL/SAMD21/HAL_SPI.cpp @@ -64,7 +64,7 @@ } void spiInit(uint8_t spiRate) { - // Use datarates Marlin uses + // Use Marlin datarates uint32_t clock; switch (spiRate) { case SPI_FULL_SPEED: clock = 8000000; break; diff --git a/Marlin/src/HAL/SAMD51/HAL_SPI.cpp b/Marlin/src/HAL/SAMD51/HAL_SPI.cpp index 9d040e9f477a..bcf0cc9edd5b 100644 --- a/Marlin/src/HAL/SAMD51/HAL_SPI.cpp +++ b/Marlin/src/HAL/SAMD51/HAL_SPI.cpp @@ -90,7 +90,7 @@ // Ignore all pin hints. if (spiRate == SPI_SPEED_DEFAULT) spiRate = SPI_HALF_SPEED; - // Use datarates Marlin uses + // Use Marlin datarates uint32_t clock; switch (spiRate) { case SPI_FULL_SPEED: clock = 8000000; break; diff --git a/Marlin/src/HAL/STM32/HAL_SPI_HW.cpp b/Marlin/src/HAL/STM32/HAL_SPI_HW.cpp index 75c389f4c8cb..25c3dfa1ecfd 100644 --- a/Marlin/src/HAL/STM32/HAL_SPI_HW.cpp +++ b/Marlin/src/HAL/STM32/HAL_SPI_HW.cpp @@ -1,6 +1,6 @@ /** * Marlin 3D Printer Firmware - * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * Based on Sprinter and grbl. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm @@ -46,8 +46,8 @@ // Public functions // ------------------------ - // If properly ported, use fast HW SPI implementation originally found in STM32 tft_spi.cpp -#if !ENABLED(SOFTWARE_SPI) && (defined(STM32F1xx) || defined(STM32F4xx)) && !ENABLED(HALSPI_HW_GENERIC) +// If properly ported, use fast HW SPI implementation originally found in STM32 tft_spi.cpp +#if DISABLED(SOFTWARE_SPI) && (defined(STM32F1xx) || defined(STM32F4xx)) && DISABLED(HALSPI_HW_GENERIC) #include "pinconfig.h" @@ -66,8 +66,6 @@ #error Fast HW SPI is currently only supported on STM32F1 and STM32F4 hardware. #endif - - #ifndef HALSPI_LOOPBEEP_TIMEOUT // Timeout in milliseconds (consider that interrupts will increase the time by a lot) #define HALSPI_LOOPBEEP_TIMEOUT 3000 @@ -76,394 +74,312 @@ static SPI_HandleTypeDef SPIhx; static DMA_HandleTypeDef DMAhx; - uint8_t _HAL_GetClockDivider( uint32_t spibasefreq, uint32_t speed ) - { - if ( speed >= (spibasefreq / 2) ) - { - return SPI_BAUDRATEPRESCALER_2; - } - else if ( speed >= (spibasefreq / 4) ) - { - return SPI_BAUDRATEPRESCALER_4; - } - else if ( speed >= (spibasefreq / 8) ) - { - return SPI_BAUDRATEPRESCALER_8; - } - else if ( speed >= (spibasefreq / 16) ) - { - return SPI_BAUDRATEPRESCALER_16; - } - else if ( speed >= (spibasefreq / 32) ) - { - return SPI_BAUDRATEPRESCALER_32; - } - else if ( speed >= (spibasefreq / 64) ) - { - return SPI_BAUDRATEPRESCALER_64; - } - else if ( speed >= (spibasefreq / 128) ) - { - return SPI_BAUDRATEPRESCALER_128; - } - else - { - return SPI_BAUDRATEPRESCALER_256; - } + uint8_t _HAL_GetClockDivider( uint32_t spibasefreq, uint32_t speed ) { + if (speed >= spibasefreq / 2) return SPI_BAUDRATEPRESCALER_2; + else if (speed >= spibasefreq / 4) return SPI_BAUDRATEPRESCALER_4; + else if (speed >= spibasefreq / 8) return SPI_BAUDRATEPRESCALER_8; + else if (speed >= spibasefreq / 16) return SPI_BAUDRATEPRESCALER_16; + else if (speed >= spibasefreq / 32) return SPI_BAUDRATEPRESCALER_32; + else if (speed >= spibasefreq / 64) return SPI_BAUDRATEPRESCALER_64; + else if (speed >= spibasefreq / 128) return SPI_BAUDRATEPRESCALER_128; + else return SPI_BAUDRATEPRESCALER_256; } extern "C" { #include } - static int _spi_pin_sck = NC; - static int _spi_pin_miso = NC; - static int _spi_pin_mosi = NC; - static int _spi_pin_cs = NC; +static int _spi_pin_sck = NC; +static int _spi_pin_miso = NC; +static int _spi_pin_mosi = NC; +static int _spi_pin_cs = NC; #ifdef HAL_SPI_SUPPORTS_ASYNC // We optimize this to be only one CPU-core only, no scheduler. // Only one SPI connection is supported at-a-time, current revision. static volatile bool _spi_busy = false; - struct spiStatusInfo - { + struct spiStatusInfo { bool async_busy = false; void (*asyncCompleteCallback)(void*) = nullptr; void *async_ud = nullptr; }; -#if 0 -#ifdef SPI1_BASE - spiStatusInfo spiStatus_1; -#endif -#ifdef SPI2_BASE - spiStatusInfo spiStatus_2; -#endif -#ifdef SPI3_BASE - spiStatusInfo spiStatus_3; -#endif -#ifdef SPI4_BASE - spiStatusInfo spiStatus_4; -#endif -#ifdef SPI5_BASE - spiStatusInfo spiStatus_5; -#endif -#ifdef SPI6_BASE - spiStatusInfo spiStatus_6; -#endif -#else - spiStatusInfo __spi_status; -#endif - - static spiStatusInfo* SPI_GetRuntimeInfo( SPI_TypeDef *instance ) - { -#if 0 -#ifdef SPI1_BASE - if (instance == SPI1) { - return spiStatus_1; - } -#endif -#ifdef SPI2_BASE - if (instance == SPI2) { - return spiStatus_2; - } -#endif -#ifdef SPI3_BASE - if (instance == SPI3) { - return spiStatus_3; - } -#endif -#ifdef SPI4_BASE - if (instance == SPI4) { - return spiStatus_4; - } -#endif -#ifdef SPI5_BASE - if (instance == SPI5) { - return spiStatus_5; - } -#endif -#ifdef SPI6_BASE - if (instance == SPI6) { - return spiStatus_6; - } -#endif - return nullptr; -#else - return &__spi_status; -#endif - } -#if 0 - static DMA_Channel_TypeDef* DMA_Channel_GetConfig( DMA_TypeDef *DMA, unsigned int channelNum ) - { -#ifdef DMA1_BASE - if (DMA == DMA1) - { - #ifdef DMA1_Channel1_BASE - if (channelNum == 1) - { - return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA1_Channel1_BASE - DMA1_BASE) ); - } - #endif - #ifdef DMA1_Channel2_BASE - if (channelNum == 2) - { - return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA1_Channel2_BASE - DMA1_BASE) ); - } + #if 0 + #ifdef SPI1_BASE + spiStatusInfo spiStatus_1; #endif - #ifdef DMA1_Channel3_BASE - if (channelNum == 3) - { - return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA1_Channel3_BASE - DMA1_BASE) ); - } - #endif - #ifdef DMA1_Channel4_BASE - if (channelNum == 4) - { - return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA1_Channel4_BASE - DMA1_BASE) ); - } - #endif - #ifdef DMA1_Channel5_BASE - if (channelNum == 5) - { - return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA1_Channel5_BASE - DMA1_BASE) ); - } + #ifdef SPI2_BASE + spiStatusInfo spiStatus_2; #endif - #ifdef DMA1_Channel6_BASE - if (channelNum == 6) - { - return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA1_Channel6_BASE - DMA1_BASE) ); - } + #ifdef SPI3_BASE + spiStatusInfo spiStatus_3; #endif - #ifdef DMA1_Channel7_BASE - if (channelNum == 7) - { - return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA1_Channel7_BASE - DMA1_BASE) ); - } + #ifdef SPI4_BASE + spiStatusInfo spiStatus_4; #endif - } -#endif -#ifdef DMA2_BASE - if (DMA == DMA2) - { - #ifdef DMA2_Channel1_BASE - if (channelNum == 1) - { - return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA2_Channel1_BASE - DMA2_BASE) ); - } + #ifdef SPI5_BASE + spiStatusInfo spiStatus_5; #endif - #ifdef DMA2_Channel2_BASE - if (channelNum == 2) - { - return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA2_Channel2_BASE - DMA2_BASE) ); - } + #ifdef SPI6_BASE + spiStatusInfo spiStatus_6; #endif - #ifdef DMA2_Channel3_BASE - if (channelNum == 3) - { - return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA2_Channel3_BASE - DMA2_BASE) ); - } + #else + spiStatusInfo __spi_status; #endif - #ifdef DMA2_Channel4_BASE - if (channelNum == 4) - { - return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA2_Channel4_BASE - DMA2_BASE) ); + + static spiStatusInfo* SPI_GetRuntimeInfo(SPI_TypeDef *instance) { + #if 0 + #ifdef SPI1_BASE + if (instance == SPI1) return spiStatus_1; + #endif + #ifdef SPI2_BASE + if (instance == SPI2) return spiStatus_2; + #endif + #ifdef SPI3_BASE + if (instance == SPI3) return spiStatus_3; + #endif + #ifdef SPI4_BASE + if (instance == SPI4) return spiStatus_4; + #endif + #ifdef SPI5_BASE + if (instance == SPI5) return spiStatus_5; + #endif + #ifdef SPI6_BASE + if (instance == SPI6) return spiStatus_6; + #endif + return nullptr; + #else + return &__spi_status; + #endif + } + + #if 0 + static DMA_Channel_TypeDef* DMA_Channel_GetConfig(DMA_TypeDef *DMA, unsigned int channelNum) { + #ifdef DMA1_BASE + if (DMA == DMA1) { + #ifdef DMA1_Channel1_BASE + if (channelNum == 1) return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA1_Channel1_BASE - DMA1_BASE) ); + #endif + #ifdef DMA1_Channel2_BASE + if (channelNum == 2) return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA1_Channel2_BASE - DMA1_BASE) ); + #endif + #ifdef DMA1_Channel3_BASE + if (channelNum == 3) return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA1_Channel3_BASE - DMA1_BASE) ); + #endif + #ifdef DMA1_Channel4_BASE + if (channelNum == 4) return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA1_Channel4_BASE - DMA1_BASE) ); + #endif + #ifdef DMA1_Channel5_BASE + if (channelNum == 5) return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA1_Channel5_BASE - DMA1_BASE) ); + #endif + #ifdef DMA1_Channel6_BASE + if (channelNum == 6) return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA1_Channel6_BASE - DMA1_BASE) ); + #endif + #ifdef DMA1_Channel7_BASE + if (channelNum == 7) return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA1_Channel7_BASE - DMA1_BASE) ); + #endif } - #endif - #ifdef DMA2_Channel5_BASE - if (channelNum == 5) - { - return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA2_Channel5_BASE - DMA2_BASE) ); + #endif + + #ifdef DMA2_BASE + if (DMA == DMA2) { + #ifdef DMA2_Channel1_BASE + if (channelNum == 1) return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA2_Channel1_BASE - DMA2_BASE) ); + #endif + #ifdef DMA2_Channel2_BASE + if (channelNum == 2) return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA2_Channel2_BASE - DMA2_BASE) ); + #endif + #ifdef DMA2_Channel3_BASE + if (channelNum == 3) return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA2_Channel3_BASE - DMA2_BASE) ); + #endif + #ifdef DMA2_Channel4_BASE + if (channelNum == 4) return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA2_Channel4_BASE - DMA2_BASE) ); + #endif + #ifdef DMA2_Channel5_BASE + if (channelNum == 5) return (DMA_Channel_TypeDef*)( (uint32_t)DMA + (DMA2_Channel5_BASE - DMA2_BASE) ); + #endif } - #endif - } -#endif + #endif // DMA2_BASE return nullptr; } -#endif + #endif // The interrupt handler. static void _DMA_Interrupt( void ); static void NVIC_DMA_Interrupt_Enable(DMA_TypeDef *DMA, uint32_t channelNum) { -#ifdef DMA1_BASE - if (DMA == DMA1) { - if (channelNum >= 1 && channelNum <= 7) { - // See page 204 of STM32F1xx ref manual (interrupt table). - IRQn_Type inum = (IRQn_Type)( 10 + channelNum ); - - HAL_NVIC_EnableIRQ(inum); - HAL_NVIC_SetPriority(inum, 5, 0); - } - } -#endif -#ifdef DMA2_BASE - if (DMA == DMA2) { - if (channelNum >= 1 && channelNum <= 3) { - // See page 204 of STM32F1xx ref manual (interrupt table). - IRQn_Type inum = (IRQn_Type)( 55 + channelNum ); - - HAL_NVIC_EnableIRQ(inum); - HAL_NVIC_SetPriority(inum, 5, 0); + #ifdef DMA1_BASE + if (DMA == DMA1) { + if (channelNum >= 1 && channelNum <= 7) { + // See page 204 of STM32F1xx ref manual (interrupt table). + IRQn_Type inum = (IRQn_Type)( 10 + channelNum ); + + HAL_NVIC_EnableIRQ(inum); + HAL_NVIC_SetPriority(inum, 5, 0); + } } - else if (channelNum == 4 || channelNum == 5) { - HAL_NVIC_EnableIRQ((IRQn_Type)59); - HAL_NVIC_SetPriority((IRQn_Type)59, 5, 0); + #endif // DMA1_BASE + #ifdef + if (DMA == DMA2) { + if (channelNum >= 1 && channelNum <= 3) { + // See page 204 of STM32F1xx ref manual (interrupt table). + IRQn_Type inum = (IRQn_Type)( 55 + channelNum ); + + HAL_NVIC_EnableIRQ(inum); + HAL_NVIC_SetPriority(inum, 5, 0); + } + else if (channelNum == 4 || channelNum == 5) { + HAL_NVIC_EnableIRQ((IRQn_Type)59); + HAL_NVIC_SetPriority((IRQn_Type)59, 5, 0); + } } - } -#endif + #endif // DMA2_BASE } static void NVIC_DMA_Interrupt_Disable(DMA_TypeDef *DMA, uint32_t channelNum) { -#ifdef DMA1_BASE - if (DMA == DMA1) { - if (channelNum >= 1 && channelNum <= 7) { - // See page 204 of STM32F1xx ref manual (interrupt table). - IRQn_Type inum = (IRQn_Type)( 10 + channelNum ); - - HAL_NVIC_SetPriority(inum, 255, 0); - HAL_NVIC_DisableIRQ(inum); + #ifdef DMA1_BASE + if (DMA == DMA1) { + if (channelNum >= 1 && channelNum <= 7) { + // See page 204 of STM32F1xx ref manual (interrupt table). + IRQn_Type inum = (IRQn_Type)( 10 + channelNum ); + + HAL_NVIC_SetPriority(inum, 255, 0); + HAL_NVIC_DisableIRQ(inum); + } } - } -#endif -#ifdef DMA2_BASE - if (DMA == DMA2) { - if (channelNum >= 1 && channelNum <= 3) { - // See page 204 of STM32F1xx ref manual (interrupt table). - IRQn_Type inum = (IRQn_Type)( 55 + channelNum ); - - HAL_NVIC_SetPriority(inum, 255, 0); - HAL_NVIC_DisableIRQ(inum); + #endif // DMA1_BASE + #ifdef DMA2_BASE + if (DMA == DMA2) { + if (channelNum >= 1 && channelNum <= 3) { + // See page 204 of STM32F1xx ref manual (interrupt table). + IRQn_Type inum = (IRQn_Type)( 55 + channelNum ); + + HAL_NVIC_SetPriority(inum, 255, 0); + HAL_NVIC_DisableIRQ(inum); + } + else if (channelNum == 4 || channelNum == 5) { + HAL_NVIC_SetPriority((IRQn_Type)59, 255, 0); + HAL_NVIC_DisableIRQ((IRQn_Type)59); + } } - else if (channelNum == 4 || channelNum == 5) { - HAL_NVIC_SetPriority((IRQn_Type)59, 255, 0); - HAL_NVIC_DisableIRQ((IRQn_Type)59); - } - } -#endif + #endif // DMA2_BASE } - static void DMA_Channel_TXCompleteInterruptSet( DMA_Channel_TypeDef *DMAch, bool enable ) - { + static void DMA_Channel_TXCompleteInterruptSet(DMA_Channel_TypeDef *DMAch, bool enable) { if (enable) DMAch->CCR |= 0x02; else DMAch->CCR &= ~0x02; } - static void DMA_Channel_TXErrorInterruptSet( DMA_Channel_TypeDef *DMAch, bool enable ) - { + static void DMA_Channel_TXErrorInterruptSet( DMA_Channel_TypeDef *DMAch, bool enable ) { if (enable) DMAch->CCR |= 0x04; else DMAch->CCR &= ~0x04; } -#if 0 - static void DMA_Channel_Enable( DMA_Channel_TypeDef *DMAch, bool enable ) - { + + #if 0 + static void DMA_Channel_Enable( DMA_Channel_TypeDef *DMAch, bool enable ) { if (enable) DMAch->CCR |= 0x01; else DMAch->CCR &= ~0x01; } -#endif + #endif - static void DMA_Channel_ResetTXComplete( DMA_TypeDef *DMA, unsigned int channelNum ) - { + static void DMA_Channel_ResetTXComplete( DMA_TypeDef *DMA, unsigned int channelNum ) { CBI(DMA->IFCR, ( 1 + (4 * (channelNum - 1)) )); } - static void DMA_Channel_ResetTXError( DMA_TypeDef *DMA, unsigned int channelNum ) - { + static void DMA_Channel_ResetTXError( DMA_TypeDef *DMA, unsigned int channelNum ) { CBI(DMA->IFCR, ( 2 + (4 * (channelNum - 1)) )); } - static bool DMA_Channel_TXComplete( DMA_TypeDef *DMA, unsigned int channelNum ) - { + static bool DMA_Channel_TXComplete( DMA_TypeDef *DMA, unsigned int channelNum ) { return TEST(DMA->ISR, ( 1 + (4 * (channelNum - 1)) )); } - static bool DMA_Channel_TXError( DMA_TypeDef *DMA, unsigned int channelNum ) - { + static bool DMA_Channel_TXError( DMA_TypeDef *DMA, unsigned int channelNum ) { return TEST(DMA->ISR, ( 2 + (4 * (channelNum - 1)) )); } -#endif //HAL_SPI_SUPPORTS_ASYNC - - static bool _HAL_SPI_InitClock(int _spi_clkmode) { - bool changed = false; - if (_spi_clkmode == SPI_CLKMODE_0 || _spi_clkmode == SPI_CLKMODE_1) { - if (SPIhx.Init.CLKPolarity != SPI_POLARITY_LOW) { - SPIhx.Init.CLKPolarity = SPI_POLARITY_LOW; - changed = true; - } + +#endif // HAL_SPI_SUPPORTS_ASYNC + +static bool _HAL_SPI_InitClock(int _spi_clkmode) { + bool changed = false; + if (_spi_clkmode == SPI_CLKMODE_0 || _spi_clkmode == SPI_CLKMODE_1) { + if (SPIhx.Init.CLKPolarity != SPI_POLARITY_LOW) { + SPIhx.Init.CLKPolarity = SPI_POLARITY_LOW; + changed = true; } - else { - if (SPIhx.Init.CLKPolarity != SPI_POLARITY_HIGH) { - SPIhx.Init.CLKPolarity = SPI_POLARITY_HIGH; - changed = true; - } + } + else { + if (SPIhx.Init.CLKPolarity != SPI_POLARITY_HIGH) { + SPIhx.Init.CLKPolarity = SPI_POLARITY_HIGH; + changed = true; } + } - if (_spi_clkmode == SPI_CLKMODE_0 || _spi_clkmode == SPI_CLKMODE_2) { - if (SPIhx.Init.CLKPhase != SPI_PHASE_1EDGE) { - SPIhx.Init.CLKPhase = SPI_PHASE_1EDGE; - changed = true; - } + if (_spi_clkmode == SPI_CLKMODE_0 || _spi_clkmode == SPI_CLKMODE_2) { + if (SPIhx.Init.CLKPhase != SPI_PHASE_1EDGE) { + SPIhx.Init.CLKPhase = SPI_PHASE_1EDGE; + changed = true; } - else { - if (SPIhx.Init.CLKPhase != SPI_PHASE_2EDGE) { - SPIhx.Init.CLKPhase = SPI_PHASE_2EDGE; - changed = true; - } + } + else { + if (SPIhx.Init.CLKPhase != SPI_PHASE_2EDGE) { + SPIhx.Init.CLKPhase = SPI_PHASE_2EDGE; + changed = true; } - - return changed; } - struct spi_monitored_loop - { + return changed; +} + +struct spi_monitored_loop { private: -#if defined(HALSPI_DO_LOOPBEEPS) && PIN_EXISTS(BEEPER) - uint32_t _start_millis; -#endif + #if defined(HALSPI_DO_LOOPBEEPS) && PIN_EXISTS(BEEPER) + uint32_t _start_millis; + #endif public: inline spi_monitored_loop() { -#if defined(HALSPI_DO_LOOPBEEPS) && PIN_EXISTS(BEEPER) - _start_millis = millis(); -#endif + #if defined(HALSPI_DO_LOOPBEEPS) && PIN_EXISTS(BEEPER) + _start_millis = millis(); + #endif } inline void update(unsigned int beep_code) { -#if defined(HALSPI_DO_LOOPBEEPS) && PIN_EXISTS(BEEPER) - if ((millis() - _start_millis) <= HALSPI_LOOPBEEP_TIMEOUT) return; - OUT_WRITE(BEEPER_PIN, HIGH); - delay(500); - OUT_WRITE(BEEPER_PIN, LOW); - delay(200); - OUT_WRITE(BEEPER_PIN, HIGH); - delay(200); - OUT_WRITE(BEEPER_PIN, LOW); - delay(200); - OUT_WRITE(BEEPER_PIN, HIGH); - delay(200); - OUT_WRITE(BEEPER_PIN, LOW); - delay(1000); - for (unsigned int n = 0; n < beep_code; n++) { + #if defined(HALSPI_DO_LOOPBEEPS) && PIN_EXISTS(BEEPER) + if ((millis() - _start_millis) <= HALSPI_LOOPBEEP_TIMEOUT) return; + OUT_WRITE(BEEPER_PIN, HIGH); + delay(500); + OUT_WRITE(BEEPER_PIN, LOW); + delay(200); OUT_WRITE(BEEPER_PIN, HIGH); delay(200); OUT_WRITE(BEEPER_PIN, LOW); delay(200); - } - delay(800); - OUT_WRITE(BEEPER_PIN, HIGH); - delay(1000); - OUT_WRITE(BEEPER_PIN, LOW); - delay(2000); -#endif + OUT_WRITE(BEEPER_PIN, HIGH); + delay(200); + OUT_WRITE(BEEPER_PIN, LOW); + delay(1000); + for (unsigned int n = 0; n < beep_code; n++) { + OUT_WRITE(BEEPER_PIN, HIGH); + delay(200); + OUT_WRITE(BEEPER_PIN, LOW); + delay(200); + } + delay(800); + OUT_WRITE(BEEPER_PIN, HIGH); + delay(1000); + OUT_WRITE(BEEPER_PIN, LOW); + delay(2000); + #endif } - }; +}; - static void _spiOnError(unsigned int beep_code = 0) { - for (;;) { -#if defined(HALSPI_DO_ERRORBEEPS) && PIN_EXISTS(BEEPER) +static void _spiOnError(unsigned int beep_code = 0) { + for (;;) { + #if defined(HALSPI_DO_ERRORBEEPS) && PIN_EXISTS(BEEPER) OUT_WRITE(BEEPER_PIN, HIGH); delay(500); OUT_WRITE(BEEPER_PIN, LOW); @@ -483,105 +399,105 @@ extern "C" { delay(1000); OUT_WRITE(BEEPER_PIN, LOW); delay(2000); -#endif - } + #endif } +} -#if !ENABLED(HAL_SPI_SUPPORTS_ASYNC) +#if DISABLED(HAL_SPI_SUPPORTS_ASYNC) static bool _spi_debug_inside_transaction = false; #endif - static void _SPI_Enter( SPI_TypeDef *instance ) { -#if ENABLED(HAL_SPI_SUPPORTS_ASYNC) +static void _SPI_Enter(SPI_TypeDef *instance) { + #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) spi_monitored_loop lw; // During testing, this loop did take longer than 1 second on the // MKS Robin E3D V1.1 (rarely). while (_spi_busy) { lw.update(12); } _spi_busy = true; -#else + #else if (_spi_debug_inside_transaction) _spiOnError(11); _spi_debug_inside_transaction = true; #endif } - static void _SPI_Leave( SPI_TypeDef *instance ) { -#if ENABLED(HAL_SPI_SUPPORTS_ASYNC) +static void _SPI_Leave(SPI_TypeDef *instance) { + #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) _spi_busy = false; -#else + #else if (!_spi_debug_inside_transaction) _spiOnError(12); _spi_debug_inside_transaction = false; -#endif - } + #endif +} - static void _SPI_AsyncBarrier() { -#if ENABLED(HAL_SPI_SUPPORTS_ASYNC) +static void _SPI_AsyncBarrier() { + #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) auto *spiInfo = SPI_GetRuntimeInfo(SPIhx.Instance); // Wait until any currently configured transfer has finished. spi_monitored_loop lw; while (spiInfo->async_busy) { lw.update(10); } -#endif - } + #endif +} - void spiBegin() { - #if PIN_EXISTS(SD_SS) - OUT_WRITE(SD_SS_PIN, HIGH); - #endif +void spiBegin() { + #if PIN_EXISTS(SD_SS) + OUT_WRITE(SD_SS_PIN, HIGH); + #endif -#if !(defined(STM32F1xx) || defined(STM32F4xx)) + #if !(defined(STM32F1xx) || defined(STM32F4xx)) memset(&SPIhx, 0, sizeof(SPIhx)); -#endif - //SPIhx.Instance = spiInstance; - SPIhx.State = HAL_SPI_STATE_RESET; - SPIhx.Init.NSS = SPI_NSS_SOFT; - SPIhx.Init.Mode = SPI_MODE_MASTER; - //SPIhx.Init.Direction = (TFT_MISO_PIN != NC && TFT_MISO_PIN == TFT_MOSI_PIN) ? SPI_DIRECTION_1LINE : SPI_DIRECTION_2LINES; - //SPIhx.Init.BaudRatePrescaler = clkdiv; - //SPIhx.Init.CLKPhase = SPI_PHASE_1EDGE; - //SPIhx.Init.CLKPolarity = SPI_POLARITY_LOW; - _HAL_SPI_InitClock(SPI_CLKMODE_DEFAULT); - //SPIhx.Init.DataSize = SPI_DATASIZE_8BIT; - SPIhx.Init.FirstBit = SPI_FIRSTBIT_MSB; // default. - SPIhx.Init.TIMode = SPI_TIMODE_DISABLE; - SPIhx.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; - SPIhx.Init.CRCPolynomial = 10; - -#if !(defined(STM32F1xx) || defined(STM32F4xx)) + #endif + //SPIhx.Instance = spiInstance; + SPIhx.State = HAL_SPI_STATE_RESET; + SPIhx.Init.NSS = SPI_NSS_SOFT; + SPIhx.Init.Mode = SPI_MODE_MASTER; + //SPIhx.Init.Direction = (TFT_MISO_PIN != NC && TFT_MISO_PIN == TFT_MOSI_PIN) ? SPI_DIRECTION_1LINE : SPI_DIRECTION_2LINES; + //SPIhx.Init.BaudRatePrescaler = clkdiv; + //SPIhx.Init.CLKPhase = SPI_PHASE_1EDGE; + //SPIhx.Init.CLKPolarity = SPI_POLARITY_LOW; + _HAL_SPI_InitClock(SPI_CLKMODE_DEFAULT); + //SPIhx.Init.DataSize = SPI_DATASIZE_8BIT; + SPIhx.Init.FirstBit = SPI_FIRSTBIT_MSB; // default. + SPIhx.Init.TIMode = SPI_TIMODE_DISABLE; + SPIhx.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + SPIhx.Init.CRCPolynomial = 10; + + #if !(defined(STM32F1xx) || defined(STM32F4xx)) memset(&DMAhx, 0, sizeof(DMAhx)); -#endif - DMAhx.Init.Direction = DMA_MEMORY_TO_PERIPH; // target is SPI bus. - //DMAhx.Init.MemInc = DMA_MINC_ENABLE; - DMAhx.Init.PeriphInc = DMA_PINC_DISABLE; - //DMAhx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - //DMAhx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - DMAhx.Init.Mode = DMA_NORMAL; - DMAhx.Init.Priority = DMA_PRIORITY_LOW; - #ifdef STM32F4xx - DMAhx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - #endif - } + #endif + DMAhx.Init.Direction = DMA_MEMORY_TO_PERIPH; // target is SPI bus. + //DMAhx.Init.MemInc = DMA_MINC_ENABLE; + DMAhx.Init.PeriphInc = DMA_PINC_DISABLE; + //DMAhx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + //DMAhx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + DMAhx.Init.Mode = DMA_NORMAL; + DMAhx.Init.Priority = DMA_PRIORITY_LOW; + #ifdef STM32F4xx + DMAhx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + #endif +} - void spiSetupChipSelect(int pin) { - OUT_WRITE(pin, HIGH); - } +void spiSetupChipSelect(int pin) { + OUT_WRITE(pin, HIGH); +} - static void _HAL_SPI_Prepare(void) { - auto name_sck_pin = digitalPinToPinName(_spi_pin_sck); +static void _HAL_SPI_Prepare(void) { + auto name_sck_pin = digitalPinToPinName(_spi_pin_sck); - pinmap_pinout(name_sck_pin, PinMap_SPI_SCLK); - pinmap_pinout(digitalPinToPinName(_spi_pin_mosi), PinMap_SPI_MOSI); - if (_spi_pin_miso != NC && _spi_pin_miso != _spi_pin_mosi) { - pinmap_pinout(digitalPinToPinName(_spi_pin_miso), PinMap_SPI_MISO); - } - //pinmap_pinout(digitalPinToPinName(TFT_CS_PIN), PinMap_SPI_SSEL); + pinmap_pinout(name_sck_pin, PinMap_SPI_SCLK); + pinmap_pinout(digitalPinToPinName(_spi_pin_mosi), PinMap_SPI_MOSI); + if (_spi_pin_miso != NC && _spi_pin_miso != _spi_pin_mosi) { + pinmap_pinout(digitalPinToPinName(_spi_pin_miso), PinMap_SPI_MISO); + } + //pinmap_pinout(digitalPinToPinName(TFT_CS_PIN), PinMap_SPI_SSEL); - pin_PullConfig(get_GPIO_Port(STM_PORT(name_sck_pin)), STM_LL_GPIO_PIN(name_sck_pin), GPIO_PULLDOWN); + pin_PullConfig(get_GPIO_Port(STM_PORT(name_sck_pin)), STM_LL_GPIO_PIN(name_sck_pin), GPIO_PULLDOWN); - // See page 282 of the STM32F1xx manual (DMA1). + // See page 282 of the STM32F1xx manual (DMA1). -#if 0 + #if 0 // @thinkyhead #ifdef STM32F1xx #define _DMATX_PREPARE(N1,N4,S,C1,C4) \ @@ -602,80 +518,80 @@ extern "C" { __HAL_RCC_SPI##I##_RELEASE_RESET(); \ _DMATX_PREPARE(N1,N4,S,C1,C4); \ } -#endif + #endif - #ifdef SPI1_BASE - if (SPIhx.Instance == SPI1) { - __HAL_RCC_SPI1_CLK_ENABLE(); - __HAL_RCC_SPI1_FORCE_RESET(); - __HAL_RCC_SPI1_RELEASE_RESET(); - #ifdef STM32F1xx - #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) - // See page 204 of the STM32F1xx manual (interrupt table). - nvicSetIRQHandler(DMA1_Channel3_IRQn, _DMA_Interrupt); - nvicInstallRedirect(); - NVIC_DMA_Interrupt_Enable(DMA1, 3); - #endif - __HAL_RCC_DMA1_CLK_ENABLE(); - DMAhx.Instance = DMA1_Channel3; - #elif defined(STM32F4xx) - __HAL_RCC_DMA2_CLK_ENABLE(); - DMAhx.Instance = DMA2_Stream3; - DMAhx.Init.Channel = DMA_CHANNEL_3; + #ifdef SPI1_BASE + if (SPIhx.Instance == SPI1) { + __HAL_RCC_SPI1_CLK_ENABLE(); + __HAL_RCC_SPI1_FORCE_RESET(); + __HAL_RCC_SPI1_RELEASE_RESET(); + #ifdef STM32F1xx + #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) + // See page 204 of the STM32F1xx manual (interrupt table). + nvicSetIRQHandler(DMA1_Channel3_IRQn, _DMA_Interrupt); + nvicInstallRedirect(); + NVIC_DMA_Interrupt_Enable(DMA1, 3); #endif - } - #endif + __HAL_RCC_DMA1_CLK_ENABLE(); + DMAhx.Instance = DMA1_Channel3; + #elif defined(STM32F4xx) + __HAL_RCC_DMA2_CLK_ENABLE(); + DMAhx.Instance = DMA2_Stream3; + DMAhx.Init.Channel = DMA_CHANNEL_3; + #endif + } + #endif - #ifdef SPI2_BASE - if (SPIhx.Instance == SPI2) { - __HAL_RCC_SPI2_CLK_ENABLE(); - __HAL_RCC_SPI2_FORCE_RESET(); - __HAL_RCC_SPI2_RELEASE_RESET(); - #ifdef STM32F1xx - #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) - // See page 204 of the STM32F1xx manual (interrupt table). - nvicSetIRQHandler(DMA1_Channel5_IRQn, _DMA_Interrupt); - nvicInstallRedirect(); - NVIC_DMA_Interrupt_Enable(DMA1, 5); - #endif - __HAL_RCC_DMA1_CLK_ENABLE(); - DMAhx.Instance = DMA1_Channel5; - #elif defined(STM32F4xx) - __HAL_RCC_DMA1_CLK_ENABLE(); - DMAhx.Instance = DMA1_Stream4; - DMAhx.Init.Channel = DMA_CHANNEL_0; + #ifdef SPI2_BASE + if (SPIhx.Instance == SPI2) { + __HAL_RCC_SPI2_CLK_ENABLE(); + __HAL_RCC_SPI2_FORCE_RESET(); + __HAL_RCC_SPI2_RELEASE_RESET(); + #ifdef STM32F1xx + #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) + // See page 204 of the STM32F1xx manual (interrupt table). + nvicSetIRQHandler(DMA1_Channel5_IRQn, _DMA_Interrupt); + nvicInstallRedirect(); + NVIC_DMA_Interrupt_Enable(DMA1, 5); #endif - } - #endif + __HAL_RCC_DMA1_CLK_ENABLE(); + DMAhx.Instance = DMA1_Channel5; + #elif defined(STM32F4xx) + __HAL_RCC_DMA1_CLK_ENABLE(); + DMAhx.Instance = DMA1_Stream4; + DMAhx.Init.Channel = DMA_CHANNEL_0; + #endif + } + #endif - #ifdef SPI3_BASE - if (SPIhx.Instance == SPI3) { - __HAL_RCC_SPI3_CLK_ENABLE(); - __HAL_RCC_SPI3_FORCE_RESET(); - __HAL_RCC_SPI3_RELEASE_RESET(); - #ifdef STM32F1xx - #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) - // See page 204 of the STM32F1xx manual (interrupt table). - nvicSetIRQHandler(DMA2_Channel2_IRQn, _DMA_Interrupt); - nvicInstallRedirect(); - NVIC_DMA_Interrupt_Enable(DMA2, 2); - #endif - __HAL_RCC_DMA2_CLK_ENABLE(); - DMAhx.Instance = DMA2_Channel2; - #elif defined(STM32F4xx) - __HAL_RCC_DMA1_CLK_ENABLE(); - DMAhx.Instance = DMA1_Stream5; - DMAhx.Init.Channel = DMA_CHANNEL_0; + #ifdef SPI3_BASE + if (SPIhx.Instance == SPI3) { + __HAL_RCC_SPI3_CLK_ENABLE(); + __HAL_RCC_SPI3_FORCE_RESET(); + __HAL_RCC_SPI3_RELEASE_RESET(); + #ifdef STM32F1xx + #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) + // See page 204 of the STM32F1xx manual (interrupt table). + nvicSetIRQHandler(DMA2_Channel2_IRQn, _DMA_Interrupt); + nvicInstallRedirect(); + NVIC_DMA_Interrupt_Enable(DMA2, 2); #endif - } - #endif + __HAL_RCC_DMA2_CLK_ENABLE(); + DMAhx.Instance = DMA2_Channel2; + #elif defined(STM32F4xx) + __HAL_RCC_DMA1_CLK_ENABLE(); + DMAhx.Instance = DMA1_Stream5; + DMAhx.Init.Channel = DMA_CHANNEL_0; + #endif + } + #endif - // TODO: there may be more than 4 SPI instances; take a look into remaining reference - // manuals to see which ones can be enabled aswell. - } + // TODO: there may be more than 4 SPI instances; take a look into remaining reference + // manuals to see which ones can be enabled aswell. +} - static void _HAL_SPI_Dismantle(void) { -#if 0 +static void _HAL_SPI_Dismantle(void) { + #if 0 // @thinkyhead #ifdef STM32F1xx #define _DMATX_DISMANTLE(N1,N4) __HAL_RCC_DMA##N1##_CLK_DISABLE() @@ -691,317 +607,309 @@ extern "C" { __HAL_RCC_SPI##I##_CLK_DISABLE(); \ _DMATX_DISMANTLE(N1,N4); \ } -#endif + #endif - #ifdef SPI1_BASE - if (SPIhx.Instance == SPI1) { - __HAL_RCC_SPI1_FORCE_RESET(); - __HAL_RCC_SPI1_RELEASE_RESET(); - __HAL_RCC_SPI1_CLK_DISABLE(); - #ifdef STM32F1xx - __HAL_RCC_DMA1_CLK_DISABLE(); - #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) - NVIC_DMA_Interrupt_Disable(DMA1, 3); - // Restore the interrupt table entry. - nvicUninstallRedirect(); - #endif - #elif defined(STM32F4xx) - __HAL_RCC_DMA2_CLK_DISABLE(); + #ifdef SPI1_BASE + if (SPIhx.Instance == SPI1) { + __HAL_RCC_SPI1_FORCE_RESET(); + __HAL_RCC_SPI1_RELEASE_RESET(); + __HAL_RCC_SPI1_CLK_DISABLE(); + #ifdef STM32F1xx + __HAL_RCC_DMA1_CLK_DISABLE(); + #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) + NVIC_DMA_Interrupt_Disable(DMA1, 3); + // Restore the interrupt table entry. + nvicUninstallRedirect(); #endif - } - #endif + #elif defined(STM32F4xx) + __HAL_RCC_DMA2_CLK_DISABLE(); + #endif + } + #endif - #ifdef SPI2_BASE - if (SPIhx.Instance == SPI2) { - __HAL_RCC_SPI2_FORCE_RESET(); - __HAL_RCC_SPI2_RELEASE_RESET(); - __HAL_RCC_SPI2_CLK_DISABLE(); - #ifdef STM32F1xx - __HAL_RCC_DMA1_CLK_DISABLE(); - #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) - NVIC_DMA_Interrupt_Disable(DMA1, 5); - // Restore the interrupt table entry. - nvicUninstallRedirect(); - #endif - #elif defined(STM32F4xx) - __HAL_RCC_DMA1_CLK_DISABLE(); + #ifdef SPI2_BASE + if (SPIhx.Instance == SPI2) { + __HAL_RCC_SPI2_FORCE_RESET(); + __HAL_RCC_SPI2_RELEASE_RESET(); + __HAL_RCC_SPI2_CLK_DISABLE(); + #ifdef STM32F1xx + __HAL_RCC_DMA1_CLK_DISABLE(); + #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) + NVIC_DMA_Interrupt_Disable(DMA1, 5); + // Restore the interrupt table entry. + nvicUninstallRedirect(); #endif - } - #endif + #elif defined(STM32F4xx) + __HAL_RCC_DMA1_CLK_DISABLE(); + #endif + } + #endif - #ifdef SPI3_BASE - if (SPIhx.Instance == SPI3) { - __HAL_RCC_SPI3_FORCE_RESET(); - __HAL_RCC_SPI3_RELEASE_RESET(); - __HAL_RCC_SPI3_CLK_DISABLE(); - #ifdef STM32F1xx - __HAL_RCC_DMA2_CLK_DISABLE(); - #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) - NVIC_DMA_Interrupt_Disable(DMA2, 2); - // Restore the interrupt table entry. - nvicUninstallRedirect(); - #endif - #elif defined(STM32F4xx) - __HAL_RCC_DMA1_CLK_DISABLE(); + #ifdef SPI3_BASE + if (SPIhx.Instance == SPI3) { + __HAL_RCC_SPI3_FORCE_RESET(); + __HAL_RCC_SPI3_RELEASE_RESET(); + __HAL_RCC_SPI3_CLK_DISABLE(); + #ifdef STM32F1xx + __HAL_RCC_DMA2_CLK_DISABLE(); + #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) + NVIC_DMA_Interrupt_Disable(DMA2, 2); + // Restore the interrupt table entry. + nvicUninstallRedirect(); #endif - } - #endif - } + #elif defined(STM32F4xx) + __HAL_RCC_DMA1_CLK_DISABLE(); + #endif + } + #endif +} - static void __HAL_SPI_ConfigDirection() { - if (_spi_pin_miso == NC) - SPI_1LINE_TX(&SPIhx); - else if (_spi_pin_mosi == NC) - SPI_1LINE_RX(&SPIhx); - } +static void __HAL_SPI_ConfigDirection() { + if (_spi_pin_miso == NC) + SPI_1LINE_TX(&SPIhx); + else if (_spi_pin_mosi == NC) + SPI_1LINE_RX(&SPIhx); +} - static void _spiSecureCSEnter() { - if (_spi_pin_cs != NC) { - WRITE(_spi_pin_cs, HIGH); - } +static void _spiSecureCSEnter() { + if (_spi_pin_cs != NC) { + WRITE(_spi_pin_cs, HIGH); } +} - static void _spiSecureCSLeave() { - if (_spi_pin_cs != NC) { - WRITE(_spi_pin_cs, LOW); - } +static void _spiSecureCSLeave() { + if (_spi_pin_cs != NC) { + WRITE(_spi_pin_cs, LOW); } +} - static bool _spi_is_transmit_sequence_initialized = false; - - static void _spiSecureShutdown() { - _SPI_AsyncBarrier(); +static bool _spi_is_transmit_sequence_initialized = false; - if (_spi_is_transmit_sequence_initialized) { - // Wait atleast until the hardware has accepted our transmission data item. - // Then we know that the BSY flag is valid. - spi_monitored_loop lw; - while (!__HAL_SPI_GET_FLAG(&SPIhx, SPI_FLAG_TXE)) { lw.update(1); } - } +static void _spiSecureShutdown() { + _SPI_AsyncBarrier(); + if (_spi_is_transmit_sequence_initialized) { + // Wait atleast until the hardware has accepted our transmission data item. + // Then we know that the BSY flag is valid. spi_monitored_loop lw; - while ( __HAL_SPI_GET_FLAG(&SPIhx, SPI_FLAG_BSY)) { lw.update(2); } + while (!__HAL_SPI_GET_FLAG(&SPIhx, SPI_FLAG_TXE)) { lw.update(1); } + } - _spiSecureCSEnter(); + spi_monitored_loop lw; + while ( __HAL_SPI_GET_FLAG(&SPIhx, SPI_FLAG_BSY)) { lw.update(2); } - __HAL_SPI_DISABLE(&SPIhx); + _spiSecureCSEnter(); - // Same status as just calling _spiSecureCSEnter. - } + __HAL_SPI_DISABLE(&SPIhx); - static bool _spi_is_initialized = false; + // Same status as just calling _spiSecureCSEnter. +} - static void _HAL_SPI_UpdateTransaction(uint16_t dataSize) { - bool requires_spi_reboot = false; +static bool _spi_is_initialized = false; - if (_spi_is_initialized == false) { - SPIhx.Init.DataSize = dataSize; - HAL_SPI_Init(&SPIhx); - _spi_is_initialized = true; - requires_spi_reboot = true; - } - else if (SPIhx.Init.DataSize != dataSize) { - _spiSecureShutdown(); - HAL_SPI_DeInit(&SPIhx); - SPIhx.Init.DataSize = dataSize; - HAL_SPI_Init(&SPIhx); - requires_spi_reboot = true; - } +static void _HAL_SPI_UpdateTransaction(uint16_t dataSize) { + bool requires_spi_reboot = false; - if (requires_spi_reboot) { - __HAL_SPI_ConfigDirection(); - __HAL_SPI_ENABLE(&SPIhx); + if (_spi_is_initialized == false) { + SPIhx.Init.DataSize = dataSize; + HAL_SPI_Init(&SPIhx); + _spi_is_initialized = true; + requires_spi_reboot = true; + } + else if (SPIhx.Init.DataSize != dataSize) { + _spiSecureShutdown(); + HAL_SPI_DeInit(&SPIhx); + SPIhx.Init.DataSize = dataSize; + HAL_SPI_Init(&SPIhx); + requires_spi_reboot = true; + } - _spi_is_transmit_sequence_initialized = false; + if (requires_spi_reboot) { + __HAL_SPI_ConfigDirection(); + __HAL_SPI_ENABLE(&SPIhx); - _spiSecureCSLeave(); - } + _spi_is_transmit_sequence_initialized = false; + + _spiSecureCSLeave(); } +} - static void _HAL_SPI_EndOfTransaction() { - if (_spi_is_initialized) { - HAL_SPI_DeInit(&SPIhx); - _spi_is_initialized = false; - } +static void _HAL_SPI_EndOfTransaction() { + if (_spi_is_initialized) { + HAL_SPI_DeInit(&SPIhx); + _spi_is_initialized = false; } +} - void spiInitEx(uint32_t maxClockFreq, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { - int use_pin_sck, use_pin_miso, use_pin_mosi, use_pin_cs; - if (hint_sck != NC && hint_mosi != NC) - { - use_pin_sck = hint_sck; - use_pin_miso = hint_miso; - use_pin_mosi = hint_mosi; - } - else - { - use_pin_sck = SD_SCK_PIN; - use_pin_miso = SD_MISO_PIN; - use_pin_mosi = SD_MOSI_PIN; - } - use_pin_cs = hint_cs; +void spiInitEx(uint32_t maxClockFreq, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { + int use_pin_sck, use_pin_miso, use_pin_mosi, use_pin_cs; + if (hint_sck != NC && hint_mosi != NC) { + use_pin_sck = hint_sck; + use_pin_miso = hint_miso; + use_pin_mosi = hint_mosi; + } + else { + use_pin_sck = SD_SCK_PIN; + use_pin_miso = SD_MISO_PIN; + use_pin_mosi = SD_MOSI_PIN; + } + use_pin_cs = hint_cs; - PinName name_sck_pin = digitalPinToPinName(use_pin_sck); + PinName name_sck_pin = digitalPinToPinName(use_pin_sck); - SPI_TypeDef *spiInstance = (SPI_TypeDef*)pinmap_peripheral(name_sck_pin, PinMap_SPI_SCLK); + SPI_TypeDef *spiInstance = (SPI_TypeDef*)pinmap_peripheral(name_sck_pin, PinMap_SPI_SCLK); - if (spiInstance != pinmap_peripheral(digitalPinToPinName(use_pin_mosi), PinMap_SPI_MOSI)) - _spiOnError(); - if (use_pin_miso != NC && spiInstance != pinmap_peripheral(digitalPinToPinName(use_pin_miso), PinMap_SPI_MISO)) - _spiOnError(); + if (spiInstance != pinmap_peripheral(digitalPinToPinName(use_pin_mosi), PinMap_SPI_MOSI)) + _spiOnError(); + if (use_pin_miso != NC && spiInstance != pinmap_peripheral(digitalPinToPinName(use_pin_miso), PinMap_SPI_MISO)) + _spiOnError(); - // Barrier. - _SPI_Enter( spiInstance ); + // Barrier. + _SPI_Enter( spiInstance ); - _spi_pin_sck = use_pin_sck; - _spi_pin_miso = use_pin_miso; - _spi_pin_mosi = use_pin_mosi; - _spi_pin_cs = use_pin_cs; + _spi_pin_sck = use_pin_sck; + _spi_pin_miso = use_pin_miso; + _spi_pin_mosi = use_pin_mosi; + _spi_pin_cs = use_pin_cs; - SPIhx.Instance = spiInstance; + SPIhx.Instance = spiInstance; - // chip-select is assumed to be handled by the software to be LOW during operations (if passed as -1 to spiInitEx) - // the pin is being adjusted to HIGH when SPI is doing critical maintenance operations - // (changing frame width, bit-ordering, etc). + // chip-select is assumed to be handled by the software to be LOW during operations (if passed as -1 to spiInitEx) + // the pin is being adjusted to HIGH when SPI is doing critical maintenance operations + // (changing frame width, bit-ordering, etc). - SPIhx.Init.Direction = (_spi_pin_miso == NC || _spi_pin_mosi == NC) ? SPI_DIRECTION_1LINE : SPI_DIRECTION_2LINES; + SPIhx.Init.Direction = (_spi_pin_miso == NC || _spi_pin_mosi == NC) ? SPI_DIRECTION_1LINE : SPI_DIRECTION_2LINES; - uint8_t clkdiv; - if (maxClockFreq > 0) { - spi_t tmp_spi; - tmp_spi.pin_sclk = name_sck_pin; - uint32_t spibasefreq = spi_getClkFreq(&tmp_spi); - clkdiv = _HAL_GetClockDivider( spibasefreq, maxClockFreq ); - } - else - { - bool has_clkdiv = false; + uint8_t clkdiv; + if (maxClockFreq > 0) { + spi_t tmp_spi; + tmp_spi.pin_sclk = name_sck_pin; + uint32_t spibasefreq = spi_getClkFreq(&tmp_spi); + clkdiv = _HAL_GetClockDivider( spibasefreq, maxClockFreq ); + } + else { + bool has_clkdiv = false; -#ifdef SPI1_BASE - if (spiInstance == SPI1) - { + #ifdef SPI1_BASE + if (spiInstance == SPI1) { clkdiv = SPI_BAUDRATEPRESCALER_4; has_clkdiv = true; } -#endif + #endif - if (!has_clkdiv) - { - clkdiv = SPI_BAUDRATEPRESCALER_2; - } - } + if (!has_clkdiv) clkdiv = SPI_BAUDRATEPRESCALER_2; + } - SPIhx.Init.BaudRatePrescaler = clkdiv; + SPIhx.Init.BaudRatePrescaler = clkdiv; - _HAL_SPI_Prepare(); + _HAL_SPI_Prepare(); - _spi_is_initialized = false; - _spi_is_transmit_sequence_initialized = false; - } + _spi_is_initialized = false; + _spi_is_transmit_sequence_initialized = false; +} - void spiInit(uint8_t spiRate, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { - // Use datarates Marlin uses - uint32_t clock; - switch (spiRate) { - case SPI_FULL_SPEED: clock = 20000000; break; // 13.9mhz=20000000 6.75mhz=10000000 3.38mhz=5000000 .833mhz=1000000 - case SPI_HALF_SPEED: clock = 5000000; break; - case SPI_QUARTER_SPEED: clock = 2500000; break; - case SPI_EIGHTH_SPEED: clock = 1250000; break; - case SPI_SPEED_5: clock = 625000; break; - case SPI_SPEED_6: clock = 300000; break; - default: - clock = 4000000; // Default from the SPI library - } - spiInitEx(clock, hint_sck, hint_miso, hint_mosi, hint_cs); +void spiInit(uint8_t spiRate, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { + // Use Marlin datarates + uint32_t clock; + switch (spiRate) { + case SPI_FULL_SPEED: clock = 20000000; break; // 13.9mhz=20000000 6.75mhz=10000000 3.38mhz=5000000 .833mhz=1000000 + case SPI_HALF_SPEED: clock = 5000000; break; + case SPI_QUARTER_SPEED: clock = 2500000; break; + case SPI_EIGHTH_SPEED: clock = 1250000; break; + case SPI_SPEED_5: clock = 625000; break; + case SPI_SPEED_6: clock = 300000; break; + default: + clock = 4000000; // Default from the SPI library } + spiInitEx(clock, hint_sck, hint_miso, hint_mosi, hint_cs); +} - void spiClose() { - // Shutdown the SPI peripheral. - _spiSecureShutdown(); +void spiClose() { + // Shutdown the SPI peripheral. + _spiSecureShutdown(); - // Close down hardware-related resources. - _HAL_SPI_EndOfTransaction(); - _HAL_SPI_Dismantle(); - _SPI_Leave( SPIhx.Instance ); - } + // Close down hardware-related resources. + _HAL_SPI_EndOfTransaction(); + _HAL_SPI_Dismantle(); + _SPI_Leave( SPIhx.Instance ); +} - void spiSetBitOrder(int bitOrder) { - if (bitOrder == SPI_BITORDER_MSB) { - if (SPIhx.Init.FirstBit == SPI_FIRSTBIT_MSB) return; - SPIhx.Init.FirstBit = SPI_FIRSTBIT_MSB; - } - else if (bitOrder == SPI_BITORDER_LSB) { - if (SPIhx.Init.FirstBit == SPI_FIRSTBIT_LSB) return; - SPIhx.Init.FirstBit = SPI_FIRSTBIT_LSB; - } +void spiSetBitOrder(int bitOrder) { + if (bitOrder == SPI_BITORDER_MSB) { + if (SPIhx.Init.FirstBit == SPI_FIRSTBIT_MSB) return; + SPIhx.Init.FirstBit = SPI_FIRSTBIT_MSB; + } + else if (bitOrder == SPI_BITORDER_LSB) { + if (SPIhx.Init.FirstBit == SPI_FIRSTBIT_LSB) return; + SPIhx.Init.FirstBit = SPI_FIRSTBIT_LSB; + } - // If the SPI is already enabled, then update it. - // When the SPI is initialized, the chip-select must be high aswell. - if (_spi_is_initialized) - { - _spiSecureShutdown(); + // If the SPI is already enabled, then update it. + // When the SPI is initialized, the chip-select must be high aswell. + if (_spi_is_initialized) { + _spiSecureShutdown(); - auto tmp_SPI_CR1 = SPIhx.Instance->CR1; + auto tmp_SPI_CR1 = SPIhx.Instance->CR1; - if (bitOrder == SPI_BITORDER_MSB) - tmp_SPI_CR1 &= ~_BV(7); - else - tmp_SPI_CR1 |= _BV(7); + if (bitOrder == SPI_BITORDER_MSB) + tmp_SPI_CR1 &= ~_BV(7); + else + tmp_SPI_CR1 |= _BV(7); - SPIhx.Instance->CR1 = tmp_SPI_CR1; + SPIhx.Instance->CR1 = tmp_SPI_CR1; - __HAL_SPI_ConfigDirection(); - __HAL_SPI_ENABLE(&SPIhx); + __HAL_SPI_ConfigDirection(); + __HAL_SPI_ENABLE(&SPIhx); - _spi_is_transmit_sequence_initialized = false; + _spi_is_transmit_sequence_initialized = false; - _spiSecureCSLeave(); - } + _spiSecureCSLeave(); } +} - void spiSetClockMode(int mode) { - bool changed = _HAL_SPI_InitClock(mode); +void spiSetClockMode(int mode) { + bool changed = _HAL_SPI_InitClock(mode); - if (!changed) return; + if (!changed) return; - if (_spi_is_initialized) { - _spiSecureShutdown(); + if (_spi_is_initialized) { + _spiSecureShutdown(); - auto tmp_SPI_CR1 = SPIhx.Instance->CR1; + auto tmp_SPI_CR1 = SPIhx.Instance->CR1; - if (mode == SPI_CLKMODE_0) { - tmp_SPI_CR1 &= ~0x03; - } - else if (mode == SPI_CLKMODE_1) { - tmp_SPI_CR1 &= ~0x02; - tmp_SPI_CR1 |= 0x01; - } - else if (mode == SPI_CLKMODE_2) { - tmp_SPI_CR1 &= ~0x01; - tmp_SPI_CR1 |= 0x02; - } - else if (mode == SPI_CLKMODE_3) { - tmp_SPI_CR1 |= 0x03; - } + if (mode == SPI_CLKMODE_0) { + tmp_SPI_CR1 &= ~0x03; + } + else if (mode == SPI_CLKMODE_1) { + tmp_SPI_CR1 &= ~0x02; + tmp_SPI_CR1 |= 0x01; + } + else if (mode == SPI_CLKMODE_2) { + tmp_SPI_CR1 &= ~0x01; + tmp_SPI_CR1 |= 0x02; + } + else if (mode == SPI_CLKMODE_3) { + tmp_SPI_CR1 |= 0x03; + } - SPIhx.Instance->CR1 = tmp_SPI_CR1; + SPIhx.Instance->CR1 = tmp_SPI_CR1; - __HAL_SPI_ConfigDirection(); - __HAL_SPI_ENABLE(&SPIhx); + __HAL_SPI_ConfigDirection(); + __HAL_SPI_ENABLE(&SPIhx); - _spi_is_transmit_sequence_initialized = false; + _spi_is_transmit_sequence_initialized = false; - _spiSecureCSLeave(); - } + _spiSecureCSLeave(); } +} - void spiEstablish() { - _HAL_SPI_UpdateTransaction(SPI_DATASIZE_8BIT); - } +void spiEstablish() { + _HAL_SPI_UpdateTransaction(SPI_DATASIZE_8BIT); +} #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) - static void _DMA_Interrupt( void ) - { + + static void _DMA_Interrupt(void) { DMA_TypeDef *DMA = DMAhx.DmaBaseAddress; uint32_t channelIndex = ((DMAhx.ChannelIndex>>2)+1); @@ -1029,10 +937,7 @@ extern "C" { info->async_busy = false; // Execute any transfer-complete callback. - if (cb) - { - cb( &DMAhx ); - } + if (cb) cb(&DMAhx); } // Error during transfer? else if (DMA_Channel_TXError(DMA, channelIndex)) { @@ -1052,53 +957,38 @@ extern "C" { info->async_busy = false; } } -#endif - - static void _HAL_SPI_CheckTransactionalError() { - if (TEST(SPIhx.Instance->SR, 3)) { - // Underrun. - _spiOnError(1); - } - if (TEST(SPIhx.Instance->SR, 4)) { - // CRC error. - _spiOnError(2); - } - if (TEST(SPIhx.Instance->SR, 5)) { - // Mode fault. - _spiOnError(3); - } - if (TEST(SPIhx.Instance->SR, 6)) { - // Overrun. - _spiOnError(4); - } - if (TEST(SPIhx.Instance->CR1, 6) == false) { - // SPI disabled??? - _spiOnError(10); - } - } - // Operates in both 8bit and 16bit modes. - template - static void _HAL_SPI_TransmitOnly(transmitType val) { +#endif // HAL_SPI_SUPPORTS_ASYNC - __IO transmitType *DR = (__IO transmitType*)&SPIhx.Instance->DR; +static void _HAL_SPI_CheckTransactionalError() { + if ( TEST(SPIhx.Instance->SR, 3)) _spiOnError( 1); // Underrun. + if ( TEST(SPIhx.Instance->SR, 4)) _spiOnError( 2); // CRC error. + if ( TEST(SPIhx.Instance->SR, 5)) _spiOnError( 3); // Mode fault. + if ( TEST(SPIhx.Instance->SR, 6)) _spiOnError( 4); // Overrun. + if (!TEST(SPIhx.Instance->CR1, 6)) _spiOnError(10); // SPI disabled??? +} - if (_spi_is_transmit_sequence_initialized) - { - spi_monitored_loop lw; - while (!__HAL_SPI_GET_FLAG(&SPIhx, SPI_FLAG_TXE)) { lw.update(4); } - } +// Operates in both 8bit and 16bit modes. +template +static void _HAL_SPI_TransmitOnly(transmitType val) { - *DR = val; + __IO transmitType *DR = (__IO transmitType*)&SPIhx.Instance->DR; - _spi_is_transmit_sequence_initialized = true; + if (_spi_is_transmit_sequence_initialized) { + spi_monitored_loop lw; + while (!__HAL_SPI_GET_FLAG(&SPIhx, SPI_FLAG_TXE)) { lw.update(4); } } - template - static void _HAL_SPI_Transmit(transmitType val) { - _HAL_SPI_TransmitOnly ( val ); + *DR = val; -#ifndef SPI_ENABLE_OPTIMIZATIONS + _spi_is_transmit_sequence_initialized = true; +} + +template +static void _HAL_SPI_Transmit(transmitType val) { + _HAL_SPI_TransmitOnly ( val ); + + #ifndef SPI_ENABLE_OPTIMIZATIONS // Perform the regular transactional pattern. if (SPIhx.Init.Direction == SPI_DIRECTION_2LINES) { __IO transmitType *DR = (__IO transmitType*)&SPIhx.Instance->DR; @@ -1109,152 +999,149 @@ extern "C" { transmitType tmp = *DR; (void)tmp; } -#else + #else // Do some OVRFLAG stuff that is regularly found on the internet. if (SPIhx.Init.Direction == SPI_DIRECTION_2LINES) __HAL_SPI_CLEAR_OVRFLAG(&SPIhx); // Clear overrun flag in 2 Lines communication mode because received data is not read -#endif + #endif - _HAL_SPI_CheckTransactionalError(); - } + _HAL_SPI_CheckTransactionalError(); +} - template - static transmitType _HAL_SPI_Receive(transmitType txval) { +template +static transmitType _HAL_SPI_Receive(transmitType txval) { - __IO transmitType *DR = (__IO transmitType*)&SPIhx.Instance->DR; + __IO transmitType *DR = (__IO transmitType*)&SPIhx.Instance->DR; - if (SPIhx.Init.Direction == SPI_DIRECTION_2LINES) - { - _HAL_SPI_TransmitOnly ( txval ); - } + if (SPIhx.Init.Direction == SPI_DIRECTION_2LINES) + _HAL_SPI_TransmitOnly (txval); - spi_monitored_loop lw; - while (!__HAL_SPI_GET_FLAG(&SPIhx, SPI_FLAG_RXNE)) { lw.update(6); } + spi_monitored_loop lw; + while (!__HAL_SPI_GET_FLAG(&SPIhx, SPI_FLAG_RXNE)) { lw.update(6); } - transmitType result = *DR; + transmitType result = *DR; - _HAL_SPI_CheckTransactionalError(); + _HAL_SPI_CheckTransactionalError(); - return result; - } + return result; +} - void spiSend(uint8_t b) { - if (_spi_pin_mosi == NC) return; - _SPI_AsyncBarrier(); - _HAL_SPI_UpdateTransaction(SPI_DATASIZE_8BIT); - _HAL_SPI_Transmit (b); - } +void spiSend(uint8_t b) { + if (_spi_pin_mosi == NC) return; + _SPI_AsyncBarrier(); + _HAL_SPI_UpdateTransaction(SPI_DATASIZE_8BIT); + _HAL_SPI_Transmit (b); +} - void spiSend16(uint16_t v) { - if (_spi_pin_mosi == NC) return; - _SPI_AsyncBarrier(); - _HAL_SPI_UpdateTransaction(SPI_DATASIZE_16BIT); - _HAL_SPI_Transmit (v); - } +void spiSend16(uint16_t v) { + if (_spi_pin_mosi == NC) return; + _SPI_AsyncBarrier(); + _HAL_SPI_UpdateTransaction(SPI_DATASIZE_16BIT); + _HAL_SPI_Transmit (v); +} - uint8_t spiRec(uint8_t txval) { - if (_spi_pin_miso == NC) return 0; - _SPI_AsyncBarrier(); - _HAL_SPI_UpdateTransaction(SPI_DATASIZE_8BIT); - uint8_t res = _HAL_SPI_Receive (txval); - return res; - } +uint8_t spiRec(uint8_t txval) { + if (_spi_pin_miso == NC) return 0; + _SPI_AsyncBarrier(); + _HAL_SPI_UpdateTransaction(SPI_DATASIZE_8BIT); + uint8_t res = _HAL_SPI_Receive (txval); + return res; +} - uint16_t spiRec16(uint16_t txval) { - if (_spi_pin_miso == NC) return 0; - _SPI_AsyncBarrier(); - _HAL_SPI_UpdateTransaction(SPI_DATASIZE_16BIT); - uint16_t res = _HAL_SPI_Receive (txval); - return res; - } +uint16_t spiRec16(uint16_t txval) { + if (_spi_pin_miso == NC) return 0; + _SPI_AsyncBarrier(); + _HAL_SPI_UpdateTransaction(SPI_DATASIZE_16BIT); + uint16_t res = _HAL_SPI_Receive (txval); + return res; +} - void spiRead(uint8_t *buf, uint16_t bufsize, uint8_t txval) { - if (_spi_pin_miso == NC) { - memset(buf, 0, bufsize); - } - else { - _SPI_AsyncBarrier(); - _HAL_SPI_UpdateTransaction(SPI_DATASIZE_8BIT); - for (uint16_t n = 0; n < bufsize; n++) - buf[n] = _HAL_SPI_Receive (txval); - } +void spiRead(uint8_t *buf, uint16_t bufsize, uint8_t txval) { + if (_spi_pin_miso == NC) { + memset(buf, 0, bufsize); } - - void spiSendBlock(uint8_t token, const uint8_t *block) { - if (_spi_pin_mosi == NC) return; + else { _SPI_AsyncBarrier(); _HAL_SPI_UpdateTransaction(SPI_DATASIZE_8BIT); - _HAL_SPI_Transmit (token); - for (uint16_t n = 0; n < 512; n++) - _HAL_SPI_Transmit ( block[n] ); + for (uint16_t n = 0; n < bufsize; n++) + buf[n] = _HAL_SPI_Receive (txval); } +} - static void _HAL_DMA_ConfigureTransfer( bool memInc, uint16_t dataSize ) { - DMAhx.Init.MemInc = ( memInc ? DMA_MINC_ENABLE : DMA_MINC_DISABLE ); // if true send one number many times, else an array. - DMAhx.Init.PeriphDataAlignment = (dataSize == SPI_DATASIZE_8BIT) ? DMA_PDATAALIGN_BYTE : DMA_PDATAALIGN_HALFWORD; - DMAhx.Init.MemDataAlignment = (dataSize == SPI_DATASIZE_8BIT) ? DMA_MDATAALIGN_BYTE : DMA_MDATAALIGN_HALFWORD; - HAL_DMA_Init(&DMAhx); - } +void spiSendBlock(uint8_t token, const uint8_t *block) { + if (_spi_pin_mosi == NC) return; + _SPI_AsyncBarrier(); + _HAL_SPI_UpdateTransaction(SPI_DATASIZE_8BIT); + _HAL_SPI_Transmit (token); + for (uint16_t n = 0; n < 512; n++) + _HAL_SPI_Transmit ( block[n] ); +} - // Blocking. - static void _HAL_DMA_Transfer( const void *buf, uint32_t bufcnt, bool memInc, uint16_t dataSize ) { - _HAL_SPI_UpdateTransaction(dataSize); +static void _HAL_DMA_ConfigureTransfer( bool memInc, uint16_t dataSize ) { + DMAhx.Init.MemInc = ( memInc ? DMA_MINC_ENABLE : DMA_MINC_DISABLE ); // if true send one number many times, else an array. + DMAhx.Init.PeriphDataAlignment = (dataSize == SPI_DATASIZE_8BIT) ? DMA_PDATAALIGN_BYTE : DMA_PDATAALIGN_HALFWORD; + DMAhx.Init.MemDataAlignment = (dataSize == SPI_DATASIZE_8BIT) ? DMA_MDATAALIGN_BYTE : DMA_MDATAALIGN_HALFWORD; + HAL_DMA_Init(&DMAhx); +} - _HAL_DMA_ConfigureTransfer(memInc, dataSize); +// Blocking. +static void _HAL_DMA_Transfer( const void *buf, uint32_t bufcnt, bool memInc, uint16_t dataSize ) { + _HAL_SPI_UpdateTransaction(dataSize); - HAL_DMA_Start(&DMAhx, (uint32_t)buf, (uint32_t)&(SPIhx.Instance->DR), bufcnt); + _HAL_DMA_ConfigureTransfer(memInc, dataSize); - SET_BIT(SPIhx.Instance->CR2, SPI_CR2_TXDMAEN); // Enable Tx DMA Request + HAL_DMA_Start(&DMAhx, (uint32_t)buf, (uint32_t)&(SPIhx.Instance->DR), bufcnt); - HAL_DMA_PollForTransfer(&DMAhx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY); + SET_BIT(SPIhx.Instance->CR2, SPI_CR2_TXDMAEN); // Enable Tx DMA Request - HAL_DMA_DeInit(&DMAhx); + HAL_DMA_PollForTransfer(&DMAhx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY); - spi_monitored_loop lw; - while ( __HAL_SPI_GET_FLAG(&SPIhx, SPI_FLAG_BSY)) { lw.update(8); } + HAL_DMA_DeInit(&DMAhx); - // Since we have only transmitted data it is sure that we got the OVRFLAG. - // Thus clear it. - if (SPIhx.Init.Direction == SPI_DIRECTION_2LINES && TEST(SPIhx.Instance->SR, 6)) - __HAL_SPI_CLEAR_OVRFLAG(&SPIhx); + spi_monitored_loop lw; + while ( __HAL_SPI_GET_FLAG(&SPIhx, SPI_FLAG_BSY)) { lw.update(8); } - _spi_is_transmit_sequence_initialized = true; - } + // Since we have only transmitted data it is sure that we got the OVRFLAG. + // Thus clear it. + if (SPIhx.Init.Direction == SPI_DIRECTION_2LINES && TEST(SPIhx.Instance->SR, 6)) + __HAL_SPI_CLEAR_OVRFLAG(&SPIhx); - void spiWrite(const uint8_t *buf, uint16_t bufcnt) { - if (_spi_pin_mosi == NC) return; - if (bufcnt == 0) return; - _SPI_AsyncBarrier(); - _HAL_DMA_Transfer( buf, bufcnt, true, SPI_DATASIZE_8BIT ); - } + _spi_is_transmit_sequence_initialized = true; +} - void spiWrite16(const uint16_t *buf, uint16_t bufcnt) { - if (_spi_pin_mosi == NC) return; - if (bufcnt == 0) return; - _SPI_AsyncBarrier(); - _HAL_DMA_Transfer( buf, bufcnt, true, SPI_DATASIZE_16BIT ); - } +void spiWrite(const uint8_t *buf, uint16_t bufcnt) { + if (_spi_pin_mosi == NC) return; + if (bufcnt == 0) return; + _SPI_AsyncBarrier(); + _HAL_DMA_Transfer( buf, bufcnt, true, SPI_DATASIZE_8BIT ); +} - void spiWriteRepeat(uint8_t val, uint16_t repcnt) { - if (_spi_pin_mosi == NC) return; - if (repcnt == 0) return; - _SPI_AsyncBarrier(); - // If async then we would need a static variable here. - _HAL_DMA_Transfer( &val, repcnt, false, SPI_DATASIZE_8BIT ); - } +void spiWrite16(const uint16_t *buf, uint16_t bufcnt) { + if (_spi_pin_mosi == NC) return; + if (bufcnt == 0) return; + _SPI_AsyncBarrier(); + _HAL_DMA_Transfer( buf, bufcnt, true, SPI_DATASIZE_16BIT ); +} - void spiWriteRepeat16(uint16_t val, uint16_t repcnt) { - if (_spi_pin_mosi == NC) return; - if (repcnt == 0) return; - _SPI_AsyncBarrier(); - // If async then we would need a static variable here. - _HAL_DMA_Transfer( &val, repcnt, false, SPI_DATASIZE_16BIT ); - } +void spiWriteRepeat(uint8_t val, uint16_t repcnt) { + if (_spi_pin_mosi == NC) return; + if (repcnt == 0) return; + _SPI_AsyncBarrier(); + // If async then we would need a static variable here. + _HAL_DMA_Transfer( &val, repcnt, false, SPI_DATASIZE_8BIT ); +} + +void spiWriteRepeat16(uint16_t val, uint16_t repcnt) { + if (_spi_pin_mosi == NC) return; + if (repcnt == 0) return; + _SPI_AsyncBarrier(); + // If async then we would need a static variable here. + _HAL_DMA_Transfer( &val, repcnt, false, SPI_DATASIZE_16BIT ); +} #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) static void _DMA_CompleteCallback( DMA_HandleTypeDef *_ ) { - auto *spiInfo = SPI_GetRuntimeInfo(SPIhx.Instance); if (auto *cb = spiInfo->asyncCompleteCallback) { @@ -1311,13 +1198,11 @@ extern "C" { } void spiAsyncAbort() { - cli(); auto *spiInfo = SPI_GetRuntimeInfo(SPIhx.Instance); - if (spiInfo->async_busy) - { + if (spiInfo->async_busy) { HAL_DMA_Abort(&DMAhx); HAL_DMA_DeInit(&DMAhx); @@ -1338,17 +1223,16 @@ extern "C" { bool spiAsyncIsRunning() { auto *spiInfo = SPI_GetRuntimeInfo(SPIhx.Instance); - return spiInfo->async_busy; } #endif // HAL_SPI_SUPPORTS_ASYNC - // DMA async semantics are actually really dangerous, here is why: - // - you need to wait for DMA transfers to finish, which devs might forget - // - it is invalid to reuse the memory while DMA is operating on it, which devs might forget - // Thus code depending on DMA needs very special attention to get it right. +// DMA async semantics are actually really dangerous, here is why: +// - you need to wait for DMA transfers to finish, which devs might forget +// - it is invalid to reuse the memory while DMA is operating on it, which devs might forget +// Thus code depending on DMA needs very special attention to get it right. -#endif +#endif // !SOFTWARE_SPI && (STM32F1xx || STM32F4xx) && !HALSPI_HW_GENERIC #endif // HAL_STM32 diff --git a/Marlin/src/HAL/STM32/HAL_SPI_HWgen.cpp b/Marlin/src/HAL/STM32/HAL_SPI_HWgen.cpp index 1b781cf6c0ea..162f5c985cc8 100644 --- a/Marlin/src/HAL/STM32/HAL_SPI_HWgen.cpp +++ b/Marlin/src/HAL/STM32/HAL_SPI_HWgen.cpp @@ -1,6 +1,6 @@ /** * Marlin 3D Printer Firmware - * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * Based on Sprinter and grbl. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm @@ -30,8 +30,8 @@ // Public functions // ------------------------ - // If properly ported, use fast HW SPI implementation originally found in STM32 tft_spi.cpp -#if !ENABLED(SOFTWARE_SPI) && (!(defined(STM32F1xx) || defined(STM32F4xx)) || ENABLED(HALSPI_HW_GENERIC)) +// If properly ported, use fast HW SPI implementation originally found in STM32 tft_spi.cpp +#if DISABLED(SOFTWARE_SPI) && (!(defined(STM32F1xx) || defined(STM32F4xx)) || ENABLED(HALSPI_HW_GENERIC)) #include @@ -41,27 +41,27 @@ [[maybe_unused]] static void _spiOnError(unsigned int beep_code = 0) { for (;;) { -#if defined(HALSPI_DO_ERRORBEEPS) && PIN_EXISTS(BEEPER) - OUT_WRITE(BEEPER_PIN, HIGH); - delay(500); - OUT_WRITE(BEEPER_PIN, LOW); - delay(200); - OUT_WRITE(BEEPER_PIN, HIGH); - delay(200); - OUT_WRITE(BEEPER_PIN, LOW); - delay(1000); - for (unsigned int n = 0; n < beep_code; n++) { + #if defined(HALSPI_DO_ERRORBEEPS) && PIN_EXISTS(BEEPER) OUT_WRITE(BEEPER_PIN, HIGH); - delay(200); + delay(500); OUT_WRITE(BEEPER_PIN, LOW); delay(200); - } - delay(800); - OUT_WRITE(BEEPER_PIN, HIGH); - delay(1000); - OUT_WRITE(BEEPER_PIN, LOW); - delay(2000); -#endif + OUT_WRITE(BEEPER_PIN, HIGH); + delay(200); + OUT_WRITE(BEEPER_PIN, LOW); + delay(1000); + for (unsigned int n = 0; n < beep_code; n++) { + OUT_WRITE(BEEPER_PIN, HIGH); + delay(200); + OUT_WRITE(BEEPER_PIN, LOW); + delay(200); + } + delay(800); + OUT_WRITE(BEEPER_PIN, HIGH); + delay(1000); + OUT_WRITE(BEEPER_PIN, LOW); + delay(2000); + #endif } } @@ -89,13 +89,13 @@ _spi_clock = maxClockFreq; spiConfig = SPISettings(maxClockFreq, MSBFIRST, SPI_MODE0); -#if ENABLED(MAPLE_STM32F1) - SPI.setModuleByMOSIPin((hint_mosi != -1) ? hint_mosi : SD_MOSI_PIN); -#else - SPI.setMISO((hint_miso != -1) ? hint_miso : SD_MISO_PIN); - SPI.setMOSI((hint_mosi != -1) ? hint_mosi : SD_MOSI_PIN); - SPI.setSCLK((hint_sck != -1) ? hint_sck : SD_SCK_PIN); -#endif + #if ENABLED(MAPLE_STM32F1) + SPI.setModuleByMOSIPin((hint_mosi != -1) ? hint_mosi : SD_MOSI_PIN); + #else + SPI.setMISO((hint_miso != -1) ? hint_miso : SD_MISO_PIN); + SPI.setMOSI((hint_mosi != -1) ? hint_mosi : SD_MOSI_PIN); + SPI.setSCLK((hint_sck != -1) ? hint_sck : SD_SCK_PIN); + #endif SPI.begin(); SPI.beginTransaction(spiConfig); @@ -105,7 +105,7 @@ void spiInit(uint8_t spiRate, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { // Ignore chip-select because the software manages it already. - // Use datarates Marlin uses + // Use Marlin datarates uint32_t clock; switch (spiRate) { case SPI_FULL_SPEED: clock = 20000000; break; // 13.9mhz=20000000 6.75mhz=10000000 3.38mhz=5000000 .833mhz=1000000 @@ -156,17 +156,17 @@ * @details */ uint8_t spiRec(uint8_t txval) { -#ifdef MAPLE_STM32F1 - SPI.setDataSize(DATA_SIZE_8BIT); -#endif + #ifdef MAPLE_STM32F1 + SPI.setDataSize(DATA_SIZE_8BIT); + #endif uint8_t returnByte = SPI.transfer(txval); return returnByte; } uint16_t spiRec16(uint16_t txval) { -#ifdef MAPLE_STM32F1 - SPI.setDataSize(DATA_SIZE_16BIT); -#endif + #ifdef MAPLE_STM32F1 + SPI.setDataSize(DATA_SIZE_16BIT); + #endif return SPI.transfer16(txval); } @@ -182,12 +182,12 @@ void spiRead(uint8_t *buf, uint16_t nbyte, uint8_t txval) { if (nbyte == 0) return; memset(buf, txval, nbyte); -#ifdef MAPLE_STM32F1 - SPI.setDataSize(DATA_SIZE_8BIT); - SPI.dmaTransfer(buf, buf, nbyte); -#else - SPI.transfer(buf, nbyte); -#endif + #ifdef MAPLE_STM32F1 + SPI.setDataSize(DATA_SIZE_8BIT); + SPI.dmaTransfer(buf, buf, nbyte); + #else + SPI.transfer(buf, nbyte); + #endif } /** @@ -206,49 +206,49 @@ } void spiWrite(const uint8_t *buf, uint16_t numbytes) { -#ifdef MAPLE_STM32F1 - SPI.setDataSize(DATA_SIZE_8BIT); - SPI.dmaSend(buf, numbytes, true); -#else - void *inout_buf = malloc(numbytes); - if (inout_buf == nullptr) - _spiOnError(); - memcpy(inout_buf, buf, numbytes); - // Generic transfer, non-DMA. - SPI.transfer(inout_buf, numbytes); - free(inout_buf); -#endif + #ifdef MAPLE_STM32F1 + SPI.setDataSize(DATA_SIZE_8BIT); + SPI.dmaSend(buf, numbytes, true); + #else + void *inout_buf = malloc(numbytes); + if (inout_buf == nullptr) + _spiOnError(); + memcpy(inout_buf, buf, numbytes); + // Generic transfer, non-DMA. + SPI.transfer(inout_buf, numbytes); + free(inout_buf); + #endif } void spiWrite16(const uint16_t *buf, uint16_t numtx) { -#ifdef MAPLE_STM32F1 - SPI.setDataSize(DATA_SIZE_16BIT); - SPI.dmaSend(buf, numtx, true); -#else - for (uint32_t n = 0; n < numtx; n++) { - SPI.transfer16(buf[n]); - } -#endif + #ifdef MAPLE_STM32F1 + SPI.setDataSize(DATA_SIZE_16BIT); + SPI.dmaSend(buf, numtx, true); + #else + for (uint32_t n = 0; n < numtx; n++) { + SPI.transfer16(buf[n]); + } + #endif } void spiWriteRepeat(uint8_t val, uint16_t repcnt) { -#ifdef MAPLE_STM32F1 - SPI.setDataSize(DATA_SIZE_8BIT); - SPI.dmaSend(&val, repcnt, false); -#else - for (uint16_t n = 0; n < repcnt; n++) - SPI.transfer(val); -#endif + #ifdef MAPLE_STM32F1 + SPI.setDataSize(DATA_SIZE_8BIT); + SPI.dmaSend(&val, repcnt, false); + #else + for (uint16_t n = 0; n < repcnt; n++) + SPI.transfer(val); + #endif } void spiWriteRepeat16(uint16_t val, uint16_t repcnt) { -#ifdef MAPLE_STM32F1 - SPI.setDataSize(DATA_SIZE_16BIT); - SPI.dmaSend(&val, repcnt, false); -#else - for (uint16_t n = 0; n < repcnt; n++) - SPI.transfer16(val); -#endif + #ifdef MAPLE_STM32F1 + SPI.setDataSize(DATA_SIZE_16BIT); + SPI.dmaSend(&val, repcnt, false); + #else + for (uint16_t n = 0; n < repcnt; n++) + SPI.transfer16(val); + #endif } /** @@ -261,15 +261,15 @@ */ void spiSendBlock(uint8_t token, const uint8_t *buf) { SPI.transfer(token); -#ifdef MAPLE_STM32F1 - SPI.setDataSize(DATA_SIZE_8BIT); - SPI.dmaSend(buf, 512, true); -#else - uint8_t rxBuf[512]; - SPI.transfer((uint8_t*)buf, rxBuf, 512); -#endif + #ifdef MAPLE_STM32F1 + SPI.setDataSize(DATA_SIZE_8BIT); + SPI.dmaSend(buf, 512, true); + #else + uint8_t rxBuf[512]; + SPI.transfer((uint8_t*)buf, rxBuf, 512); + #endif } #endif // !FAST HW SPI, SOFTWARE_SPI -#endif // HAL_STM32, MAPLE_STM32F1 +#endif // HAL_STM32 || MAPLE_STM32F1 diff --git a/Marlin/src/HAL/STM32/HAL_SPI_SW.cpp b/Marlin/src/HAL/STM32/HAL_SPI_SW.cpp index 3e73078496c1..c8585e26a93f 100644 --- a/Marlin/src/HAL/STM32/HAL_SPI_SW.cpp +++ b/Marlin/src/HAL/STM32/HAL_SPI_SW.cpp @@ -1,6 +1,6 @@ /** * Marlin 3D Printer Firmware - * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * Based on Sprinter and grbl. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm @@ -32,17 +32,17 @@ #if ENABLED(SOFTWARE_SPI) - #include +#include - // ------------------------ - // Software SPI - // ------------------------ +// ------------------------ +// Software SPI +// ------------------------ - // TODO: this software SPI is really bad... it tries to use SPI clock-mode 3 only...?????? +// TODO: this software SPI is really bad... it tries to use SPI clock-mode 3 only...?????? - static void _spiOnError(unsigned int beep_code = 0) { - for (;;) { -#if defined(HALSPI_DO_ERRORBEEPS) && PIN_EXISTS(BEEPER) +static void _spiOnError(unsigned int beep_code = 0) { + for (;;) { + #if defined(HALSPI_DO_ERRORBEEPS) && PIN_EXISTS(BEEPER) OUT_WRITE(BEEPER_PIN, HIGH); delay(500); OUT_WRITE(BEEPER_PIN, LOW); @@ -62,199 +62,185 @@ delay(1000); OUT_WRITE(BEEPER_PIN, LOW); delay(2000); -#endif - } - } - - #include "../shared/Delay.h" - - void spiBegin(void) { - #if PIN_EXISTS(SD_SS) - OUT_WRITE(SD_SS_PIN, HIGH); #endif - OUT_WRITE(SD_SCK_PIN, HIGH); - SET_INPUT(SD_MISO_PIN); - OUT_WRITE(SD_MOSI_PIN, HIGH); } - - // Use function with compile-time value so we can actually reach the desired frequency - // Need to adjust this a little bit: on a 72MHz clock, we have 14ns/clock - // and we'll use ~3 cycles to jump to the method and going back, so it'll take ~40ns from the given clock here - #define CALLING_COST_NS (3U * 1000000000U) / (F_CPU) - static void (*delaySPIFunc)(); - void delaySPI_125() { DELAY_NS(125 - CALLING_COST_NS); } - void delaySPI_250() { DELAY_NS(250 - CALLING_COST_NS); } - void delaySPI_500() { DELAY_NS(500 - CALLING_COST_NS); } - void delaySPI_1000() { DELAY_NS(1000 - CALLING_COST_NS); } - void delaySPI_2000() { DELAY_NS(2000 - CALLING_COST_NS); } - void delaySPI_4000() { DELAY_NS(4000 - CALLING_COST_NS); } - - static int _spi_bit_order = SPI_BITORDER_DEFAULT; - - void spiInit(uint8_t spiRate, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { - // Use datarates Marlin uses - switch (spiRate) { - case SPI_FULL_SPEED: delaySPIFunc = &delaySPI_125; break; // desired: 8,000,000 actual: ~1.1M - case SPI_HALF_SPEED: delaySPIFunc = &delaySPI_125; break; // desired: 4,000,000 actual: ~1.1M - case SPI_QUARTER_SPEED:delaySPIFunc = &delaySPI_250; break; // desired: 2,000,000 actual: ~890K - case SPI_EIGHTH_SPEED: delaySPIFunc = &delaySPI_500; break; // desired: 1,000,000 actual: ~590K - case SPI_SPEED_5: delaySPIFunc = &delaySPI_1000; break; // desired: 500,000 actual: ~360K - case SPI_SPEED_6: delaySPIFunc = &delaySPI_2000; break; // desired: 250,000 actual: ~210K - default: delaySPIFunc = &delaySPI_4000; break; // desired: 125,000 actual: ~123K - } - // TODO: there is an issue on Github by BTT(?) that this does not use software but hardware SPI. - // we are kind of lying to the user here, is that OK? -#ifdef MAPLE_STM32F1 +} + +#include "../shared/Delay.h" + +void spiBegin(void) { + #if PIN_EXISTS(SD_SS) + OUT_WRITE(SD_SS_PIN, HIGH); + #endif + OUT_WRITE(SD_SCK_PIN, HIGH); + SET_INPUT(SD_MISO_PIN); + OUT_WRITE(SD_MOSI_PIN, HIGH); +} + +// Use function with compile-time value so we can actually reach the desired frequency +// Need to adjust this a little bit: on a 72MHz clock, we have 14ns/clock +// and we'll use ~3 cycles to jump to the method and going back, so it'll take ~40ns from the given clock here +#define CALLING_COST_NS (3U * 1000000000U) / (F_CPU) +static void (*delaySPIFunc)(); +void delaySPI_125() { DELAY_NS(125 - CALLING_COST_NS); } +void delaySPI_250() { DELAY_NS(250 - CALLING_COST_NS); } +void delaySPI_500() { DELAY_NS(500 - CALLING_COST_NS); } +void delaySPI_1000() { DELAY_NS(1000 - CALLING_COST_NS); } +void delaySPI_2000() { DELAY_NS(2000 - CALLING_COST_NS); } +void delaySPI_4000() { DELAY_NS(4000 - CALLING_COST_NS); } + +static int _spi_bit_order = SPI_BITORDER_DEFAULT; + +void spiInit(uint8_t spiRate, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { + // Use Marlin datarates + switch (spiRate) { + case SPI_FULL_SPEED: delaySPIFunc = &delaySPI_125; break; // desired: 8,000,000 actual: ~1.1M + case SPI_HALF_SPEED: delaySPIFunc = &delaySPI_125; break; // desired: 4,000,000 actual: ~1.1M + case SPI_QUARTER_SPEED:delaySPIFunc = &delaySPI_250; break; // desired: 2,000,000 actual: ~890K + case SPI_EIGHTH_SPEED: delaySPIFunc = &delaySPI_500; break; // desired: 1,000,000 actual: ~590K + case SPI_SPEED_5: delaySPIFunc = &delaySPI_1000; break; // desired: 500,000 actual: ~360K + case SPI_SPEED_6: delaySPIFunc = &delaySPI_2000; break; // desired: 250,000 actual: ~210K + default: delaySPIFunc = &delaySPI_4000; break; // desired: 125,000 actual: ~123K + } + // TODO: there is an issue on Github by BTT(?) that this does not use software but hardware SPI. + // we are kind of lying to the user here, is that OK? + #ifdef MAPLE_STM32F1 SPI.setModuleByMOSIPin(hint_mosi); -#else + #else SPI.setMISO(hint_miso); SPI.setMOSI(hint_mosi); SPI.setSCLK(hint_sck); -#endif - SPI.begin(); - } - - void spiInitEx(uint32_t maxClockFreq, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { - // Use datarates Marlin uses - uint8_t spiRate; - if (maxClockFreq >= 20000000) { - spiRate = SPI_FULL_SPEED; - } - else if (maxClockFreq >= 5000000) { - spiRate = SPI_HALF_SPEED; - } - else if (maxClockFreq >= 2500000) { - spiRate = SPI_QUARTER_SPEED; - } - else if (maxClockFreq >= 1250000) { - spiRate = SPI_EIGHTH_SPEED; - } - else if (maxClockFreq >= 625000) { - spiRate = SPI_SPEED_5; - } - else if (maxClockFreq >= 300000) { - spiRate = SPI_SPEED_6; - } - else - spiRate = SPI_SPEED_6; - - spiInit(spiRate, hint_sck, hint_miso, hint_mosi, hint_cs); - } - - void spiClose() { - SPI.end(); - } - - void spiSetupChipSelect(int pin) { - OUT_WRITE(pin, HIGH); - } - - void spiSetBitOrder(int bitOrder) { - _spi_bit_order = bitOrder; - } - - void spiSetClockMode(int clockMode) { - if (clockMode != SPI_CLKMODE_3) - _spiOnError(); - } - - uint8_t HAL_SPI_STM32_SpiTransfer_Mode_3(uint8_t b) { // using Mode 3 - bool msb = ( _spi_bit_order == SPI_BITORDER_MSB ); - uint8_t result = 0; - for (uint8_t bits = 0; bits < 8; bits++) { - int bitidx = ( msb ? 7-bits : bits ); - WRITE(SD_SCK_PIN, LOW); - WRITE(SD_MOSI_PIN, (b & ( 1 << bitidx )) != 0); - - delaySPIFunc(); - WRITE(SD_SCK_PIN, HIGH); - delaySPIFunc(); - - result |= ( (READ(SD_MISO_PIN) != 0) << bitidx ); - } - DELAY_NS(125); - return result; - } - - uint16_t HAL_SPI_STM32_SpiTransfer_Mode_3_16bits(uint16_t v) { // using Mode 3 - bool msb = ( _spi_bit_order == SPI_BITORDER_MSB ); - uint16_t result = 0; - for (uint8_t bits = 0; bits < 16; bits++) { - int bitidx = ( msb ? 15-bits : bits ); - WRITE(SD_SCK_PIN, LOW); - WRITE(SD_MOSI_PIN, (v & ( 1 << bitidx )) != 0); - - delaySPIFunc(); - WRITE(SD_SCK_PIN, HIGH); - delaySPIFunc(); - - result |= ( (READ(SD_MISO_PIN) != 0) << bitidx ); - } - DELAY_NS(125); - return result; - } - - // Soft SPI receive byte - uint8_t spiRec(uint8_t txval) { - hal.isr_off(); // No interrupts during byte receive - const uint8_t data = HAL_SPI_STM32_SpiTransfer_Mode_3(txval); - hal.isr_on(); // Enable interrupts - return data; - } - - uint16_t spiRec16(uint16_t txval) { - hal.isr_off(); - uint16_t data = HAL_SPI_STM32_SpiTransfer_Mode_3_16bits(txval); - hal.isr_on(); - return data; - } - - // Soft SPI read data - void spiRead(uint8_t *buf, uint16_t nbyte, uint8_t txval) { - for (uint16_t i = 0; i < nbyte; i++) - buf[i] = spiRec(txval); - } - - // Soft SPI send byte - void spiSend(uint8_t data) { - hal.isr_off(); // No interrupts during byte send - HAL_SPI_STM32_SpiTransfer_Mode_3(data); // Don't care what is received - hal.isr_on(); // Enable interrupts - } - - void spiSend16(uint16_t data) { - hal.isr_off(); - HAL_SPI_STM32_SpiTransfer_Mode_3_16bits(data); - hal.isr_on(); - } - - // Soft SPI send block - void spiSendBlock(uint8_t token, const uint8_t *buf) { - spiSend(token); - for (uint16_t i = 0; i < 512; i++) - spiSend(buf[i]); - } - - void spiWrite(const uint8_t *buf, uint16_t cnt) { - for (uint16_t n = 0; n < cnt; n++) - spiSend(buf[n]); - } - - void spiWrite16(const uint16_t *buf, uint16_t cnt) { - for (uint16_t n = 0; n < cnt; n++) - spiSend16(buf[n]); - } - - void spiWriteRepeat(uint8_t val, uint16_t repcnt) { - for (uint16_t n = 0; n < repcnt; n++) - spiSend(val); - } - - void spiWriteRepeat16(uint16_t val, uint16_t repcnt) { - for (uint16_t n = 0; n < repcnt; n++) - spiSend16(val); - } - -#endif - + #endif + SPI.begin(); +} + +void spiInitEx(uint32_t maxClockFreq, int hint_sck, int hint_miso, int hint_mosi, int hint_cs) { + // Use Marlin datarates + uint8_t spiRate; + if (maxClockFreq >= 20000000) spiRate = SPI_FULL_SPEED; + else if (maxClockFreq >= 5000000) spiRate = SPI_HALF_SPEED; + else if (maxClockFreq >= 2500000) spiRate = SPI_QUARTER_SPEED; + else if (maxClockFreq >= 1250000) spiRate = SPI_EIGHTH_SPEED; + else if (maxClockFreq >= 625000) spiRate = SPI_SPEED_5; + else if (maxClockFreq >= 300000) spiRate = SPI_SPEED_6; + else spiRate = SPI_SPEED_6; + + spiInit(spiRate, hint_sck, hint_miso, hint_mosi, hint_cs); +} + +void spiClose() { + SPI.end(); +} + +void spiSetupChipSelect(int pin) { + OUT_WRITE(pin, HIGH); +} + +void spiSetBitOrder(int bitOrder) { + _spi_bit_order = bitOrder; +} + +void spiSetClockMode(int clockMode) { + if (clockMode != SPI_CLKMODE_3) + _spiOnError(); +} + +uint8_t HAL_SPI_STM32_SpiTransfer_Mode_3(uint8_t b) { // using Mode 3 + bool msb = ( _spi_bit_order == SPI_BITORDER_MSB ); + uint8_t result = 0; + for (uint8_t bits = 0; bits < 8; bits++) { + int bitidx = ( msb ? 7-bits : bits ); + WRITE(SD_SCK_PIN, LOW); + WRITE(SD_MOSI_PIN, (b & ( 1 << bitidx )) != 0); + + delaySPIFunc(); + WRITE(SD_SCK_PIN, HIGH); + delaySPIFunc(); + + result |= ( (READ(SD_MISO_PIN) != 0) << bitidx ); + } + DELAY_NS(125); + return result; +} + +uint16_t HAL_SPI_STM32_SpiTransfer_Mode_3_16bits(uint16_t v) { // using Mode 3 + bool msb = ( _spi_bit_order == SPI_BITORDER_MSB ); + uint16_t result = 0; + for (uint8_t bits = 0; bits < 16; bits++) { + int bitidx = ( msb ? 15-bits : bits ); + WRITE(SD_SCK_PIN, LOW); + WRITE(SD_MOSI_PIN, (v & ( 1 << bitidx )) != 0); + + delaySPIFunc(); + WRITE(SD_SCK_PIN, HIGH); + delaySPIFunc(); + + result |= ( (READ(SD_MISO_PIN) != 0) << bitidx ); + } + DELAY_NS(125); + return result; +} + +// Soft SPI receive byte +uint8_t spiRec(uint8_t txval) { + hal.isr_off(); // No interrupts during byte receive + const uint8_t data = HAL_SPI_STM32_SpiTransfer_Mode_3(txval); + hal.isr_on(); // Enable interrupts + return data; +} + +uint16_t spiRec16(uint16_t txval) { + hal.isr_off(); + uint16_t data = HAL_SPI_STM32_SpiTransfer_Mode_3_16bits(txval); + hal.isr_on(); + return data; +} + +// Soft SPI read data +void spiRead(uint8_t *buf, uint16_t nbyte, uint8_t txval) { + for (uint16_t i = 0; i < nbyte; i++) + buf[i] = spiRec(txval); +} + +// Soft SPI send byte +void spiSend(uint8_t data) { + hal.isr_off(); // No interrupts during byte send + HAL_SPI_STM32_SpiTransfer_Mode_3(data); // Don't care what is received + hal.isr_on(); // Enable interrupts +} + +void spiSend16(uint16_t data) { + hal.isr_off(); + HAL_SPI_STM32_SpiTransfer_Mode_3_16bits(data); + hal.isr_on(); +} + +// Soft SPI send block +void spiSendBlock(uint8_t token, const uint8_t *buf) { + spiSend(token); + for (uint16_t i = 0; i < 512; i++) + spiSend(buf[i]); +} + +void spiWrite(const uint8_t *buf, uint16_t cnt) { + for (uint16_t n = 0; n < cnt; n++) + spiSend(buf[n]); +} + +void spiWrite16(const uint16_t *buf, uint16_t cnt) { + for (uint16_t n = 0; n < cnt; n++) + spiSend16(buf[n]); +} + +void spiWriteRepeat(uint8_t val, uint16_t repcnt) { + for (uint16_t n = 0; n < repcnt; n++) + spiSend(val); +} + +void spiWriteRepeat16(uint16_t val, uint16_t repcnt) { + for (uint16_t n = 0; n < repcnt; n++) + spiSend16(val); +} + +#endif // SOFTWARE_SPI #endif // HAL_STM32, MAPLE_STM32F1 diff --git a/Marlin/src/HAL/shared/tft/tft_spi.cpp b/Marlin/src/HAL/shared/tft/tft_spi.cpp index 9aa6997330db..cc96f276fd35 100644 --- a/Marlin/src/HAL/shared/tft/tft_spi.cpp +++ b/Marlin/src/HAL/shared/tft/tft_spi.cpp @@ -39,16 +39,15 @@ #endif void TFT_SPI::Init() { - OUT_WRITE(TFT_A0_PIN, HIGH); spiSetupChipSelect(TFT_CS_PIN); } void TFT_SPI::DataTransferBegin(eSPIMode spiMode) { int pin_miso = -1; -#if PIN_EXISTS(TFT_MISO) - pin_miso = TFT_MISO_PIN; -#endif + #if PIN_EXISTS(TFT_MISO) + pin_miso = TFT_MISO_PIN; + #endif spiInitEx((spiMode == eSPIMode::READ) ? TFT_BAUDRATE_READ : TFT_BAUDRATE_WRITE, TFT_SCK_PIN, pin_miso, TFT_MOSI_PIN, TFT_CS_PIN); } @@ -90,17 +89,11 @@ uint32_t TFT_SPI::ReadID(uint16_t Reg) { } bool TFT_SPI::isBusy() { -#if ENABLED(HAL_SPI_SUPPORTS_ASYNC) - return spiAsyncIsRunning(); -#else - return false; -#endif + return TERN0(HAL_SPI_SUPPORTS_ASYNC, spiAsyncIsRunning()); } void TFT_SPI::Abort() { -#if ENABLED(HAL_SPI_SUPPORTS_ASYNC) - spiAsyncAbort(); -#endif + TERN_(HAL_SPI_SUPPORTS_ASYNC, spiAsyncAbort()); } void TFT_SPI::Transmit(uint16_t Data) { @@ -124,7 +117,6 @@ void TFT_SPI::TransmitDMA(const uint8_t *Data, uint16_t Count) { } void TFT_SPI::TransmitRepeat(const uint16_t Data, uint16_t Count) { - DataTransferBegin(eSPIMode::WRITE); spiWriteRepeat16(Data, Count); DataTransferEnd(); @@ -132,30 +124,27 @@ void TFT_SPI::TransmitRepeat(const uint16_t Data, uint16_t Count) { #if ENABLED(HAL_SPI_SUPPORTS_ASYNC) -static void (*_txcomplete_callback)(void*) = nullptr; -void *_txcomplete_ud = nullptr; + static void (*_txcomplete_callback)(void*) = nullptr; + void *_txcomplete_ud = nullptr; -void TFT_SPI::_TXComplete( void *ud ) -{ - auto cb = _txcomplete_callback; - auto _ud = _txcomplete_ud; + void TFT_SPI::_TXComplete( void *ud ) { + auto cb = _txcomplete_callback; + auto _ud = _txcomplete_ud; - DataTransferEnd(); + DataTransferEnd(); - if (cb) { - cb( _ud ); + if (cb) cb(_ud); } -} -void TFT_SPI::TransmitDMA_Async(const uint16_t *Data, uint16_t Count, void (*completeCallback)(void*), void *ud) { - DataTransferBegin(eSPIMode::WRITE); + void TFT_SPI::TransmitDMA_Async(const uint16_t *Data, uint16_t Count, void (*completeCallback)(void*), void *ud) { + DataTransferBegin(eSPIMode::WRITE); - _txcomplete_callback = completeCallback; - _txcomplete_ud = ud; + _txcomplete_callback = completeCallback; + _txcomplete_ud = ud; - spiWriteAsync16(Data, Count, TFT_SPI::_TXComplete, nullptr); -} + spiWriteAsync16(Data, Count, TFT_SPI::_TXComplete, nullptr); + } -#endif +#endif // HAL_SPI_SUPPORTS_ASYNC #endif // HAS_SPI_TFT diff --git a/Marlin/src/module/stepper/trinamic.cpp b/Marlin/src/module/stepper/trinamic.cpp index 3127fb01fc0b..5b5a7e37723f 100644 --- a/Marlin/src/module/stepper/trinamic.cpp +++ b/Marlin/src/module/stepper/trinamic.cpp @@ -39,7 +39,7 @@ enum StealthIndex : uint8_t { }; #define TMC_INIT(ST, STEALTH_INDEX) tmc_init(stepper##ST, ST##_CURRENT, ST##_MICROSTEPS, ST##_HYBRID_THRESHOLD, stealthchop_by_axis[STEALTH_INDEX], chopper_timing_##ST, ST##_INTERPOLATE, ST##_HOLD_MULTIPLIER) -#if !ENABLED(TMC_USE_SW_SPI) +#if DISABLED(TMC_USE_SW_SPI) struct MarlinTMCSPIInterface : public TMCSPIInterface { void begin(uint32_t maxClockFreq, int bitOrder, int clkMode) override { int spi_bitOrder = ( bitOrder == TMCSPI_BITORDER_MSB ) ? SPI_BITORDER_MSB : SPI_BITORDER_LSB;