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 000000000..cded8a16a --- /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 4986dcdd7..cb757bb8c 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 c8fe029d3..2765bb553 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 e5acaa4e6..1374e6aaf 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 cd9f55c50..0a0df2697 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 9f6d62649..fb659b396 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 daffddf07..101cd7f10 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 841a3f845..d67a70700 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 3ead62dc2..9e9b76439 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 1d3c7f18d..43b46d5dd 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 589e05ebd..9138c04ac 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 e8d9f4a7c..48e8ac0ba 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 7a5819834..be84367e4 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 743bed643..31047a8a0 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} +