diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 0f2e9d7711..6800797d49 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -1459,14 +1459,48 @@ //#define DISABLE_M503 // Saves ~2700 bytes of PROGMEM. Disable for release! #define EEPROM_CHITCHAT // Give feedback on EEPROM commands. Disable to save PROGMEM. //#define EEPROM_BOOT_SILENT // Keep M503 quiet and only give errors during first load + #if ENABLED(EEPROM_SETTINGS) +/* +MKS Robin EEPROM: +EEPROM_SD +EEPROM_AT24C16 +EEPROM_W25Q +*/ +#define EEPROM_SD + +#if ENABLED(EEPROM_AT24C16) +#undef SDCARD_EEPROM_EMULATION +#undef USE_REAL_EEPROM +#undef FLASH_EEPROM_EMULATION +#undef SRAM_EEPROM_EMULATION +#define I2C_EEPROM_AT24C16 +#define USE_WIRED_EEPROM 1 +#define E2END (2*1024 - 1) +#endif + +#if ENABLED(EEPROM_W25Q) +#undef SDCARD_EEPROM_EMULATION +#undef USE_REAL_EEPROM +#undef FLASH_EEPROM_EMULATION +#undef SRAM_EEPROM_EMULATION +#undef I2C_EEPROM_AT24C16 +#define SPI_EEPROM_W25Q +#define SPI_EEPROM_OFFSET 0x700000 +#define USE_WIRED_EEPROM 1 +#define E2END (2*1024 - 1) +#endif + +#if ENABLED(EEPROM_SD) #define SDCARD_EEPROM_EMULATION #undef USE_REAL_EEPROM #undef FLASH_EEPROM_EMULATION #undef SRAM_EEPROM_EMULATION -//#define USE_WIRED_EEPROM 1 -//#define I2C_EEPROM_AT24C16 -//#define E2END (2*1024 - 1) +#undef I2C_EEPROM_AT24C16 +#undef SPI_EEPROM_W25Q +#undef USE_WIRED_EEPROM +#endif + #define EEPROM_AUTO_INIT // Init EEPROM automatically on any errors. #endif diff --git a/Marlin/src/HAL/STM32F1/HAL.h b/Marlin/src/HAL/STM32F1/HAL.h index 6bb360faeb..b87800c194 100644 --- a/Marlin/src/HAL/STM32F1/HAL.h +++ b/Marlin/src/HAL/STM32F1/HAL.h @@ -257,16 +257,16 @@ static int freeMemory() { * Wire library should work for i2c EEPROMs. */ -#if ENABLED(I2C_EEPROM_AT24C16) -uint8_t eeprom_read_byte(uint16_t *pos); -void eeprom_write_byte(uint16_t *pos, unsigned char value); +#if ANY(I2C_EEPROM_AT24C16, SPI_EEPROM_W25Q) void eeprom_hw_init(void); -#else +void eeprom_hw_deinit(void); +#endif uint8_t eeprom_read_byte(uint8_t *pos); void eeprom_write_byte(uint8_t *pos, unsigned char value); void eeprom_read_block(void *__dst, const void *__src, size_t __n); void eeprom_update_block(const void *__src, void *__dst, size_t __n); -#endif + + // diff --git a/Marlin/src/HAL/STM32F1/eeprom.cpp b/Marlin/src/HAL/STM32F1/eeprom.cpp index 8ad70291a4..48daffc4f0 100644 --- a/Marlin/src/HAL/STM32F1/eeprom.cpp +++ b/Marlin/src/HAL/STM32F1/eeprom.cpp @@ -27,6 +27,7 @@ #include "../shared/eeprom_api.h" bool PersistentStore::access_start() { + DEBUG("EEPROM start"); #if ENABLED(SPI_EEPROM) #if SPI_CHAN_EEPROM1 == 1 SET_OUTPUT(BOARD_SPI1_SCK_PIN); @@ -36,13 +37,20 @@ bool PersistentStore::access_start() { #endif spiInit(0); #endif - #if ENABLED(I2C_EEPROM_AT24C16) + + #if ANY(I2C_EEPROM_AT24C16, SPI_EEPROM_W25Q) eeprom_hw_init(); #endif return true; } -bool PersistentStore::access_finish() { return true; } +bool PersistentStore::access_finish() { + #if ANY(I2C_EEPROM_AT24C16, SPI_EEPROM_W25Q) + eeprom_hw_deinit(); + #endif + + return true; + } bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) { while (size--) { diff --git a/Marlin/src/HAL/STM32F1/eeprom_i2c_at24.cpp b/Marlin/src/HAL/STM32F1/eeprom_i2c_at24.cpp new file mode 100644 index 0000000000..2131934e8d --- /dev/null +++ b/Marlin/src/HAL/STM32F1/eeprom_i2c_at24.cpp @@ -0,0 +1,198 @@ +/** + +AT24C16, 16K SERIAL EEPROM: +Internally organized with 128 pages of 16 bytes each (2048 bytes) + +16K requires an 11-bit data word address for random word addressing. + +The 16K does not use any device address bits but instead the 3 bits are used for mem- +ory page addressing. These page addressing bits on the 4K, 8K and 16K devices +should be considered the most significant bits of the data word address which follows. +The A0, A1 and A2 pins are no connect. + +*/ +#include "../../inc/MarlinConfig.h" + +#if ENABLED(I2C_EEPROM_AT24C16) + +#include "../HAL.h" +#include "../../module/mks_wifi/small_cmsis.h" +#include "../../module/mks_wifi/dwt.h" + +#define DEV_ADDR 0xA0 +#define FSMC_DISABLE RCC->AHBENR &= ~RCC_AHBENR_FSMCEN //Конфликт на ноге FSMC_NADV с I2C. На время передачи приходится отключать FSMC +#define FSMC_RESTORE RCC->AHBENR |= RCC_AHBENR_FSMCEN; + +#define I2C_TIMEOUT 2000 //таймаут на ожидание опереций I2C. + +#define CHECK_TIMEOUT do{if(dwt_get_timeout() == 0){ERROR("Timeout");return 0;}}while(0) + +static bool waitSRBitSet(uint32_t Bit); +static uint8_t i2c_write(const uint8_t hw_adr, uint8_t *data, uint32_t len); +static uint8_t i2c_read(const uint8_t hw_adr, uint16_t addr, uint8_t *data, uint32_t len); + +void eeprom_hw_deinit(void){ + DEBUG("Finish I2C"); +} + +void eeprom_hw_init(void){ +/* +PB6 SCL Alternate function open drain +PB7 SDA Alternate function open drain +*/ + DEBUG("Init I2C"); + dwt_init(); + + RCC->APB2ENR |= RCC_APB2ENR_IOPBEN|RCC_APB2ENR_AFIOEN; + PORTB->CRL |= (GPIO_CRL_MODE6|GPIO_CRL_MODE7|GPIO_CRL_CNF6|GPIO_CRL_CNF7); + + AFIO->MAPR2 |= AFIO_MAPR2_FSMC_NADV_REMAP; //Remap по факту не работает, бит не устанавливается. + RCC->APB1ENR|= RCC_APB1ENR_I2C1EN; + + I2C1->CR1 = I2C_CR1_SWRST; + I2C1->CR1 = 0; + + //Тактовая 72Mhz, PCLK 36Mhz + I2C1->CCR = (180 << I2C_CCR_CCR_Pos); + I2C1->CR2 = (36 << I2C_CR2_FREQ_Pos); + I2C1->TRISE = 37; + I2C1->CR1 = I2C_CR1_PE; +} + +void eeprom_write_byte(uint8_t *pos, unsigned char value){ + uint8_t data[2]; + + FSMC_DISABLE; + + data[0]=(uint8_t)((unsigned)pos % 256); + data[1]=(uint8_t)(value); + + if(!i2c_write((DEV_ADDR+(uint8_t)(((unsigned)pos/256)<<1)),data,2)){ + ERROR("write failed"); + } + safe_delay(20); //Задержка на время пока eeprom пишет. + FSMC_RESTORE; +} + +uint8_t eeprom_read_byte(uint8_t *pos) { + uint8_t data; + + FSMC_DISABLE; + + if(!i2c_read(DEV_ADDR, (uint16_t)((unsigned)pos), &data, 1)){ + ERROR("read failed"); + data=0; + } + + safe_delay(1); //небольшая пауза перед включением FSMC, чтобы состояние STOP успело выставиться на линии. + FSMC_RESTORE; + return data; +} + +void eeprom_read_block(void *__dst, const void *__src, size_t __n){ + ERROR("Call to missing function"); +}; + +void eeprom_update_block(const void *__src, void *__dst, size_t __n){ + ERROR("Call to missing function"); +}; + +static uint8_t i2c_write(const uint8_t hw_adr, uint8_t *data, uint32_t len){ + + DEBUG("i2c write at %d val %0X",data[0],data[1]); + + dwt_settimeout(I2C_TIMEOUT); + DEBUG("Wait busy"); + while(I2C1->SR2 & I2C_SR2_BUSY) {CHECK_TIMEOUT;}; + + + I2C1->CR1 = I2C_CR1_PE | I2C_CR1_START; + dwt_settimeout(I2C_TIMEOUT); + DEBUG("Wait SB"); + while(!(I2C1->SR1 & I2C_SR1_SB)) {CHECK_TIMEOUT;}; + I2C1->DR = (hw_adr & 0xFE); + + if(!waitSRBitSet(I2C_SR1_ADDR)) return false; + (void)I2C1->SR2; + + while(len--){ + if(!waitSRBitSet(I2C_SR1_TXE)) return false; + I2C1->DR = *data++; + } + + dwt_settimeout(I2C_TIMEOUT); + DEBUG("Wait BTF"); + while(!((I2C1->SR1 & I2C_SR1_TXE) && (I2C1->SR1 & I2C_SR1_BTF))) {CHECK_TIMEOUT;}; + I2C1->CR1 = I2C_CR1_PE | I2C_CR1_STOP; + + return 1; + } + +static uint8_t i2c_read(const uint8_t hw_adr, uint16_t addr, uint8_t *data, uint32_t len){ + + dwt_settimeout(I2C_TIMEOUT); + DEBUG("Wait busy"); + while(I2C1->SR2 & I2C_SR2_BUSY) {CHECK_TIMEOUT;}; + + //Запись адреса + I2C1->CR1 = I2C_CR1_PE | I2C_CR1_START; + + dwt_settimeout(I2C_TIMEOUT); + DEBUG("Wait SB"); + while(!(I2C1->SR1 & I2C_SR1_SB)) {CHECK_TIMEOUT;}; //Условие старт + + + I2C1->DR = ((hw_adr & 0xFE) + ((addr/256) << 1)); + if(!waitSRBitSet(I2C_SR1_ADDR)) return false; //i2c адрес отправлен + I2C1->SR2; + + if(!waitSRBitSet(I2C_SR1_TXE)) return false; + I2C1->DR = addr%256; //адрес в памяти отправлен + + dwt_settimeout(I2C_TIMEOUT); + DEBUG("Wait BTF"); + while(!((I2C1->SR1 & I2C_SR1_TXE) && (I2C1->SR1 & I2C_SR1_BTF))) {CHECK_TIMEOUT;}; + + //Чтение + I2C1->CR1 = I2C_CR1_PE | I2C_CR1_START | I2C_CR1_ACK; + + dwt_settimeout(I2C_TIMEOUT); + DEBUG("Wait SB"); + while(!(I2C1->SR1 & I2C_SR1_SB)) {CHECK_TIMEOUT;}; + I2C1->DR = hw_adr|1; + + if(!waitSRBitSet(I2C_SR1_ADDR)) return false; + I2C1->SR2; + I2C1->CR1 = I2C_CR1_PE | I2C_CR1_STOP; + + if(!waitSRBitSet(I2C_SR1_RXNE)) return false; + *data = I2C1->DR; + + return true; + } + + +static bool waitSRBitSet(uint32_t Bit){ + uint32_t sr; + + dwt_settimeout(I2C_TIMEOUT); + do{ + sr = I2C1->SR1; + if(sr & ( I2C_SR1_AF | I2C_SR1_ARLO | I2C_SR1_BERR)){ + I2C1->CR1 = I2C_CR1_PE | I2C_CR1_STOP; + I2C1->SR1 = 0; + ERROR("I2C Error flag %0X",sr); + return false; + } + if(dwt_get_timeout() == 0){ + ERROR("Timeout %0X",Bit); + return false; + } + + }while(!(sr & Bit)); + + return true; +}; + + +#endif // I2C_EEPROM diff --git a/Marlin/src/HAL/STM32F1/eeprom_spi_w25q.cpp b/Marlin/src/HAL/STM32F1/eeprom_spi_w25q.cpp new file mode 100644 index 0000000000..495500e3ba --- /dev/null +++ b/Marlin/src/HAL/STM32F1/eeprom_spi_w25q.cpp @@ -0,0 +1,272 @@ +/** +MKS Robin Nano +U5 W25Q64BV, 16K SERIAL EEPROM: + + +*/ +#include "../../inc/MarlinConfig.h" + +#if ENABLED(SPI_EEPROM_W25Q) + +#include "../HAL.h" +#include "../../module/mks_wifi/small_cmsis.h" +#include "../../module/mks_wifi/dwt.h" + +#define SPI_DIR_READ 0 +#define SPI_DIR_WRITE 1 + +#define W25X_WriteEnable 0x06 +#define W25X_WriteDisable 0x04 +#define W25X_ReadStatusReg 0x05 +#define W25X_WriteStatusReg 0x01 +#define W25X_ReadData 0x03 +#define W25X_FastReadData 0x0B +#define W25X_PageProgram 0x02 +#define W25X_BlockErase 0xD8 +#define W25X_SectorErase 0x20 +#define W25X_ChipErase 0xC7 +#define W25X_ReleasePowerDown 0xAB +#define W25X_DeviceID 0xAB +#define W25X_ManufactDeviceID 0x90 +#define W25X_JedecDeviceID 0x9F + +#define SPI_EEPROM_SIZE 2048 +#define SPIFLASH_PAGESIZE 256 +#define SPI_TIMEOUT 2000 //таймаут на ожидание опереций +#define CHECK_TIMEOUT do{if(dwt_get_timeout() == 0){ERROR("Timeout");return 0;}}while(0) + +#define SPI2_START PORTB->BSRR=GPIO_BSRR_BR12 +#define SPI2_STOP PORTB->BSRR=GPIO_BSRR_BS12 + +volatile uint8_t spi_eeprom[SPI_EEPROM_SIZE]; + +uint8_t spi_send(uint8_t data); +void spi_read(uint32_t addr, uint8_t *buf, uint32_t len); +void spi_write(uint32_t addr, uint8_t *buf, uint32_t len); +uint8_t spi_read_status(void); + + +void eeprom_hw_init(void){ + uint32_t tmp; + uint8_t device_id, manuf_id; + uint16_t chip_id; + +/* +SPI2 +MISO - PB14 Input floating / Input pull-up +MOSI - PB15 Alternate function push-pull +SCK - PB13 Alternate function push-pull +CS - PB12 Out push-pull +*/ + + DEBUG("Start SPI"); + + dwt_init(); + + RCC->APB2ENR |= RCC_APB2ENR_IOPBEN|RCC_APB2ENR_AFIOEN; + + tmp = PORTB->CRH; + tmp |= (GPIO_CRH_MODE13|GPIO_CRH_MODE15|GPIO_CRH_CNF13|GPIO_CRH_CNF15); + tmp &= ~(GPIO_CRH_MODE14|GPIO_CRH_CNF14); + tmp |= GPIO_CRH_CNF14_0; + tmp &= ~GPIO_CRH_CNF12; + tmp |= GPIO_CRH_MODE12; + PORTB->CRH = tmp; + + SPI2_STOP; + + RCC->APB1ENR|= RCC_APB1ENR_SPI2EN; + + SPI2->CR1 = SPI_CR1_SSM|\ + SPI_CR1_SSI|\ + (6 << SPI_CR1_BR_Pos)|\ + SPI_CR1_CPHA|\ + SPI_CR1_MSTR; + + SPI2->CR1 |= SPI_CR1_SPE; + + //Wake up + SPI2_START; + spi_send(W25X_ReleasePowerDown); + SPI2_STOP; + + for(uint32_t i=0; i<0x1000; i++){NOP;} //3us для выхода из power down + + //Device ID + SPI2_START; + spi_send(W25X_DeviceID); + for(uint32_t i=0; i<3; i++){spi_send(0);} + device_id = spi_send(0); + SPI2_STOP; + + //Jedec ID + SPI2_START; + spi_send(W25X_JedecDeviceID); + manuf_id = spi_send(0); + chip_id = spi_send(0) << 8; + chip_id |= spi_send(0); + DEBUG("W25Q Device ID %0X Manuf ID: %0X Chip ID %0X",device_id,manuf_id,chip_id); + SPI2_STOP; + + spi_read(SPI_EEPROM_OFFSET,(uint8_t *)spi_eeprom,SPI_EEPROM_SIZE); +} + +void eeprom_hw_deinit(void){ + + DEBUG("Finish SPI"); + //Write Enable + SPI2_START; + spi_send(W25X_WriteEnable); + SPI2_STOP; + + while (spi_read_status() & 1){ //Busy + NOP; + } + + //Erase 4K + SPI2_START; + spi_send(W25X_SectorErase); + spi_send((SPI_EEPROM_OFFSET >> 16) & 0xFF); + spi_send((SPI_EEPROM_OFFSET >> 8) & 0xFF); + spi_send(SPI_EEPROM_OFFSET & 0xFF); + SPI2_STOP; + + while (spi_read_status() & 1){ //Busy + NOP; + } + //write + spi_write(SPI_EEPROM_OFFSET,(uint8_t *)spi_eeprom,SPI_EEPROM_SIZE); + //deinit spi + +} + +void eeprom_write_byte(uint8_t *pos, unsigned char value){ + uint16_t addr=(unsigned)pos; + + if(addr < SPI_EEPROM_SIZE){ + spi_eeprom[addr]=value; + }else{ + ERROR("Write out of SPI size: %d %d",addr,SPI_EEPROM_SIZE); + } +} + +uint8_t eeprom_read_byte(uint8_t *pos) { + uint16_t addr=(unsigned)pos; + + if(addr < SPI_EEPROM_SIZE){ + return spi_eeprom[addr]; + }else{ + ERROR("Read out of SPI size: %d %d",addr,SPI_EEPROM_SIZE); + return 0; + } +} + +void eeprom_read_block(void *__dst, const void *__src, size_t __n){ + ERROR("Call to missing function"); +}; + +void eeprom_update_block(const void *__src, void *__dst, size_t __n){ + ERROR("Call to missing function"); +}; + + +uint8_t spi_send(uint8_t data){ + + while((SPI2->SR & SPI_SR_TXE) == 0){NOP;}; + SPI2->DR = data; + + while((SPI2->SR & SPI_SR_RXNE) == 0){NOP;}; + return SPI2->DR; +} + + +void spi_read(uint32_t addr, uint8_t *buf, uint32_t len){ + + if( (len == 0) || (len > SPI_EEPROM_SIZE) ){ + ERROR("Len size error: %d",len); + return; + } + + addr &= 0xFFFFFF; //24bit address + + SPI2_START; + if(len == 1){ + spi_send(W25X_ReadData); + spi_send((addr >> 16) & 0xFF); + spi_send((addr >> 8) & 0xFF); + spi_send(addr & 0xFF); + }else{ + spi_send(W25X_FastReadData); + spi_send((addr >> 16) & 0xFF); + spi_send((addr >> 8) & 0xFF); + spi_send(addr & 0xFF); + spi_send(0); + } + + while (len--){ + *buf++ = spi_send(0); + } + SPI2_STOP; +} + +void spi_write(uint32_t addr, uint8_t *buf, uint32_t len){ + + uint16_t bytes_in_page = SPIFLASH_PAGESIZE - (addr % SPIFLASH_PAGESIZE); + uint16_t offset = 0; + + addr &= 0xFFFFFF; //24bit address + + while (spi_read_status() & 1){ //Busy + NOP; + } + //Write Enable + + while (len > 0){ + uint16_t batch_size = (len <= bytes_in_page) ? len : bytes_in_page; + + SPI2_START; + spi_send(W25X_WriteEnable); + SPI2_STOP; + + while (spi_read_status() & 1){ //Busy + NOP; + } + + SPI2_START; + spi_send(W25X_PageProgram); + spi_send((addr >> 16) & 0xFF); + spi_send((addr >> 8) & 0xFF); + spi_send(addr & 0xFF); + + for (uint32_t i = 0; i < batch_size; i++){ + spi_send(((uint8_t*)buf)[offset + i]); + } + + SPI2_STOP; + + //wait till it's programmed + while (spi_read_status() & 2){ //Busy + NOP; + } + + addr += batch_size; + offset += batch_size; + len -= batch_size; + bytes_in_page = SPIFLASH_PAGESIZE; + } + +} + + +uint8_t spi_read_status(void){ + uint8_t data; + + SPI2_START; + spi_send(W25X_ReadStatusReg); + data = spi_send(0); + SPI2_STOP; + return data; +} + + +#endif // SPI_EEPROM_W25Q diff --git a/Marlin/src/feature/touch/xpt2046.cpp b/Marlin/src/feature/touch/xpt2046.cpp index 26e25950d8..186a13045a 100644 --- a/Marlin/src/feature/touch/xpt2046.cpp +++ b/Marlin/src/feature/touch/xpt2046.cpp @@ -43,18 +43,21 @@ XPT2046 touch; extern int8_t encoderDiff; -void XPT2046::init() { + +void XPT2046::begin() { SET_INPUT(TOUCH_MISO_PIN); SET_OUTPUT(TOUCH_MOSI_PIN); SET_OUTPUT(TOUCH_SCK_PIN); OUT_WRITE(TOUCH_CS_PIN, HIGH); +} - #if PIN_EXISTS(TOUCH_INT) - // Optional Pendrive interrupt pin - SET_INPUT(TOUCH_INT_PIN); - #endif +void XPT2046::end() { + SET_INPUT(TOUCH_MISO_PIN); + SET_INPUT(TOUCH_MOSI_PIN); + SET_INPUT(TOUCH_SCK_PIN); +} - // Read once to enable pendrive status pin +void XPT2046::init() { getInTouch(XPT2046_X); } @@ -78,7 +81,8 @@ uint8_t XPT2046::read_buttons() { y = uint16_t(((uint32_t(getInTouch(XPT2046_Y))) * tsoffsets[2]) >> 16) + tsoffsets[3]; if (!isTouched()) return 0; // Fingers must still be on the TS for a valid read. - if (y < 175 || y > 234) return 0; +//@ little more Y + if (y < 165 || y > 234) return 0; return WITHIN(x, 14, 77) ? EN_D : WITHIN(x, 90, 153) ? EN_A @@ -100,6 +104,7 @@ bool XPT2046::isTouched() { uint16_t XPT2046::getInTouch(const XPTCoordinate coordinate) { uint16_t data[3]; + begin(); OUT_WRITE(TOUCH_CS_PIN, LOW); const uint8_t coord = uint8_t(coordinate) | XPT2046_CONTROL | XPT2046_DFR_MODE; @@ -121,6 +126,7 @@ uint16_t XPT2046::getInTouch(const XPTCoordinate coordinate) { } WRITE(TOUCH_CS_PIN, HIGH); + end(); uint16_t delta01 = _MAX(data[0], data[1]) - _MIN(data[0], data[1]), delta02 = _MAX(data[0], data[2]) - _MIN(data[0], data[2]), diff --git a/Marlin/src/feature/touch/xpt2046.h b/Marlin/src/feature/touch/xpt2046.h index 7f8eece1f4..9eeddec523 100644 --- a/Marlin/src/feature/touch/xpt2046.h +++ b/Marlin/src/feature/touch/xpt2046.h @@ -41,6 +41,9 @@ enum XPTCoordinate : uint8_t { class XPT2046 { public: static void init(); + static void begin(); + static void end(); + static uint8_t read_buttons(); bool getTouchPoint(uint16_t &x, uint16_t &y); static bool isTouched(); diff --git a/Marlin/src/libs/fatfs/ff.cpp b/Marlin/src/libs/fatfs/ff.cpp index 563ec3b1fd..271e733738 100644 --- a/Marlin/src/libs/fatfs/ff.cpp +++ b/Marlin/src/libs/fatfs/ff.cpp @@ -6534,7 +6534,7 @@ static void putc_bfd (putbuff* pb, TCHAR c) WCHAR hs, wc; #if FF_LFN_UNICODE == 2 DWORD dc; - TCHAR *tp; + const TCHAR *tp; #endif #endif @@ -6576,7 +6576,7 @@ static void putc_bfd (putbuff* pb, TCHAR c) return; } } - tp = (TCHAR*)pb->bs; + tp = (const TCHAR*)pb->bs; dc = tchar2uni(&tp); /* UTF-8 ==> UTF-16 */ if (dc == 0xFFFFFFFF) return; /* Wrong code? */ wc = (WCHAR)dc; diff --git a/Marlin/src/libs/fatfs/sdio_driver.cpp b/Marlin/src/libs/fatfs/sdio_driver.cpp index 09ab05475d..ae097bba71 100644 --- a/Marlin/src/libs/fatfs/sdio_driver.cpp +++ b/Marlin/src/libs/fatfs/sdio_driver.cpp @@ -59,13 +59,15 @@ uint8_t SD_Cmd(uint8_t cmd, uint32_t arg, uint16_t response_type, uint32_t *resp return 0; } -//#pragma GCC push_options -//#pragma GCC optimize ("O0") uint32_t SD_transfer(uint8_t *buf, uint32_t blk, uint32_t cnt, uint32_t dir){ uint32_t trials; uint8_t cmd=0; uint8_t *ptr = buf; - + + if (SDCard.Type != SDCT_SDHC) { + blk = blk * 512; + } + trials=SDIO_DATA_TIMEOUT; while (transmit && trials--) {}; if(!trials) { @@ -158,7 +160,6 @@ uint32_t SD_transfer(uint8_t *buf, uint32_t blk, uint32_t cnt, uint32_t dir){ SDIO->ICR=SDIO_ICR_STATIC; return 0; }; -//#pragma GCC pop_options uint8_t SD_Init(void) { volatile uint32_t trials = 0x0000FFFF; @@ -199,6 +200,9 @@ uint8_t SD_Init(void) { return 41; }; + SDCard.Type = (response[0] & SD_HIGH_CAPACITY) ? SDCT_SDHC : SDCT_SDSC_V2; + DEBUG("Card type %d",SDCard.Type); + result = SD_Cmd(SD_CMD2,0x00,SDIO_RESP_LONG,(uint32_t*)response); //CMD2 CID R2 if (result != 0) { ERROR("CMD2: %d",result); @@ -270,6 +274,14 @@ uint8_t SD_Init(void) { SDIO->CLKCR=tempreg; #endif + if ((SDCard.Type != SDCT_SDHC)) { + result = SD_Cmd(SD_CMD_SET_BLOCKLEN, 512 ,SDIO_RESP_SHORT,(uint32_t*)response); //CMD16 + if (result != 0) { + ERROR("Error set block size"); + return 16; + } + } + DEBUG("SDINIT: ok"); return 0; }; diff --git a/Marlin/src/libs/fatfs/sdio_driver.h b/Marlin/src/libs/fatfs/sdio_driver.h index 9db28f2cb1..158f7cd877 100644 --- a/Marlin/src/libs/fatfs/sdio_driver.h +++ b/Marlin/src/libs/fatfs/sdio_driver.h @@ -60,12 +60,25 @@ typedef struct { uint8_t ake_seq_error; //Ошибка в последовательности аутентификации. } SD_Status_TypeDef; +// Card type +enum { + SDCT_UNKNOWN = 0x00, + SDCT_SDSC_V1 = 0x01, // Standard capacity SD card v1.0 + SDCT_SDSC_V2 = 0x02, // Standard capacity SD card v2.0 + SDCT_MMC = 0x03, // MMC + SDCT_SDHC = 0x04 // High capacity SD card (SDHC or SDXC) +}; + #define SDIO_4BIT_Mode 1 //#define SDIO_HIGH_SPEED 1 #define SDIO_DATA_TIMEOUT ((uint32_t)0x01000000) +// Mask for ACMD41 +#define SD_STD_CAPACITY ((uint32_t)0x00000000U) +#define SD_HIGH_CAPACITY ((uint32_t)0x40000000U) + // SDIO CMD response type #define SDIO_RESP_NONE 0x00 // No response #define SDIO_RESP_SHORT SDIO_CMD_WAITRESP_0 // Short response diff --git a/Marlin/src/module/mks_wifi/mks_wifi.cpp b/Marlin/src/module/mks_wifi/mks_wifi.cpp index 00dd772312..839d1b28d3 100644 --- a/Marlin/src/module/mks_wifi/mks_wifi.cpp +++ b/Marlin/src/module/mks_wifi/mks_wifi.cpp @@ -30,6 +30,13 @@ void mks_wifi_init(void){ safe_delay(1000); WRITE(MKS_WIFI_IO4, LOW); + #ifdef LIST_FILES_AT_STARTUP + mks_wifi_sd_deinit(); + mks_wifi_sd_init(); + mks_wifi_sd_ls(); + mks_wifi_sd_deinit(); + #endif + } diff --git a/Marlin/src/module/mks_wifi/mks_wifi.h b/Marlin/src/module/mks_wifi/mks_wifi.h index de6d5fc818..c7bfe84e33 100644 --- a/Marlin/src/module/mks_wifi/mks_wifi.h +++ b/Marlin/src/module/mks_wifi/mks_wifi.h @@ -12,6 +12,8 @@ #define WIFI_MODE_AP (uint8_t)1 +#define LIST_FILES_AT_STARTUP (uint8_t)1 + typedef struct { uint8_t type; diff --git a/Marlin/src/module/mks_wifi/mks_wifi_sd.cpp b/Marlin/src/module/mks_wifi/mks_wifi_sd.cpp index 808016a373..f39342ceda 100644 --- a/Marlin/src/module/mks_wifi/mks_wifi_sd.cpp +++ b/Marlin/src/module/mks_wifi/mks_wifi_sd.cpp @@ -260,6 +260,20 @@ void mks_wifi_start_file_upload(ESP_PROTOC_FRAME *packet){ ui.set_status((const char *)"Upload done",true); DEBUG("Upload ok"); BUZZ(1000,260); + + str[0]='0'; + str[1]=':'; + str[2]='/'; + + memcpy((uint8_t *)str+3,(uint8_t *)&packet->data[5],(packet->dataLen - 5)); + str[packet->dataLen - 5 + 3] = 0; + + if(!strcmp(str,"0:/Robin_Nano35.bin")){ + DEBUG("Firmware found, reboot"); + nvic_sys_reset(); + } + + }else{ ui.set_status((const char *)"Upload failed",true); DEBUG("Upload failed! File size: %d; Recieve %d; SD write %d",file_size,file_inc_size,file_size_writen); diff --git a/Marlin/src/module/mks_wifi/small_cmsis.h b/Marlin/src/module/mks_wifi/small_cmsis.h index 8a4d52bd0e..1ca98cd160 100644 --- a/Marlin/src/module/mks_wifi/small_cmsis.h +++ b/Marlin/src/module/mks_wifi/small_cmsis.h @@ -142,6 +142,18 @@ typedef struct __IO uint32_t MAPR2; } AFIO_TypeDef; +typedef struct +{ + __IO uint32_t CR1; + __IO uint32_t CR2; + __IO uint32_t SR; + __IO uint32_t DR; + __IO uint32_t CRCPR; + __IO uint32_t RXCRCR; + __IO uint32_t TXCRCR; + __IO uint32_t I2SCFGR; + __IO uint32_t I2SPR; +} SPI_TypeDef; #define PERIPH_BASE 0x40000000U /*!< Peripheral base address in the alias region */ @@ -161,7 +173,7 @@ typedef struct #define AFIOBASE (APB2PERIPH_BASE + 0x00000000U) #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ - +#define SPI2_BASE (APB1PERIPH_BASE + 0x00003800U) #define RCC ((RCC_TypeDef *)RCC_BASE) #define SDIO ((SDIO_TypeDef *)SDIO_BASE) @@ -177,6 +189,7 @@ typedef struct #define AFIO ((AFIO_TypeDef *)AFIOBASE) #define CoreDebug ((CoreDebug_Type *)CoreDebug_BASE) /*!< Core Debug configuration struct */ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define SPI2 ((SPI_TypeDef *)SPI2_BASE) /******************************************************************************/ /* */ /* Universal Synchronous Asynchronous Receiver Transmitter */ @@ -1708,5 +1721,119 @@ typedef struct #define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ #define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ +/******************************************************************************/ +/* */ +/* Serial Peripheral Interface */ +/* */ +/******************************************************************************/ +/* + * @brief Specific device feature definitions (not present on all devices in the STM32F1 serie) + */ +#define SPI_I2S_SUPPORT /*!< I2S support */ +/******************* Bit definition for SPI_CR1 register ********************/ +#define SPI_CR1_CPHA_Pos (0U) +#define SPI_CR1_CPHA_Msk (0x1U << SPI_CR1_CPHA_Pos) /*!< 0x00000001 */ +#define SPI_CR1_CPHA SPI_CR1_CPHA_Msk /*!< Clock Phase */ +#define SPI_CR1_CPOL_Pos (1U) +#define SPI_CR1_CPOL_Msk (0x1U << SPI_CR1_CPOL_Pos) /*!< 0x00000002 */ +#define SPI_CR1_CPOL SPI_CR1_CPOL_Msk /*!< Clock Polarity */ +#define SPI_CR1_MSTR_Pos (2U) +#define SPI_CR1_MSTR_Msk (0x1U << SPI_CR1_MSTR_Pos) /*!< 0x00000004 */ +#define SPI_CR1_MSTR SPI_CR1_MSTR_Msk /*!< Master Selection */ + +#define SPI_CR1_BR_Pos (3U) +#define SPI_CR1_BR_Msk (0x7U << SPI_CR1_BR_Pos) /*!< 0x00000038 */ +#define SPI_CR1_BR SPI_CR1_BR_Msk /*!< BR[2:0] bits (Baud Rate Control) */ +#define SPI_CR1_BR_0 (0x1U << SPI_CR1_BR_Pos) /*!< 0x00000008 */ +#define SPI_CR1_BR_1 (0x2U << SPI_CR1_BR_Pos) /*!< 0x00000010 */ +#define SPI_CR1_BR_2 (0x4U << SPI_CR1_BR_Pos) /*!< 0x00000020 */ + +#define SPI_CR1_SPE_Pos (6U) +#define SPI_CR1_SPE_Msk (0x1U << SPI_CR1_SPE_Pos) /*!< 0x00000040 */ +#define SPI_CR1_SPE SPI_CR1_SPE_Msk /*!< SPI Enable */ +#define SPI_CR1_LSBFIRST_Pos (7U) +#define SPI_CR1_LSBFIRST_Msk (0x1U << SPI_CR1_LSBFIRST_Pos) /*!< 0x00000080 */ +#define SPI_CR1_LSBFIRST SPI_CR1_LSBFIRST_Msk /*!< Frame Format */ +#define SPI_CR1_SSI_Pos (8U) +#define SPI_CR1_SSI_Msk (0x1U << SPI_CR1_SSI_Pos) /*!< 0x00000100 */ +#define SPI_CR1_SSI SPI_CR1_SSI_Msk /*!< Internal slave select */ +#define SPI_CR1_SSM_Pos (9U) +#define SPI_CR1_SSM_Msk (0x1U << SPI_CR1_SSM_Pos) /*!< 0x00000200 */ +#define SPI_CR1_SSM SPI_CR1_SSM_Msk /*!< Software slave management */ +#define SPI_CR1_RXONLY_Pos (10U) +#define SPI_CR1_RXONLY_Msk (0x1U << SPI_CR1_RXONLY_Pos) /*!< 0x00000400 */ +#define SPI_CR1_RXONLY SPI_CR1_RXONLY_Msk /*!< Receive only */ +#define SPI_CR1_DFF_Pos (11U) +#define SPI_CR1_DFF_Msk (0x1U << SPI_CR1_DFF_Pos) /*!< 0x00000800 */ +#define SPI_CR1_DFF SPI_CR1_DFF_Msk /*!< Data Frame Format */ +#define SPI_CR1_CRCNEXT_Pos (12U) +#define SPI_CR1_CRCNEXT_Msk (0x1U << SPI_CR1_CRCNEXT_Pos) /*!< 0x00001000 */ +#define SPI_CR1_CRCNEXT SPI_CR1_CRCNEXT_Msk /*!< Transmit CRC next */ +#define SPI_CR1_CRCEN_Pos (13U) +#define SPI_CR1_CRCEN_Msk (0x1U << SPI_CR1_CRCEN_Pos) /*!< 0x00002000 */ +#define SPI_CR1_CRCEN SPI_CR1_CRCEN_Msk /*!< Hardware CRC calculation enable */ +#define SPI_CR1_BIDIOE_Pos (14U) +#define SPI_CR1_BIDIOE_Msk (0x1U << SPI_CR1_BIDIOE_Pos) /*!< 0x00004000 */ +#define SPI_CR1_BIDIOE SPI_CR1_BIDIOE_Msk /*!< Output enable in bidirectional mode */ +#define SPI_CR1_BIDIMODE_Pos (15U) +#define SPI_CR1_BIDIMODE_Msk (0x1U << SPI_CR1_BIDIMODE_Pos) /*!< 0x00008000 */ +#define SPI_CR1_BIDIMODE SPI_CR1_BIDIMODE_Msk /*!< Bidirectional data mode enable */ + +/******************* Bit definition for SPI_CR2 register ********************/ +#define SPI_CR2_RXDMAEN_Pos (0U) +#define SPI_CR2_RXDMAEN_Msk (0x1U << SPI_CR2_RXDMAEN_Pos) /*!< 0x00000001 */ +#define SPI_CR2_RXDMAEN SPI_CR2_RXDMAEN_Msk /*!< Rx Buffer DMA Enable */ +#define SPI_CR2_TXDMAEN_Pos (1U) +#define SPI_CR2_TXDMAEN_Msk (0x1U << SPI_CR2_TXDMAEN_Pos) /*!< 0x00000002 */ +#define SPI_CR2_TXDMAEN SPI_CR2_TXDMAEN_Msk /*!< Tx Buffer DMA Enable */ +#define SPI_CR2_SSOE_Pos (2U) +#define SPI_CR2_SSOE_Msk (0x1U << SPI_CR2_SSOE_Pos) /*!< 0x00000004 */ +#define SPI_CR2_SSOE SPI_CR2_SSOE_Msk /*!< SS Output Enable */ +#define SPI_CR2_ERRIE_Pos (5U) +#define SPI_CR2_ERRIE_Msk (0x1U << SPI_CR2_ERRIE_Pos) /*!< 0x00000020 */ +#define SPI_CR2_ERRIE SPI_CR2_ERRIE_Msk /*!< Error Interrupt Enable */ +#define SPI_CR2_RXNEIE_Pos (6U) +#define SPI_CR2_RXNEIE_Msk (0x1U << SPI_CR2_RXNEIE_Pos) /*!< 0x00000040 */ +#define SPI_CR2_RXNEIE SPI_CR2_RXNEIE_Msk /*!< RX buffer Not Empty Interrupt Enable */ +#define SPI_CR2_TXEIE_Pos (7U) +#define SPI_CR2_TXEIE_Msk (0x1U << SPI_CR2_TXEIE_Pos) /*!< 0x00000080 */ +#define SPI_CR2_TXEIE SPI_CR2_TXEIE_Msk /*!< Tx buffer Empty Interrupt Enable */ + +/******************** Bit definition for SPI_SR register ********************/ +#define SPI_SR_RXNE_Pos (0U) +#define SPI_SR_RXNE_Msk (0x1U << SPI_SR_RXNE_Pos) /*!< 0x00000001 */ +#define SPI_SR_RXNE SPI_SR_RXNE_Msk /*!< Receive buffer Not Empty */ +#define SPI_SR_TXE_Pos (1U) +#define SPI_SR_TXE_Msk (0x1U << SPI_SR_TXE_Pos) /*!< 0x00000002 */ +#define SPI_SR_TXE SPI_SR_TXE_Msk /*!< Transmit buffer Empty */ +#define SPI_SR_CHSIDE_Pos (2U) +#define SPI_SR_CHSIDE_Msk (0x1U << SPI_SR_CHSIDE_Pos) /*!< 0x00000004 */ +#define SPI_SR_CHSIDE SPI_SR_CHSIDE_Msk /*!< Channel side */ +#define SPI_SR_UDR_Pos (3U) +#define SPI_SR_UDR_Msk (0x1U << SPI_SR_UDR_Pos) /*!< 0x00000008 */ +#define SPI_SR_UDR SPI_SR_UDR_Msk /*!< Underrun flag */ +#define SPI_SR_CRCERR_Pos (4U) +#define SPI_SR_CRCERR_Msk (0x1U << SPI_SR_CRCERR_Pos) /*!< 0x00000010 */ +#define SPI_SR_CRCERR SPI_SR_CRCERR_Msk /*!< CRC Error flag */ +#define SPI_SR_MODF_Pos (5U) +#define SPI_SR_MODF_Msk (0x1U << SPI_SR_MODF_Pos) /*!< 0x00000020 */ +#define SPI_SR_MODF SPI_SR_MODF_Msk /*!< Mode fault */ +#define SPI_SR_OVR_Pos (6U) +#define SPI_SR_OVR_Msk (0x1U << SPI_SR_OVR_Pos) /*!< 0x00000040 */ +#define SPI_SR_OVR SPI_SR_OVR_Msk /*!< Overrun flag */ +#define SPI_SR_BSY_Pos (7U) +#define SPI_SR_BSY_Msk (0x1U << SPI_SR_BSY_Pos) /*!< 0x00000080 */ +#define SPI_SR_BSY SPI_SR_BSY_Msk /*!< Busy flag */ + +/******************** Bit definition for SPI_DR register ********************/ +#define SPI_DR_DR_Pos (0U) +#define SPI_DR_DR_Msk (0xFFFFU << SPI_DR_DR_Pos) /*!< 0x0000FFFF */ +#define SPI_DR_DR SPI_DR_DR_Msk /*!< Data Register */ + +/******************* Bit definition for SPI_CRCPR register ******************/ +#define SPI_CRCPR_CRCPOLY_Pos (0U) +#define SPI_CRCPR_CRCPOLY_Msk (0xFFFFU << SPI_CRCPR_CRCPOLY_Pos) /*!< 0x0000FFFF */ +#define SPI_CRCPR_CRCPOLY SPI_CRCPR_CRCPOLY_Msk /*!< CRC polynomial register */ + #endif \ No newline at end of file diff --git a/Marlin/src/pins/stm32f1/pins_MKS_ROBIN_NANO.h b/Marlin/src/pins/stm32f1/pins_MKS_ROBIN_NANO.h index a6b32fed88..920f104c27 100644 --- a/Marlin/src/pins/stm32f1/pins_MKS_ROBIN_NANO.h +++ b/Marlin/src/pins/stm32f1/pins_MKS_ROBIN_NANO.h @@ -163,3 +163,4 @@ #define MKS_WIFI_IO4 PC7 #define MKS_WIFI_IO_RST PA5 #endif + diff --git a/README.md b/README.md index 256da75cbe..4ffd951c7b 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,11 @@ ## Версия с тестовой поддержкой WIFI модуля -Это конфигурация [официального Marlin](https://github.com/MarlinFirmware/Marlin) для принтера Flying Bear Ghost 4S. +Это конфигурация [официального Marlin](https://github.com/MarlinFirmware/Marlin) для принтера Flying Bear Ghost 4S (плата MKS Robin Nano). Эта ветка содержит код для работы с WIFI модулем, установленным в FB4S. Загрузка файлов через стандартный plugin в Cura. +Код работы с экраном взят из репозитория [inib/Marlin](https://github.com/inib/Marlin) + +В ветке [FB4S_Config](https://github.com/Sergey1560/Marlin_FB4S/tree/FB4S_Config) находится вариант с минимальными изменениями в коде Marlin (только работа с экраном и конфигурация) ## Что работает, что не работает @@ -19,9 +22,8 @@ ### Не работает (совсем) * **Имена файлов на русском** Переименуйте файл в Cura -* Работает только с картами стандарта SDHC и новее. Это все карты от 4Гб и больше. +* Работает только с картами стандарта SD card v2.0 и новее. Это все карты от 1Гб и больше. * Отображение состояния принтера (печатает, не печатает) в Cura -* Все остальное, что не в указано в "работает" ## Как работает, как настроить @@ -84,139 +86,65 @@ IP адрес так же будет на экране. В качестве места хренения EEPROM в Marlin доступны несколько вариантов: * SD карта. Этот вариант наиболее предпочтительный, если нет осознанного желания хранить EEPROM где-то еще. +* I2C EEPROM. Хранение в AT24C16 подключенной по I2C. При первом включении все содержимое AT24C16 будет переписано. Память не быстрая, поэтому процесс занимает до 10 секунд. В дальнейшем в память пишутся только измененные значения, поэтому работает быстрее. +* SPI_EEPROM. Хранение в W25Q64BV подключенной по SPI. +* FLASH_EEPROM_EMULATION. Это хранение EEPROM в flash памяти STM32. Этот вариант не работает. +* SRAM_EEPROM_EMULATION. Этот вариант не работает. -Для включения в [Configuration.h](./Marlin/Configuration.h) в разделе EEPROM должно быть включено SDCARD_EEPROM_EMULATION и отключены другие опции хранения. Пример: +Для включения в [Configuration.h](./Marlin/Configuration.h) в разделе EEPROM нужно указать нужный define. Возможные варианты указаны в комментарии. Пример: ```C -#define EEPROM_SETTINGS // Persistent storage with M500 and M501 -#define EEPROM_CHITCHAT // Give feedback on EEPROM commands. Disable to save PROGMEM. #if ENABLED(EEPROM_SETTINGS) -#define SDCARD_EEPROM_EMULATION +/* +MKS Robin EEPROM: +EEPROM_SD +EEPROM_AT24C16 +EEPROM_W25Q +*/ +#define EEPROM_SD + +#if ENABLED(EEPROM_AT24C16) +#undef SDCARD_EEPROM_EMULATION #undef USE_REAL_EEPROM #undef FLASH_EEPROM_EMULATION #undef SRAM_EEPROM_EMULATION -//#define USE_WIRED_EEPROM 1 -//#define I2C_EEPROM_AT24C16 -//#define E2END (2*1024 - 1) -#define EEPROM_AUTO_INIT // Init EEPROM automatically on any errors. +#define I2C_EEPROM_AT24C16 +#define USE_WIRED_EEPROM 1 +#define E2END (2*1024 - 1) #endif -``` - -* I2C EEPROM. Для включения нужно включить I2C_EEPROM_AT24C16 и установить USE_WIRED_EEPROM в 1 и задать размер EEPROM в E2END, а остальные опции отключить. Пример: -```C -#define EEPROM_SETTINGS // Persistent storage with M500 and M501 -#define EEPROM_CHITCHAT // Give feedback on EEPROM commands. Disable to save PROGMEM. -#if ENABLED(EEPROM_SETTINGS) +#if ENABLED(EEPROM_W25Q) #undef SDCARD_EEPROM_EMULATION #undef USE_REAL_EEPROM #undef FLASH_EEPROM_EMULATION #undef SRAM_EEPROM_EMULATION +#undef I2C_EEPROM_AT24C16 +#define SPI_EEPROM_W25Q +#define SPI_EEPROM_OFFSET 0x700000 #define USE_WIRED_EEPROM 1 -#define I2C_EEPROM_AT24C16 #define E2END (2*1024 - 1) -#define EEPROM_AUTO_INIT // Init EEPROM automatically on any errors. #endif -``` - -При первом включении все содержимое AT24C16 будет переписано. Память не быстрая, поэтому процесс занимает до 10 секунд. В дальнейшем в память пишутся только измененные значения, поэтому работает быстрее. - -* SPI_EEPROM. Хранение в памяти подключенной по SPI. Этот вариант пока не работает. -* FLASH_EEPROM_EMULATION. Это хранение EEPROM в flash памяти STM32. Этот вариант не работает. -* SRAM_EEPROM_EMULATION. Этот вариант не работает. - -### Работа с Octoprint - -При работе с Octoprint через Uart возможны проблемы при печати. Рекомендуется, увеличить буферы команд в настройках Marlin [Configuration_adv.h](./Marlin/Configuration_adv.h): - -```C -#define MAX_CMD_SIZE 96 //Максимальный размер команды -#define BUFSIZE 32 //Количество команд, которые стоят в плане. -#define TX_BUFFER_SIZE 256 //Размер буфера для отправки -#define RX_BUFFER_SIZE 2048 //Размер буфера для приема -``` - -Процесс получения данных из UART организован следующим образом: - -* используется аппаратный UART STM32 -* включено прерывание по приему каждого байта, данные складываются в буфер внутри драйвера -* Marlin периодически проверяет, есть ли у драйвера в буфере данные, забирает их оттуда и складывает в свой буфер, который задан RX_BUFFER_SIZE. -Есть предположение, что проблемы печати могут быть связаны с тем, что переполняется буфер внутри драйвера. В качестве драйвера использована библиотека libmaple. Обработчик прерывания в файле .platformio/packages/framework-arduinoststm32-maple/STM32F1/system/libmaple/usart_private.h: - -```C -__weak void __irq_usart1(void) { - usart_irq(&usart1_rb, &usart1_wb, USART1_BASE); -} -``` - -В обработчике usart_irq (в файле .platformio/packages/framework-arduinoststm32-maple/STM32F1/system/libmaple/usart_private.h) пришедший байт помещается в буфер функцией - -```C -rb_push_insert(rb, (uint8)regs->DR); -``` - -rb имеет тип структуры ring_buffer: - -```C -typedef struct ring_buffer { - volatile uint8 *buf; /**< Buffer items are stored into */ - volatile uint16 head; /**< Index of the next item to remove */ - volatile uint16 tail; /**< Index where the next item will get inserted */ - volatile uint16 size; /**< Buffer capacity minus one */ -} ring_buffer; -``` - -Сам приемный буфер и его размер задается в .platformio/packages/framework-arduinoststm32-maple/STM32F1/system/libmaple/include/libmaple/usart.h: - -```C -typedef struct usart_dev { - usart_reg_map *regs; /**< Register map */ - ring_buffer *rb; /**< RX ring buffer */ - ring_buffer *wb; /**< TX ring buffer */ - uint32 max_baud; /**< @brief Deprecated. - * Maximum baud rate. */ - uint8 rx_buf[USART_RX_BUF_SIZE]; /**< @brief Deprecated. - * Actual RX buffer used by rb. - * This field will be removed in - * a future release. */ - uint8 tx_buf[USART_TX_BUF_SIZE]; /**< Actual TX buffer used by wb */ - rcc_clk_id clk_id; /**< RCC clock information */ - nvic_irq_num irq_num; /**< USART NVIC interrupt */ -} usart_dev; -``` - -Размер массива задан при помощи USART_RX_BUF_SIZE и USART_TX_BUF_SIZE: - -```C -#ifndef USART_RX_BUF_SIZE -#define USART_RX_BUF_SIZE 64 +#if ENABLED(EEPROM_SD) +#define SDCARD_EEPROM_EMULATION +#undef USE_REAL_EEPROM +#undef FLASH_EEPROM_EMULATION +#undef SRAM_EEPROM_EMULATION +#undef I2C_EEPROM_AT24C16 +#undef SPI_EEPROM_W25Q +#undef USE_WIRED_EEPROM #endif -#ifndef USART_TX_BUF_SIZE -#define USART_TX_BUF_SIZE 64 +#define EEPROM_AUTO_INIT // Init EEPROM automatically on any errors. #endif ``` -Для успешной работы Octoprint возможно имеет смысл увеличить эти значения. Например до 1024. Это предположение не тестировалось на практике. Возможно, одновременно с увеличением размера буферов в драйвере поможет и увеличение скорости UART до 250000. +Для изменения места хранения EEPROM например на SPI флеш, надо заменить "#define EEPROM_SD" на "#define EEPROM_W25Q" -Библиотека libmaple находится внутри platformio, и обновляется автоматически. Поэтому, чтобы не изменять стандартные файлы библиотеки и не потерять изменения при обновлении бибилиотеки, задать параметры лучше через флаги сборки. В файле [platformio.ini](./platformio.ini), в разделе mks_robin_nano надо добавить в build_flags параметры USART_RX_BUF_SIZE и USART_TX_BUF_SIZE. Пример: +### Загрузка прошивки по WIFI -```C -# -# MKS Robin Nano (STM32F103VET6) -# -[env:mks_robin_nano] -platform = ststm32 -board = genericSTM32F103VE -platform_packages = tool-stm32duino -build_flags = !python Marlin/src/HAL/STM32F1/build_flags.py - ${common.build_flags} -std=gnu++14 -DHAVE_SW_SERIAL -DSS_TIMER=4 -DUSART_RX_BUF_SIZE=1024 -DUSART_TX_BUF_SIZE=1024 - -build_unflags = -std=gnu++11 -extra_scripts = buildroot/share/PlatformIO/scripts/mks_robin_nano.py -src_filter = ${common.default_src_filter} + -lib_deps = ${common.lib_deps} - SoftwareSerialM=https://github.com/FYSETC/SoftwareSerialM/archive/master.zip -lib_ignore = Adafruit NeoPixel, SPI -``` +Есть возможность отправлять прошивку на принтер через WIFI. Для этого в файле [platformio.ini](./platformio.ini) в разделе "[env:mks_robin_nano]" нужно указать IP адрес принтера в опции upload_flags (строка 499). + +Передача файла происходит при помощи curl, поэтому надо или добавить curl в $PATH, либо указать полный путь в файле [mks_robin_nano.py](./buildroot/share/PlatformIO/scripts/mks_robin_nano.py) в строке 48. + +После успешной передачи файла принтер перезагрузится автоматически. diff --git a/buildroot/share/PlatformIO/scripts/mks_robin_nano.py b/buildroot/share/PlatformIO/scripts/mks_robin_nano.py index f19e28e1ff..1663b98c96 100755 --- a/buildroot/share/PlatformIO/scripts/mks_robin_nano.py +++ b/buildroot/share/PlatformIO/scripts/mks_robin_nano.py @@ -42,3 +42,9 @@ def encrypt(source, target, env): destination = target[0].dir.path +'/Robin_nano35.bin' shutil.copyfile(source, destination) env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", encrypt); + + +env.Replace( + UPLOADER="curl", + UPLOADCMD="$UPLOADER -v -H 'Content-Type:application/octet-stream' http://$UPLOADERFLAGS/upload?X-Filename=Robin_Nano35.bin --data-binary @$BUILD_DIR/Robin_nano35.bin" +) \ No newline at end of file diff --git a/firmware/2208/Robin_nano35.bin b/firmware/2208/Robin_nano35.bin index acd314e045..623efa2e7d 100644 Binary files a/firmware/2208/Robin_nano35.bin and b/firmware/2208/Robin_nano35.bin differ diff --git a/firmware/bootloader/fb_4s_bootloader.bin b/firmware/bootloader/fb_4s_bootloader.bin new file mode 100644 index 0000000000..0ca7b1c239 Binary files /dev/null and b/firmware/bootloader/fb_4s_bootloader.bin differ diff --git a/firmware/std/Robin_nano35.bin b/firmware/std/Robin_nano35.bin index 2e89d8708f..c761dd5a37 100644 Binary files a/firmware/std/Robin_nano35.bin and b/firmware/std/Robin_nano35.bin differ diff --git a/platformio.ini b/platformio.ini index 0ffb0f6e76..8605e9329c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -494,7 +494,9 @@ src_filter = ${common.default_src_filter} + lib_deps = ${common.lib_deps} SoftwareSerialM=https://github.com/FYSETC/SoftwareSerialM/archive/master.zip lib_ignore = Adafruit NeoPixel, SPI - +upload_protocol = custom +upload_flags = + 192.168.0.107 # # MKS Robin (STM32F103ZET6) #