diff --git a/Marlin/src/HAL/HAL_LPC1768/DebugMonitor_LPC1768.cpp b/Marlin/src/HAL/HAL_LPC1768/DebugMonitor_LPC1768.cpp
new file mode 100644
index 0000000000..cded8a16ae
--- /dev/null
+++ b/Marlin/src/HAL/HAL_LPC1768/DebugMonitor_LPC1768.cpp
@@ -0,0 +1,318 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#ifdef TARGET_LPC1768
+
+#include "../../core/macros.h"
+#include "../../core/serial.h"
+#include
+
+#include "../shared/backtrace/unwinder.h"
+#include "../shared/backtrace/unwmemaccess.h"
+#include "watchdog.h"
+#include
+
+
+// Debug monitor that dumps to the Programming port all status when
+// an exception or WDT timeout happens - And then resets the board
+
+// All the Monitor routines must run with interrupts disabled and
+// under an ISR execution context. That is why we cannot reuse the
+// Serial interrupt routines or any C runtime, as we don't know the
+// state we are when running them
+
+// A SW memory barrier, to ensure GCC does not overoptimize loops
+#define sw_barrier() __asm__ volatile("": : :"memory");
+
+// (re)initialize UART0 as a monitor output to 250000,n,8,1
+static void TXBegin(void) {
+}
+
+// Send character through UART with no interrupts
+static void TX(char c) {
+ _DBC(c);
+}
+
+// Send String through UART
+static void TX(const char* s) {
+ while (*s) TX(*s++);
+}
+
+static void TXDigit(uint32_t d) {
+ if (d < 10) TX((char)(d+'0'));
+ else if (d < 16) TX((char)(d+'A'-10));
+ else TX('?');
+}
+
+// Send Hex number thru UART
+static void TXHex(uint32_t v) {
+ TX("0x");
+ for (uint8_t i = 0; i < 8; i++, v <<= 4)
+ TXDigit((v >> 28) & 0xF);
+}
+
+// Send Decimal number thru UART
+static void TXDec(uint32_t v) {
+ if (!v) {
+ TX('0');
+ return;
+ }
+
+ char nbrs[14];
+ char *p = &nbrs[0];
+ while (v != 0) {
+ *p++ = '0' + (v % 10);
+ v /= 10;
+ }
+ do {
+ p--;
+ TX(*p);
+ } while (p != &nbrs[0]);
+}
+
+// Dump a backtrace entry
+static bool UnwReportOut(void* ctx, const UnwReport* bte) {
+ int* p = (int*)ctx;
+
+ (*p)++;
+ TX('#'); TXDec(*p); TX(" : ");
+ TX(bte->name?bte->name:"unknown"); TX('@'); TXHex(bte->function);
+ TX('+'); TXDec(bte->address - bte->function);
+ TX(" PC:");TXHex(bte->address); TX('\n');
+ return true;
+}
+
+#ifdef UNW_DEBUG
+ void UnwPrintf(const char* format, ...) {
+ char dest[256];
+ va_list argptr;
+ va_start(argptr, format);
+ vsprintf(dest, format, argptr);
+ va_end(argptr);
+ TX(&dest[0]);
+ }
+#endif
+
+/* Table of function pointers for passing to the unwinder */
+static const UnwindCallbacks UnwCallbacks = {
+ UnwReportOut,
+ UnwReadW,
+ UnwReadH,
+ UnwReadB
+ #if defined(UNW_DEBUG)
+ ,UnwPrintf
+ #endif
+};
+
+
+/**
+ * HardFaultHandler_C:
+ * This is called from the HardFault_HandlerAsm with a pointer the Fault stack
+ * as the parameter. We can then read the values from the stack and place them
+ * into local variables for ease of reading.
+ * We then read the various Fault Status and Address Registers to help decode
+ * cause of the fault.
+ * The function ends with a BKPT instruction to force control back into the debugger
+ */
+extern "C"
+void HardFault_HandlerC(unsigned long *sp, unsigned long lr, unsigned long cause) {
+
+ static const char* causestr[] = {
+ "NMI","Hard","Mem","Bus","Usage","Debug","WDT","RSTC"
+ };
+
+ UnwindFrame btf;
+
+ // Dump report to the Programming port (interrupts are DISABLED)
+ TXBegin();
+ TX("\n\n## Software Fault detected ##\n");
+ TX("Cause: "); TX(causestr[cause]); TX('\n');
+
+ TX("R0 : "); TXHex(((unsigned long)sp[0])); TX('\n');
+ TX("R1 : "); TXHex(((unsigned long)sp[1])); TX('\n');
+ TX("R2 : "); TXHex(((unsigned long)sp[2])); TX('\n');
+ TX("R3 : "); TXHex(((unsigned long)sp[3])); TX('\n');
+ TX("R12 : "); TXHex(((unsigned long)sp[4])); TX('\n');
+ TX("LR : "); TXHex(((unsigned long)sp[5])); TX('\n');
+ TX("PC : "); TXHex(((unsigned long)sp[6])); TX('\n');
+ TX("PSR : "); TXHex(((unsigned long)sp[7])); TX('\n');
+
+ // Configurable Fault Status Register
+ // Consists of MMSR, BFSR and UFSR
+ TX("CFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED28)))); TX('\n');
+
+ // Hard Fault Status Register
+ TX("HFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED2C)))); TX('\n');
+
+ // Debug Fault Status Register
+ TX("DFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED30)))); TX('\n');
+
+ // Auxiliary Fault Status Register
+ TX("AFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED3C)))); TX('\n');
+
+ // Read the Fault Address Registers. These may not contain valid values.
+ // Check BFARVALID/MMARVALID to see if they are valid values
+ // MemManage Fault Address Register
+ TX("MMAR : "); TXHex((*((volatile unsigned long *)(0xE000ED34)))); TX('\n');
+
+ // Bus Fault Address Register
+ TX("BFAR : "); TXHex((*((volatile unsigned long *)(0xE000ED38)))); TX('\n');
+
+ TX("ExcLR: "); TXHex(lr); TX('\n');
+ TX("ExcSP: "); TXHex((unsigned long)sp); TX('\n');
+
+ btf.sp = ((unsigned long)sp) + 8*4; // The original stack pointer
+ btf.fp = btf.sp;
+ btf.lr = ((unsigned long)sp[5]);
+ btf.pc = ((unsigned long)sp[6]) | 1; // Force Thumb, as CORTEX only support it
+
+ // Perform a backtrace
+ TX("\nBacktrace:\n\n");
+ int ctr = 0;
+ UnwindStart(&btf, &UnwCallbacks, &ctr);
+
+ // Disable all NVIC interrupts
+ NVIC->ICER[0] = 0xFFFFFFFF;
+ NVIC->ICER[1] = 0xFFFFFFFF;
+
+ // Relocate VTOR table to default position
+ SCB->VTOR = 0;
+
+ // Clear cause of reset to prevent entering smoothie bootstrap
+ HAL_clear_reset_source();
+ // Restart watchdog
+ //WDT_Restart(WDT);
+ watchdog_init();
+
+ // Reset controller
+ NVIC_SystemReset();
+
+ while(1) { watchdog_init(); }
+}
+
+extern "C" {
+__attribute__((naked)) void NMI_Handler(void) {
+ __asm__ __volatile__ (
+ ".syntax unified" "\n\t"
+ A("tst lr, #4")
+ A("ite eq")
+ A("mrseq r0, msp")
+ A("mrsne r0, psp")
+ A("mov r1,lr")
+ A("mov r2,#0")
+ A("b HardFault_HandlerC")
+ );
+}
+
+__attribute__((naked)) void HardFault_Handler(void) {
+ __asm__ __volatile__ (
+ ".syntax unified" "\n\t"
+ A("tst lr, #4")
+ A("ite eq")
+ A("mrseq r0, msp")
+ A("mrsne r0, psp")
+ A("mov r1,lr")
+ A("mov r2,#1")
+ A("b HardFault_HandlerC")
+ );
+}
+
+__attribute__((naked)) void MemManage_Handler(void) {
+ __asm__ __volatile__ (
+ ".syntax unified" "\n\t"
+ A("tst lr, #4")
+ A("ite eq")
+ A("mrseq r0, msp")
+ A("mrsne r0, psp")
+ A("mov r1,lr")
+ A("mov r2,#2")
+ A("b HardFault_HandlerC")
+ );
+}
+
+__attribute__((naked)) void BusFault_Handler(void) {
+ __asm__ __volatile__ (
+ ".syntax unified" "\n\t"
+ A("tst lr, #4")
+ A("ite eq")
+ A("mrseq r0, msp")
+ A("mrsne r0, psp")
+ A("mov r1,lr")
+ A("mov r2,#3")
+ A("b HardFault_HandlerC")
+ );
+}
+
+__attribute__((naked)) void UsageFault_Handler(void) {
+ __asm__ __volatile__ (
+ ".syntax unified" "\n\t"
+ A("tst lr, #4")
+ A("ite eq")
+ A("mrseq r0, msp")
+ A("mrsne r0, psp")
+ A("mov r1,lr")
+ A("mov r2,#4")
+ A("b HardFault_HandlerC")
+ );
+}
+
+__attribute__((naked)) void DebugMon_Handler(void) {
+ __asm__ __volatile__ (
+ ".syntax unified" "\n\t"
+ A("tst lr, #4")
+ A("ite eq")
+ A("mrseq r0, msp")
+ A("mrsne r0, psp")
+ A("mov r1,lr")
+ A("mov r2,#5")
+ A("b HardFault_HandlerC")
+ );
+}
+
+/* This is NOT an exception, it is an interrupt handler - Nevertheless, the framing is the same */
+__attribute__((naked)) void WDT_IRQHandler(void) {
+ __asm__ __volatile__ (
+ ".syntax unified" "\n\t"
+ A("tst lr, #4")
+ A("ite eq")
+ A("mrseq r0, msp")
+ A("mrsne r0, psp")
+ A("mov r1,lr")
+ A("mov r2,#6")
+ A("b HardFault_HandlerC")
+ );
+}
+
+__attribute__((naked)) void RSTC_Handler(void) {
+ __asm__ __volatile__ (
+ ".syntax unified" "\n\t"
+ A("tst lr, #4")
+ A("ite eq")
+ A("mrseq r0, msp")
+ A("mrsne r0, psp")
+ A("mov r1,lr")
+ A("mov r2,#7")
+ A("b HardFault_HandlerC")
+ );
+}
+}
+#endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/HAL/HAL_LPC1768/HAL.h b/Marlin/src/HAL/HAL_LPC1768/HAL.h
index 4986dcdd7b..cb757bb8cd 100644
--- a/Marlin/src/HAL/HAL_LPC1768/HAL.h
+++ b/Marlin/src/HAL/HAL_LPC1768/HAL.h
@@ -152,4 +152,7 @@ using FilteredADC = LPC176x::ADC;
// Parse a G-code word into a pin index
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval);
+#define HAL_IDLETASK 1
+void HAL_idletask(void);
+
#endif // _HAL_LPC1768_H_
diff --git a/Marlin/src/HAL/HAL_LPC1768/HAL_spi.cpp b/Marlin/src/HAL/HAL_LPC1768/HAL_spi.cpp
index c8fe029d39..2765bb553a 100644
--- a/Marlin/src/HAL/HAL_LPC1768/HAL_spi.cpp
+++ b/Marlin/src/HAL/HAL_LPC1768/HAL_spi.cpp
@@ -49,7 +49,6 @@
#ifdef TARGET_LPC1768
#include "../../inc/MarlinConfig.h"
-
// --------------------------------------------------------------------------
// Includes
// --------------------------------------------------------------------------
@@ -59,7 +58,6 @@
// --------------------------------------------------------------------------
// Public functions
// --------------------------------------------------------------------------
-
#if ENABLED(LPC_SOFTWARE_SPI)
#include "SoftwareSPI.h"
@@ -127,8 +125,25 @@
#include
#include
- void spiBegin() { // setup SCK, MOSI & MISO pins for SSP0
+ // decide which HW SPI device to use
+ #ifndef LPC_HW_SPI_DEV
+ #if (SCK_PIN == P0_07 && MISO_PIN == P0_08 && MOSI_PIN == P0_09)
+ #define LPC_HW_SPI_DEV 1
+ #else
+ #if (SCK_PIN == P0_15 && MISO_PIN == P0_17 && MOSI_PIN == P0_18)
+ #define LPC_HW_SPI_DEV 0
+ #else
+ #error "Invalid pins selected for hardware SPI"
+ #endif
+ #endif
+ #endif
+ #if (LPC_HW_SPI_DEV == 0)
+ #define LPC_SSPn LPC_SSP0
+ #else
+ #define LPC_SSPn LPC_SSP1
+ #endif
+ void spiBegin() { // setup SCK, MOSI & MISO pins for SSP0
PINSEL_CFG_Type PinCfg; // data structure to hold init values
PinCfg.Funcnum = 2;
PinCfg.OpenDrain = 0;
@@ -147,10 +162,13 @@
PinCfg.Portnum = LPC1768_PIN_PORT(MOSI_PIN);
PINSEL_ConfigPin(&PinCfg);
SET_OUTPUT(MOSI_PIN);
+ // divide PCLK by 2 for SSP0
+ CLKPWR_SetPCLKDiv(LPC_HW_SPI_DEV == 0 ? CLKPWR_PCLKSEL_SSP0 : CLKPWR_PCLKSEL_SSP1, CLKPWR_PCLKSEL_CCLK_DIV_2);
+ spiInit(0);
+ SSP_Cmd(LPC_SSPn, ENABLE); // start SSP running
}
void spiInit(uint8_t spiRate) {
- SSP_Cmd(LPC_SSP0, DISABLE); // Disable SSP0 before changing rate
// table to convert Marlin spiRates (0-5 plus default) into bit rates
uint32_t Marlin_speed[7]; // CPSR is always 2
Marlin_speed[0] = 8333333; //(SCR: 2) desired: 8,000,000 actual: 8,333,333 +4.2% SPI_FULL_SPEED
@@ -160,33 +178,32 @@
Marlin_speed[4] = 500000; //(SCR: 49) desired: 500,000 actual: 500,000 SPI_SPEED_5
Marlin_speed[5] = 250000; //(SCR: 99) desired: 250,000 actual: 250,000 SPI_SPEED_6
Marlin_speed[6] = 125000; //(SCR:199) desired: 125,000 actual: 125,000 Default from HAL.h
-
- // divide PCLK by 2 for SSP0
- CLKPWR_SetPCLKDiv(CLKPWR_PCLKSEL_SSP0, CLKPWR_PCLKSEL_CCLK_DIV_2);
-
// setup for SPI mode
SSP_CFG_Type HW_SPI_init; // data structure to hold init values
SSP_ConfigStructInit(&HW_SPI_init); // set values for SPI mode
HW_SPI_init.ClockRate = Marlin_speed[MIN(spiRate, 6)]; // put in the specified bit rate
- SSP_Init(LPC_SSP0, &HW_SPI_init); // puts the values into the proper bits in the SSP0 registers
+ HW_SPI_init.Mode |= SSP_CR1_SSP_EN;
+ SSP_Init(LPC_SSPn, &HW_SPI_init); // puts the values into the proper bits in the SSP0 registers
+ }
- SSP_Cmd(LPC_SSP0, ENABLE); // start SSP0 running
+
+ static uint8_t doio(uint8_t b) {
+ /* send and receive a single byte */
+ SSP_SendData(LPC_SSPn, b & 0x00FF);
+ while (SSP_GetStatus(LPC_SSPn, SSP_STAT_BUSY)); // wait for it to finish
+ return SSP_ReceiveData(LPC_SSPn) & 0x00FF;
}
void spiSend(uint8_t b) {
- while (!SSP_GetStatus(LPC_SSP0, SSP_STAT_TXFIFO_NOTFULL)); // wait for room in the buffer
- SSP_SendData(LPC_SSP0, b & 0x00FF);
- while (SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)); // wait for it to finish
+ doio(b);
}
void spiSend(const uint8_t* buf, size_t n) {
if (n == 0) return;
for (uint16_t i = 0; i < n; i++) {
- while (!SSP_GetStatus(LPC_SSP0, SSP_STAT_TXFIFO_NOTFULL)); // wait for room in the buffer
- SSP_SendData(LPC_SSP0, buf[i] & 0x00FF);
+ doio(buf[i]);
}
- while (SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)); // wait for it to finish
}
void spiSend(uint32_t chan, byte b) {
@@ -195,17 +212,9 @@
void spiSend(uint32_t chan, const uint8_t* buf, size_t n) {
}
- static uint8_t get_one_byte() {
- // send a dummy byte so can clock in receive data
- SSP_SendData(LPC_SSP0,0x00FF);
- while (SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)); // wait for it to finish
- return SSP_ReceiveData(LPC_SSP0) & 0x00FF;
- }
-
// Read single byte from SPI
uint8_t spiRec() {
- while (SSP_GetStatus(LPC_SSP0, SSP_STAT_RXFIFO_NOTEMPTY) || SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)) SSP_ReceiveData(LPC_SSP0); //flush the receive buffer
- return get_one_byte();
+ return doio(0xff);
}
uint8_t spiRec(uint32_t chan) {
@@ -214,22 +223,25 @@
// Read from SPI into buffer
void spiRead(uint8_t*buf, uint16_t nbyte) {
- while (SSP_GetStatus(LPC_SSP0, SSP_STAT_RXFIFO_NOTEMPTY) || SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)) SSP_ReceiveData(LPC_SSP0); //flush the receive buffer
if (nbyte == 0) return;
for (int i = 0; i < nbyte; i++) {
- buf[i] = get_one_byte();
+ buf[i] = doio(0xff);
}
}
static uint8_t spiTransfer(uint8_t b) {
- while (SSP_GetStatus(LPC_SSP0, SSP_STAT_RXFIFO_NOTEMPTY) || SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)) SSP_ReceiveData(LPC_SSP0); //flush the receive buffer
- SSP_SendData(LPC_SSP0, b); // send the byte
- while (SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)); // wait for it to finish
- return SSP_ReceiveData(LPC_SSP0) & 0x00FF;
+ return doio(b);
}
// Write from buffer to SPI
void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ uint8_t response;
+ response = spiTransfer(token);
+
+ for (uint16_t i = 0; i < 512; i++) {
+ response = spiTransfer(buf[i]);
+ }
+ UNUSED(response);
}
/** Begin SPI transaction, set clock, bit order, data mode */
@@ -270,4 +282,3 @@ uint16_t SPIClass::transfer16(uint16_t data) {
SPIClass SPI;
#endif // TARGET_LPC1768
-
diff --git a/Marlin/src/HAL/HAL_LPC1768/fastio.h b/Marlin/src/HAL/HAL_LPC1768/fastio.h
index e5acaa4e62..1374e6aafa 100644
--- a/Marlin/src/HAL/HAL_LPC1768/fastio.h
+++ b/Marlin/src/HAL/HAL_LPC1768/fastio.h
@@ -39,19 +39,19 @@
#define USEABLE_HARDWARE_PWM(pin) useable_hardware_PWM(pin)
-#define LPC_PIN(pin) (gpio_pin(pin))
-#define LPC_GPIO(port) (gpio_port(port))
+#define LPC_PIN(pin) gpio_pin(pin)
+#define LPC_GPIO(port) gpio_port(port)
-#define SET_DIR_INPUT(IO) (gpio_set_input(IO))
-#define SET_DIR_OUTPUT(IO) (gpio_set_output(IO))
+#define SET_DIR_INPUT(IO) gpio_set_input(IO)
+#define SET_DIR_OUTPUT(IO) gpio_set_output(IO)
-#define SET_MODE(IO, mode) (pinMode(IO, mode))
+#define SET_MODE(IO, mode) pinMode(IO, mode)
-#define WRITE_PIN_SET(IO) (gpio_set(IO))
-#define WRITE_PIN_CLR(IO) (gpio_clear(IO))
+#define WRITE_PIN_SET(IO) gpio_set(IO)
+#define WRITE_PIN_CLR(IO) gpio_clear(IO)
-#define READ_PIN(IO) (gpio_get(IO))
-#define WRITE_PIN(IO,V) (gpio_set(IO, V))
+#define READ_PIN(IO) gpio_get(IO)
+#define WRITE_PIN(IO,V) gpio_set(IO, V)
/**
* Magic I/O routines
diff --git a/Marlin/src/HAL/HAL_LPC1768/main.cpp b/Marlin/src/HAL/HAL_LPC1768/main.cpp
index cd9f55c50c..0a0df26978 100644
--- a/Marlin/src/HAL/HAL_LPC1768/main.cpp
+++ b/Marlin/src/HAL/HAL_LPC1768/main.cpp
@@ -9,7 +9,13 @@
#include
#include
#include
+#include
+extern "C" {
+ #include
+}
+
+#include "../../sd/cardreader.h"
#include "../../inc/MarlinConfig.h"
#include "HAL.h"
#include "HAL_timers.h"
@@ -41,15 +47,28 @@ void HAL_init() {
delay(100);
}
#endif
-
- (void)MSC_SD_Init(0);
-
- USB_Init();
+ //debug_frmwrk_init();
+ //_DBG("\n\nDebug running\n");
+ // Initialise the SD card chip select pins as soon as possible
+ #ifdef SS_PIN
+ digitalWrite(SS_PIN, HIGH);
+ pinMode(SS_PIN, OUTPUT);
+ #endif
+ #ifdef ONBOARD_SD_CS
+ digitalWrite(ONBOARD_SD_CS, HIGH);
+ pinMode(ONBOARD_SD_CS, OUTPUT);
+ #endif
+ USB_Init(); // USB Initialization
+ USB_Connect(FALSE); // USB clear connection
+ delay(1000); // Give OS time to notice
USB_Connect(TRUE);
-
+ #ifndef USB_SD_DISABLED
+ MSC_SD_Init(0); // Enable USB SD card access
+ #endif
const uint32_t usb_timeout = millis() + 2000;
while (!USB_Configuration && PENDING(millis(), usb_timeout)) {
delay(50);
+ HAL_idletask();
#if PIN_EXISTS(LED)
TOGGLE(LED_PIN); // Flash quickly during USB initialization
#endif
@@ -68,4 +87,23 @@ void HAL_init() {
LPC1768_PWM_init();
}
+// HAL idle task
+void HAL_idletask(void) {
+ #if ENABLED(SDSUPPORT) && defined(SHARED_SD_CARD)
+ // If Marlin is using the SD card we need to lock it to prevent access from
+ // a PC via USB.
+ // Other HALs use IS_SD_PRINTING and IS_SD_FILE_OPEN to check for access but
+ // this will not reliably detect delete operations. To be safe we will lock
+ // the disk if Marlin has it mounted. Unfortuately there is currently no way
+ // to unmount the disk from the LCD menu.
+ // if (IS_SD_PRINTING || IS_SD_FILE_OPEN)
+ if (card.cardOK)
+ MSC_Aquire_Lock();
+ else
+ MSC_Release_Lock();
+ #endif
+ // Perform USB stack housekeeping
+ MSC_RunDeferredCommands();
+}
+
#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/HAL_LPC1768/persistent_store_api.h b/Marlin/src/HAL/HAL_LPC1768/persistent_store_api.h
index 9f6d626491..fb659b396c 100644
--- a/Marlin/src/HAL/HAL_LPC1768/persistent_store_api.h
+++ b/Marlin/src/HAL/HAL_LPC1768/persistent_store_api.h
@@ -21,4 +21,4 @@
*/
#include "../shared/persistent_store_api.h"
-//#define FLASH_EEPROM
+#define FLASH_EEPROM
diff --git a/Marlin/src/HAL/HAL_LPC1768/persistent_store_flash.cpp b/Marlin/src/HAL/HAL_LPC1768/persistent_store_flash.cpp
index daffddf079..101cd7f105 100644
--- a/Marlin/src/HAL/HAL_LPC1768/persistent_store_flash.cpp
+++ b/Marlin/src/HAL/HAL_LPC1768/persistent_store_flash.cpp
@@ -116,7 +116,7 @@ bool PersistentStore::access_finish() {
}
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
- for (int i = 0; i < size; i++) ram_eeprom[pos + i] = value[i];
+ for (size_t i = 0; i < size; i++) ram_eeprom[pos + i] = value[i];
eeprom_dirty = true;
crc16(crc, value, size);
pos += size;
@@ -125,7 +125,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
const uint8_t * const buff = writing ? &value[0] : &ram_eeprom[pos];
- if (writing) for (int i = 0; i < size; i++) value[i] = ram_eeprom[pos + i];
+ if (writing) for (size_t i = 0; i < size; i++) value[i] = ram_eeprom[pos + i];
crc16(crc, buff, size);
pos += size;
return false; // return true for any error
diff --git a/Marlin/src/HAL/HAL_LPC1768/spi_pins.h b/Marlin/src/HAL/HAL_LPC1768/spi_pins.h
index 841a3f845f..d67a70700a 100644
--- a/Marlin/src/HAL/HAL_LPC1768/spi_pins.h
+++ b/Marlin/src/HAL/HAL_LPC1768/spi_pins.h
@@ -50,7 +50,8 @@
#ifndef SS_PIN
#define SS_PIN P1_23
#endif
-#ifndef SDSS
+#if !defined(SDSS) || SDSS == P_NC // get defaulted in pins.h
+ #undef SDSS
#define SDSS SS_PIN
#endif
diff --git a/Marlin/src/HAL/HAL_LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp b/Marlin/src/HAL/HAL_LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp
index 3ead62dc23..9e9b76439a 100644
--- a/Marlin/src/HAL/HAL_LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp
+++ b/Marlin/src/HAL/HAL_LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp
@@ -63,6 +63,7 @@
#include "SoftwareSPI.h"
#include "../../shared/Delay.h"
+#undef SPI_SPEED
#define SPI_SPEED 3 // About 1 MHz
static pin_t SCK_pin_ST7920_HAL, MOSI_pin_ST7920_HAL_HAL;
diff --git a/Marlin/src/HAL/HAL_LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp b/Marlin/src/HAL/HAL_LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp
index 1d3c7f18dd..43b46d5ddf 100644
--- a/Marlin/src/HAL/HAL_LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp
+++ b/Marlin/src/HAL/HAL_LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp
@@ -62,6 +62,7 @@
#include
#include "SoftwareSPI.h"
+#undef SPI_SPEED
#define SPI_SPEED 2 // About 2 MHz
static uint8_t SPI_speed = 0;
diff --git a/Marlin/src/HAL/HAL_LPC1768/watchdog.cpp b/Marlin/src/HAL/HAL_LPC1768/watchdog.cpp
index 589e05ebd6..9138c04ac2 100644
--- a/Marlin/src/HAL/HAL_LPC1768/watchdog.cpp
+++ b/Marlin/src/HAL/HAL_LPC1768/watchdog.cpp
@@ -30,7 +30,29 @@
#include "watchdog.h"
void watchdog_init(void) {
- WDT_Init(WDT_CLKSRC_IRC, WDT_MODE_RESET);
+ #if ENABLED(WATCHDOG_RESET_MANUAL)
+ // We enable the watchdog timer, but only for the interrupt.
+
+ // Configure WDT to only trigger an interrupt
+ // Disable WDT interrupt (just in case, to avoid triggering it!)
+ NVIC_DisableIRQ(WDT_IRQn);
+
+ // We NEED memory barriers to ensure Interrupts are actually disabled!
+ // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
+ __DSB();
+ __ISB();
+
+ // Configure WDT to only trigger an interrupt
+ // Initialize WDT with the given parameters
+ WDT_Init(WDT_CLKSRC_IRC, WDT_MODE_INT_ONLY);
+
+ // Configure and enable WDT interrupt.
+ NVIC_ClearPendingIRQ(WDT_IRQn);
+ NVIC_SetPriority(WDT_IRQn, 0); // Use highest priority, so we detect all kinds of lockups
+ NVIC_EnableIRQ(WDT_IRQn);
+ #else
+ WDT_Init(WDT_CLKSRC_IRC, WDT_MODE_RESET);
+ #endif
WDT_Start(WDT_TIMEOUT);
}
diff --git a/Marlin/src/pins/pins.h b/Marlin/src/pins/pins.h
index e8d9f4a7c8..48e8ac0ba2 100644
--- a/Marlin/src/pins/pins.h
+++ b/Marlin/src/pins/pins.h
@@ -299,19 +299,19 @@
#elif MB(AZSMZ_MINI)
#include "pins_AZSMZ_MINI.h" // LPC1768 env:LPC1768
#elif MB(AZTEEG_X5_GT)
- #include "pins_AZTEEG_X5_GT.h" // LPC1769 env:LPC1768
+ #include "pins_AZTEEG_X5_GT.h" // LPC1769 env:LPC1769
#elif MB(AZTEEG_X5_MINI_WIFI)
- #include "pins_AZTEEG_X5_MINI_WIFI.h" // LPC1769 env:LPC1768
+ #include "pins_AZTEEG_X5_MINI_WIFI.h" // LPC1769 env:LPC1769
#elif MB(BIQU_BQ111_A4)
#include "pins_BIQU_BQ111_A4.h" // LPC1768 env:LPC1768
#elif MB(SELENA_COMPACT)
#include "pins_SELENA_COMPACT.h" // LPC1768 env:LPC1768
#elif MB(COHESION3D_REMIX)
- #include "pins_COHESION3D_REMIX.h" // LPC1769 env:LPC1768
+ #include "pins_COHESION3D_REMIX.h" // LPC1769 env:LPC1769
#elif MB(COHESION3D_MINI)
- #include "pins_COHESION3D_MINI.h" // LPC1769 env:LPC1768
+ #include "pins_COHESION3D_MINI.h" // LPC1769 env:LPC1769
#elif MB(SMOOTHIEBOARD)
- #include "pins_SMOOTHIEBOARD.h" // LPC1769 env:LPC1768
+ #include "pins_SMOOTHIEBOARD.h" // LPC1769 env:LPC1769
//
// Other 32-bit Boards
diff --git a/Marlin/src/pins/pins_MKS_SBASE.h b/Marlin/src/pins/pins_MKS_SBASE.h
index 7a58198342..be84367e42 100644
--- a/Marlin/src/pins/pins_MKS_SBASE.h
+++ b/Marlin/src/pins/pins_MKS_SBASE.h
@@ -141,8 +141,6 @@
// Misc. Functions
//
#define PS_ON_PIN P0_25 //TH3 Connector
-#define LPC_SOFTWARE_SPI // MKS_SBASE needs a software SPI because the
- // selected pins are not on a hardware SPI controller
/**
* Smart LCD adapter
@@ -185,14 +183,77 @@
#define ENET_TXD0 P1_00 // J12-11
#define ENET_TXD1 P1_01 // J12-12
-// A custom cable is needed. See the README file in the
-// Marlin\src\config\examples\Mks\Sbase directory
-#define SCK_PIN P1_22 // J8-2 (moved from EXP2 P0.7)
-#define MISO_PIN P1_23 // J8-3 (moved from EXP2 P0.8)
-#define MOSI_PIN P2_12 // J8-4 (moved from EXP2 P0.5)
-#define SS_PIN P0_28
-#define SDSS P0_06
+/*
+ * The SBase can share the on-board SD card with a PC via USB the following
+ * definitions control this feature:
+ */
+//#define USB_SD_DISABLED
+#define USB_SD_ONBOARD
+
+/*
+ * There are a number of configurations available for the SBase SD card reader.
+ * A custom cable can be used to allow access to the LCD based SD card.
+ * A standard cable can be used for access to the LCD SD card (but no SD detect).
+ * The onboard SD card can be used and optionally shared with a PC via USB.
+ */
+
+//#define SBASE_SD_CUSTOM_CABLE // Use a custom cable to access the SD
+//#define SBASE_SD_LCD // Use the SD drive attached to the LCD
+#define SBASE_SD_ONBOARD // Use the SD drive on the control board
+
+#ifdef SBASE_SD_CUSTOM_CABLE
+ /**
+ * A custom cable is needed. See the README file in the
+ * Marlin\src\config\examples\Mks\Sbase directory
+ * P0.27 is on EXP2 and the on-board SD card's socket. That means it can't be
+ * used as the SD_DETECT for the LCD's SD card.
+ *
+ * The best solution is to use the custom cable to connect the LCD's SD_DETECT
+ * to a pin NOT on EXP2.
+ *
+ * If you can't find a pin to use for the LCD's SD_DETECT then comment out
+ * SD_DETECT_PIN entirely and remove that wire from the the custom cable.
+ */
+ #define SD_DETECT_PIN P2_11 // J8-5 (moved from EXP2 P0.27)
+ #define SCK_PIN P1_22 // J8-2 (moved from EXP2 P0.7)
+ #define MISO_PIN P1_23 // J8-3 (moved from EXP2 P0.8)
+ #define MOSI_PIN P2_12 // J8-4 (moved from EXP2 P0.9)
+ #define SS_PIN P0_28 // Chip select for SD card used by Marlin
+ #define ONBOARD_SD_CS P0_06 // Chip select for "System" SD card
+ #define LPC_SOFTWARE_SPI // With a custom cable we need software SPI because the
+ // selected pins are not on a hardware SPI controller
+#endif
+
+#ifdef SBASE_SD_LCD
+ // use standard cable and header, SPI and SD detect sre shared with on-board SD card
+ // hardware SPI is used for both SD cards. The detect pin is shred between the
+ // LCD and onboard SD readers so we disable it.
+ #define SD_DETECT_PIN P0_27
+ #undef SD_DETECT_PIN
+ #define SCK_PIN P0_07
+ #define MISO_PIN P0_08
+ #define MOSI_PIN P0_09
+ #define SS_PIN P0_28 // Chip select for SD card used by Marlin
+ #define ONBOARD_SD_CS P0_06 // Chip select for "System" SD card
+#endif
+
+#ifdef SBASE_SD_ONBOARD
+ // The external SD card is not used. Hardware SPI is used to access the card.
+ #ifdef USB_SD_ONBOARD
+ // When sharing the SD card with a PC we want the menu options to
+ // mount/unmount the card and refresh it. So we disable card detect.
+ #define SHARED_SD_CARD
+ #undef SD_DETECT_PIN
+ #else
+ #define SD_DETECT_PIN P0_27
+ #endif
+ #define SCK_PIN P0_07
+ #define MISO_PIN P0_08
+ #define MOSI_PIN P0_09
+ #define SS_PIN P0_06 // Chip select for SD card used by Marlin
+ #define ONBOARD_SD_CS P0_06 // Chip select for "System" SD card
+#endif
/**
* Example for trinamic drivers using the J8 connector on MKs Sbase.
@@ -237,18 +298,6 @@
#define E0_SERIAL_RX_PIN P0_26 // TH4
#endif
-/**
- * P0.27 is on EXP2 and the on-board SD card's socket. That means it can't be
- * used as the SD_DETECT for the LCD's SD card.
- *
- * The best solution is to use the custom cable to connect the LCD's SD_DETECT
- * to a pin NOT on EXP2.
- *
- * If you can't find a pin to use for the LCD's SD_DETECT then comment out
- * SD_DETECT_PIN entirely and remove that wire from the the custom cable.
- */
-#define SD_DETECT_PIN P2_11 // J8-5 (moved from EXP2 P0.27)
-
/**
* PWMs
*
diff --git a/platformio.ini b/platformio.ini
index 743bed6439..31047a8a06 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -153,6 +153,9 @@ platform = https://github.com/p3p/pio-nxplpc-arduino-lpc176x/archive/ma
framework = arduino
board = nxp_lpc1768
build_flags = -DTARGET_LPC1768 -DU8G_HAL_LINKS -IMarlin/src/HAL/HAL_LPC1768/include -IMarlin/src/HAL/HAL_LPC1768/u8g ${common.build_flags}
+# debug options for backtrace
+# -funwind-tables
+# -mpoke-function-name
lib_ldf_mode = off
extra_scripts = Marlin/src/HAL/HAL_LPC1768/upload_extra_script.py
src_filter = ${common.default_src_filter} +
@@ -165,6 +168,9 @@ platform = https://github.com/p3p/pio-nxplpc-arduino-lpc176x/archive/ma
framework = arduino
board = nxp_lpc1769
build_flags = -DTARGET_LPC1768 -DU8G_HAL_LINKS -IMarlin/src/HAL/HAL_LPC1768/include -IMarlin/src/HAL/HAL_LPC1768/u8g ${common.build_flags}
+# debug options for backtrace
+# -funwind-tables
+# -mpoke-function-name
lib_ldf_mode = off
extra_scripts = Marlin/src/HAL/HAL_LPC1768/upload_extra_script.py
src_filter = ${common.default_src_filter} +