#include "mks_wifi_sd.h" #include "../../MarlinCore.h" #include "../../lcd/marlinui.h" #include "../../libs/fatfs/ff.h" #include "../../libs/buzzer.h" #include "../temperature.h" #include "../../libs/fatfs/fatfs_shared.h" #include "uart.h" #ifdef MKS_WIFI #if ENABLED(TFT_480x320) || ENABLED(TFT_480x320_SPI) #include "mks_wifi_ui.h" #endif volatile uint8_t *file_buff=shared_mem; volatile uint8_t *file_buff_pos; volatile uint16_t file_data_size; volatile uint8_t *dma_buff[] = {file_buff+FILE_BUFFER_SIZE,file_buff+FILE_BUFFER_SIZE+ESP_PACKET_SIZE}; volatile uint8_t dma_buff_index=0; volatile uint8_t *buff; volatile uint8_t buffer_ready; volatile uint8_t dma_stopped; FIL upload_file; void mks_wifi_sd_ls(void){ res = f_opendir((DIR*)&dir, "0:"); /* Open the directory */ if (res == FR_OK) { for (;;) { res = f_readdir((DIR*)&dir,(FILINFO*) &fno); /* Read a directory item */ if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ DEBUG("%s\n", fno.fname); } }else{ ERROR("Opendir error %d",res); } f_closedir((DIR*)&dir); } uint8_t mks_wifi_sd_init(void){ card.release(); DEBUG("Card release"); res = f_mount((FATFS *)&FATFS_Obj, "0", 1); DEBUG("SD init result:%d",res); return (uint8_t)res; } void mks_wifi_sd_deinit(void){ DEBUG("Unmount SD"); f_mount(0, "", 1); DEBUG("Marlin mount"); card.mount(); card.mount(); }; void sd_delete_file(char *filename){ mks_wifi_sd_init(); DEBUG("Remove %s",filename); f_unlink(filename); mks_wifi_sd_deinit(); } /* Ищет файл filename и возвращает 8.3 имя в dosfilename Возвращаемое значение 1 если нашлось, 0 если нет */ uint8_t get_dos_filename(char *filename, char* dosfilename){ uint8_t ret_val=0; mks_wifi_sd_init(); res = f_opendir((DIR*)&dir, "0:"); /* Open the directory */ if (res == FR_OK) { for (;;) { res = f_readdir((DIR*)&dir, (FILINFO*)&fno); /* Read a directory item */ if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ if(!strcmp((char *)fno.fname,filename)){ DEBUG("Found %s %s\n", fno.fname, fno.altname); strncpy(dosfilename,(char *)fno.altname,13); ret_val = 1; } } }else{ ERROR("Opendir error %d",res); } f_closedir((DIR*)&dir); mks_wifi_sd_deinit(); return ret_val; } void mks_wifi_start_file_upload(ESP_PROTOC_FRAME *packet){ char str[100]; UINT bytes_writen=0; uint32_t file_size, file_inc_size, file_size_writen; uint16_t in_sector; uint16_t last_sector; volatile uint32_t dma_timeout; uint16_t data_size; int16_t save_bed,save_e0; uint32_t data_to_write=0; uint8_t *data_packet; char file_name[100]; save_bed=thermalManager.degTargetBed(); save_e0=thermalManager.degTargetHotend(0); DEBUG("Saved target temp E0 %d Bed %d",save_e0,save_bed); thermalManager.setTargetBed(0); thermalManager.setTargetHotend(0,0); thermalManager.manage_heater(); OUT_WRITE(FAN1_PIN,HIGH); //Установить имя файла. Смещение на 3 байта, чтобы добавить путь к диску file_name[0]='0'; file_name[1]=':'; file_name[2]='/'; memcpy((uint8_t *)file_name+3,(uint8_t *)&packet->data[5],(packet->dataLen - 5)); file_name[packet->dataLen - 5 + 3] = 0; file_size=(packet->data[4] << 24) | (packet->data[3] << 16) | (packet->data[2] << 8) | packet->data[1]; DEBUG("Start file %s size %d",file_name,file_size); //Отмонтировать SD от Marlin, Монтировать FATFs if(mks_wifi_sd_init()){ ERROR("Error SD mount"); ui.set_status((const char *)"Error SD mount",true); ui.update(); mks_wifi_sd_deinit(); return; } DEBUG("Open file"); //открыть файл для записи res=f_open((FIL *)&upload_file,file_name,FA_CREATE_ALWAYS | FA_WRITE); if(res){ ERROR("File open error %d",res); ui.set_status((const char *)"File open error",true); ui.update(); mks_wifi_sd_deinit(); return; } #if ENABLED(TFT_480x320) || ENABLED(TFT_480x320_SPI) #ifdef SHOW_PROGRESS mks_update_status(file_name+3,0,file_size); #else mks_upload_screen(); #endif #endif dma_buff_index=0; file_inc_size=0; //Счетчик принятых данных, для записи в файл file_size_writen = 0; //Счетчик записанных в файл данных file_data_size = 0; dma_timeout = DMA_TIMEOUT; //Тайм-аут, на случай если передача зависла. last_sector = 0; buffer_ready = 0; #ifdef STM32F1 //Отключение тактирования не используемых блоков RCC->APB1ENR &= ~(RCC_APB1ENR_TIM5EN|RCC_APB1ENR_TIM4EN); RCC->APB1ENR &= ~(RCC_APB1ENR_SPI2EN|RCC_APB1ENR_USART3EN); RCC->APB2ENR &= ~RCC_APB2ENR_TIM1EN; RCC->AHBENR &= ~(RCC_AHBENR_FSMCEN); //Максимальная частота в режиме out GPIOC->CRL |= GPIO_CRL_MODE7; GPIOC->CRL &= ~GPIO_CRL_CNF7; DMA1_Channel5->CCR = DMA_CONF; DMA1_Channel5->CPAR = (uint32_t)&USART1->DR; DMA1_Channel5->CMAR = (uint32_t)dma_buff[dma_buff_index]; DMA1_Channel5->CNDTR = ESP_PACKET_SIZE; DMA1->IFCR = DMA_IFCR_CGIF5|DMA_IFCR_CTEIF5|DMA_IFCR_CHTIF5|DMA_IFCR_CTCIF5; DMA1_Channel5->CCR = DMA_CONF|DMA_CCR_EN; NVIC_EnableIRQ(DMA1_Channel5_IRQn); USART1->CR1 = USART_CR1_UE; USART1->CR1 = USART_CR1_TE | USART_CR1_UE; USART1->BRR = 0x25; USART1->CR2 = 0; USART1->CR3 = USART_CR3_DMAR; USART1->SR = 0; USART1->CR1 |= USART_CR1_RE; #endif #ifdef STM32F4 DMA2_Stream5->CR = 0; DMA2->HIFCR=DMA_S5_CLEAR; DMA2_Stream5->PAR = (uint32_t)&USART1->DR; DMA2_Stream5->M0AR = (uint32_t)dma_buff[dma_buff_index]; DMA2_Stream5->NDTR = ESP_PACKET_SIZE; DMA2_Stream5->CR = DMA_CONF|DMA_SxCR_EN; NVIC_EnableIRQ(DMA2_Stream5_IRQn); USART1->CR1 = USART_CR1_UE; USART1->CR1 = USART_CR1_TE | USART_CR1_UE; USART1->BRR = (uint32_t)(84000000+1958400/2)/1958400; USART1->CR2 = 0; USART1->CR3 = USART_CR3_DMAR; USART1->SR = 0; USART1->CR1 |= USART_CR1_RE; #endif safe_delay(200); (void)USART1->DR; TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); DEBUG("DMA1 buff: %0X", dma_buff[0]); DEBUG("DMA2 buff: %0X", dma_buff[1]); DEBUG("File buff: %0X size %d (%0X)", file_buff, FILE_BUFFER_SIZE, FILE_BUFFER_SIZE); //На время передачи отключение systick SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; data_packet = 0; while(--dma_timeout > 0){ if(buffer_ready > 0){ if(data_packet != buff){ data_packet = (uint8_t *)buff; }else{ DEBUG("Change"); if(dma_buff_index){ data_packet = (uint8_t *)dma_buff[1]; }else{ data_packet = (uint8_t *)dma_buff[0]; } } if(*data_packet != ESP_PROTOC_HEAD){ ERROR("Wrong packet head"); break; } in_sector = (*(data_packet+5) << 8) | *(data_packet+4); if((in_sector - last_sector) > 1){ ERROR("IN Sec: %d Prev sec: %d",in_sector,last_sector); dma_stopped = 2; break; }else{ last_sector=in_sector; } data_size = (*(data_packet+3) << 8) | *(data_packet+2); data_size -= 4; //4 байта с номером сегмента и флагами memcpy((uint8_t *)file_buff+file_data_size,(uint8_t*)(data_packet+8),data_size); file_data_size+=data_size; //Если буфер полон и писать некуда, запись в файл if((file_data_size + ESP_PACKET_SIZE) > FILE_BUFFER_SIZE){ data_to_write = file_data_size / 512; data_to_write = data_to_write * 512; file_inc_size += data_to_write; DEBUG("%d [%d]Save %d bytes (%d of %d) ",buffer_ready,in_sector,data_to_write,file_inc_size,file_size); res=f_write((FIL *)&upload_file,(uint8_t*)file_buff,data_to_write,&bytes_writen); if(res){ ERROR("Write err %d",res); break; } file_size_writen+=bytes_writen; file_data_size -= data_to_write; memcpy((uint8_t *)file_buff,(uint8_t *)(file_buff+data_to_write),file_data_size); } if(in_sector == 0){ if(data_size == file_size){ DEBUG("1-packet file"); *(data_packet+7) = 0x80; } } if(*(data_packet+7) == 0x80){ //Последний пакет с данными WRITE(MKS_WIFI_IO4, HIGH); //Остановить передачу от ESP DEBUG("Last packet"); if(file_data_size != 0 ){ file_inc_size += file_data_size; DEBUG("Save last %d bytes from buffer (%d of %d) ",file_data_size,file_inc_size,file_size); res=f_write((FIL *)&upload_file,(uint8_t*)file_buff,file_data_size,&bytes_writen); if(res){ ERROR("Write err %d",res); break; } file_size_writen+=bytes_writen; } break; } if(buffer_ready > 0){ --buffer_ready; }; if((buffer_ready == 0) && (dma_stopped == 1)){ DEBUG("Start"); (void)USART1->SR; GPIOC->BSRR = GPIO_BSRR_BR7; dma_stopped=0; } if(dma_stopped == 2){ break; } dma_timeout = DMA_TIMEOUT; }else{ TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); } } #ifdef STM32F1 //Включение обратно переферии SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; RCC->APB1ENR |= (RCC_APB1ENR_TIM5EN|RCC_APB1ENR_TIM4EN); RCC->APB1ENR |= (RCC_APB1ENR_SPI2EN|RCC_APB1ENR_USART3EN); RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; RCC->AHBENR |= (RCC_AHBENR_FSMCEN); #endif #ifdef STM32F4 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; #endif if((dma_timeout == 0) || (dma_stopped == 2)) { #ifdef STM32F1 DEBUG("DMA timeout, NDTR: %d",DMA1_Channel5->CNDTR); #endif #ifdef STM32F4 DEBUG("DMA timeout, NDTR: %d",DMA2_Stream5->NDTR); #endif DEBUG("SR: %0X",USART1->SR); //Restart ESP8266 WRITE(MKS_WIFI_IO_RST, LOW); delay(200); WRITE(MKS_WIFI_IO_RST, HIGH); } #ifdef STM32F1 //Выключить DMA DMA1->IFCR = DMA_IFCR_CGIF5|DMA_IFCR_CTEIF5|DMA_IFCR_CHTIF5|DMA_IFCR_CTCIF5; DMA1_Channel5->CCR = 0; #endif #ifdef STM32F4 //Выключить DMA DMA2->HIFCR=DMA_S5_CLEAR; DMA2_Stream5->CR = 0; #endif MYSERIAL2.begin(BAUDRATE_2); WRITE(MKS_WIFI_IO4, LOW); //Включить передачу от ESP TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); f_close((FIL *)&upload_file); DEBUG("File closed"); if( (file_size == file_inc_size) && (file_size == file_size_writen) ){ TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); mks_wifi_sd_deinit(); DEBUG("Remount SD"); #if ENABLED(TFT_480x320) || ENABLED(TFT_480x320_SPI) mks_end_transmit(); #endif ui.set_status((const char *)"Upload done",true); DEBUG("Upload ok"); BUZZ(1000,260); if(!strcmp(file_name,"0:/Robin_Nano35.bin")){ TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); DEBUG("Firmware found, reboot"); safe_delay(1000); NVIC_SystemReset(); } }else{ TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); #if ENABLED(TFT_480x320) || ENABLED(TFT_480x320_SPI) mks_end_transmit(); #endif 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); //Установить имя файла. 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; DEBUG("Rename file %s",file_name); f_rename(file_name,"file_failed.gcode"); TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); mks_wifi_sd_deinit(); DEBUG("Remount SD"); BUZZ(436,392); BUZZ(109,0); BUZZ(436,392); BUZZ(109,0); BUZZ(436,392); } TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); thermalManager.setTargetBed(save_bed); thermalManager.setTargetHotend(save_e0,0); DEBUG("Restore thermal settings E0:%d Bed:%d",save_bed,save_e0); } #ifdef STM32F1 extern "C" void DMA1_Channel5_IRQHandler(void){ if(DMA1->ISR & DMA_ISR_TEIF5){ DEBUG("DMA Error"); dma_stopped = 2; DMA1->IFCR = DMA_CLEAR; return; } if(buffer_ready > 0){ GPIOC->BSRR = GPIO_BSRR_BS7; //остановить передачу от esp dma_stopped=1; }; DMA1->IFCR = DMA_CLEAR; //Указатель на полученный буфер buff=dma_buff[dma_buff_index]; //переключить индекс dma_buff_index = (dma_buff_index) ? 0 : 1; DMA1_Channel5->CCR = DMA_CONF; DMA1_Channel5->CMAR = (uint32_t)dma_buff[dma_buff_index]; DMA1_Channel5->CNDTR = ESP_PACKET_SIZE; DMA1_Channel5->CCR = DMA_CONF|DMA_CCR_EN; ++buffer_ready; } #endif #ifdef STM32F4 extern "C" void DMA2_Stream5_IRQHandler(void){ if(DMA2->HISR & DMA_HISR_TEIF5){ DEBUG("DMA Error"); dma_stopped = 2; DMA2->HIFCR=DMA_S5_CLEAR; return; } if(buffer_ready > 0){ GPIOC->BSRR = GPIO_BSRR_BS7; //остановить передачу от esp dma_stopped=1; }; DMA2->HIFCR=DMA_S5_CLEAR; //Указатель на полученный буфер buff=dma_buff[dma_buff_index]; //переключить индекс dma_buff_index = (dma_buff_index) ? 0 : 1; DMA2_Stream5->CR = DMA_CONF; DMA2_Stream5->M0AR = (uint32_t)dma_buff[dma_buff_index]; DMA2_Stream5->NDTR = ESP_PACKET_SIZE; DMA2_Stream5->CR = DMA_CONF|DMA_SxCR_EN; ++buffer_ready; } #endif #endif