From ae0e4159e082829620615b3a428905bf7fd827c3 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/ESP32/HAL_SPI_HW.cpp | 2 +- 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/STM32/HAL_SPI_HW.cpp | 4 +- Marlin/src/HAL/STM32/HAL_SPI_HWgen.cpp | 2 +- Marlin/src/module/stepper/trinamic.cpp | 2 +- 10 files changed, 2276 insertions(+), 2312 deletions(-) diff --git a/Marlin/src/HAL/ESP32/HAL_SPI_HW.cpp b/Marlin/src/HAL/ESP32/HAL_SPI_HW.cpp index 7e9fd89413dca..f1c51907a90fd 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" diff --git a/Marlin/src/HAL/ESP32/HAL_SPI_HWgen.cpp b/Marlin/src/HAL/ESP32/HAL_SPI_HWgen.cpp index 3d5f3b31237ab..0e77970f20b21 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 d7b0b3d23253a..ef8430f63e44d 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 91e1f509865e8..0a0032548fbbd 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 f04435872b026..00349af2fdb12 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 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 } - 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 17a0a109c957e..8f9ee9d505314 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 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; +} + +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 93e420590fec4..fd3378b33759f 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/STM32/HAL_SPI_HW.cpp b/Marlin/src/HAL/STM32/HAL_SPI_HW.cpp index 75c389f4c8cb7..637171bd52170 100644 --- a/Marlin/src/HAL/STM32/HAL_SPI_HW.cpp +++ b/Marlin/src/HAL/STM32/HAL_SPI_HW.cpp @@ -47,7 +47,7 @@ // ------------------------ // 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 DISABLED(SOFTWARE_SPI) && (defined(STM32F1xx) || defined(STM32F4xx)) && DISABLED(HALSPI_HW_GENERIC) #include "pinconfig.h" @@ -487,7 +487,7 @@ extern "C" { } } -#if !ENABLED(HAL_SPI_SUPPORTS_ASYNC) +#if DISABLED(HAL_SPI_SUPPORTS_ASYNC) static bool _spi_debug_inside_transaction = false; #endif diff --git a/Marlin/src/HAL/STM32/HAL_SPI_HWgen.cpp b/Marlin/src/HAL/STM32/HAL_SPI_HWgen.cpp index 1b781cf6c0ea3..7ed4cb7f9faf6 100644 --- a/Marlin/src/HAL/STM32/HAL_SPI_HWgen.cpp +++ b/Marlin/src/HAL/STM32/HAL_SPI_HWgen.cpp @@ -31,7 +31,7 @@ // ------------------------ // 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 DISABLED(SOFTWARE_SPI) && (!(defined(STM32F1xx) || defined(STM32F4xx)) || ENABLED(HALSPI_HW_GENERIC)) #include diff --git a/Marlin/src/module/stepper/trinamic.cpp b/Marlin/src/module/stepper/trinamic.cpp index 3127fb01fc0b3..5b5a7e37723f1 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;