/********************************************************************************************************* ** Function name : flash_write_sector ** Descriptions : Write flash memory , just in one page memory ** Input parameters : WAddr -- the start address to write ** Output parameters : buf -- the buffer to write the data ** RLength -- the length of the data to write ** Returned value : The operation result. 1 -- sucess, 0 -- false *********************************************************************************************************/ uint8_t flash_write_sector (uint32_t WAddr, uint8_t *buf, uint32_t WLength) { uint32_t i; if (WLength == 0) { return 0; } flash_write_enable(); /* Write enable */ SPI_FLASH_CS_LOW(); /* P0.2--0,CS = 0 选中SPI Flash */ Send_Byte(0x02); Send_Byte((WAddr & 0xFF0000) >> 16); Send_Byte((WAddr & 0x00FF00) >> 8); Send_Byte((WAddr & 0x0000FF)); for (i=0; i<WLength; i++) { Send_Byte(buf[i]); } SPI_FLASH_CS_HIGH(); /* P0.2--1,CS = 1 释放SPI Flash */ while (flash_read_status() & 0x01 != 0x00); return 1; }
/********************************************************************************************************* ** Function name : flash_read_data ** Descriptions : Read flash memory ** Input parameters : RAddr -- the start address to read ** Output parameters : buf -- the buffer to receive the read data ** RLength -- the length of the data to read ** Returned value : The operation result. 1 -- sucess, 0 -- false *********************************************************************************************************/ uint8_t flash_read_data (uint32_t RAddr, uint8_t *buf, uint32_t RLength) { uint8_t Temp; uint32_t i; if (RLength == 0) { return 0; } /* * Check the state register. If it's busy , wait until it's free */ while(1) { Temp = flash_read_status( ); Temp &= 0x01; if(Temp == 0x00) break; for(i=0; i<10; i++); } SPI_FLASH_CS_LOW(); /* P0.2--0,CS = 0 选中SPI Flash */ Send_Byte(0x03); Send_Byte((RAddr & 0xFF0000) >> 16); Send_Byte((RAddr & 0x00FF00) >> 8); Send_Byte((RAddr & 0x0000FF)); for (i=0; i<RLength; i++) { buf[i] = Send_Byte(0xff); } SPI_FLASH_CS_HIGH(); /* P0.2--1,CS = 1 释放SPI Flash */ return 1; }
/********************************************************************************************************* ** Function name : W25X10_ReadStatus ** Descriptions : Read the state register in the flash memory ** Input parameters : none ** Output parameters : The value of the state register ** Returned value : none *********************************************************************************************************/ uint8_t flash_read_status ( void ) { uint8_t status; SPI_FLASH_CS_LOW(); /* 选中SPI Flash */ Send_Byte(0x05); status = Send_Byte(0xff); SPI_FLASH_CS_HIGH(); /* P0.2--1,CS = 1 释放SPI Flash */ return status; /* Return Reg 1's Content */ }
/** * @brief Transmit a file using the ymodem protocol * @param buf: Address of the first byte * @retval The size of the file */ uint8_t Ymodem_Transmit (uint8_t *buf, const uint8_t* sendFileName, uint32_t sizeFile) { uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD]; uint8_t filename[FILE_NAME_LENGTH]; uint8_t *buf_ptr, tempCheckSum; uint16_t tempCRC; uint16_t blkNumber; uint8_t receivedC[2], CRC16_F = 0, i; uint32_t errors, ackReceived, size = 0, pktSize; errors = 0; ackReceived = 0; for (i = 0; i < (FILE_NAME_LENGTH - 1); i++) { filename[i] = sendFileName[i]; } CRC16_F = 1; /* Prepare first block */ Ymodem_PrepareIntialPacket(&packet_data[0], filename, &sizeFile); do { /* Send Packet */ Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_HEADER); /* Send CRC or Check Sum based on CRC16_F */ if (CRC16_F) { tempCRC = Cal_CRC16(&packet_data[3], PACKET_SIZE); Send_Byte(tempCRC >> 8); Send_Byte(tempCRC & 0xFF); } else { tempCheckSum = CalChecksum (&packet_data[3], PACKET_SIZE); Send_Byte(tempCheckSum); } /* Wait for Ack and 'C' */ if (Receive_Byte(&receivedC[0], 10000) == 0) { if (receivedC[0] == ACK) { /* Packet transferred correctly */ ackReceived = 1; } } else { errors++; } } while (!ackReceived && (errors < 0x0A));
/********************************************************************************************************* ** Terry: The function must be called once before progremme the SPI Flash ** ** Function name : flash_write_status ** Descriptions : Write the write state register in the flash memory ** Input parameters : none ** Output parameters : The value of the write state register ** Returned value : none *********************************************************************************************************/ void flash_write_status ( uint_16 Status ) { flash_write_enable(); Status|=0x01<<1; //Set SEL to 1 SPI_FLASH_CS_LOW(); /* P0.2--0,CS = 0 选中SPI Flash */ Send_Byte(0x01); Send_Byte((Status & 0x0000FF)); Send_Byte((Status & 0x00FF00) >> 8); SPI_FLASH_CS_HIGH(); /* P0.2--1,CS = 1 释放SPI Flash */ return; }
/******************************************************************************* * @函数名称 Ymodem_Transmit * @函数说明 通过ymodem协议传输一个文件 * @输入参数 buf :数据地址指针 sendFileName :文件名 sizeFile:文件长度 * @输出参数 无 * @返回参数 是否成功 0:成功 *******************************************************************************/ uint8_t Ymodem_Transmit (uint8_t *buf, const uint8_t* sendFileName, uint32_t sizeFile) { uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD]; uint8_t FileName[FILE_NAME_LENGTH]; uint8_t *buf_ptr, tempCheckSum ; uint16_t tempCRC, blkNumber; uint8_t receivedC[2], CRC16_F = 0, i; uint32_t errors, ackReceived, size = 0, pktSize; errors = 0; ackReceived = 0; for (i = 0; i < (FILE_NAME_LENGTH - 1); i++) { FileName[i] = sendFileName[i]; } CRC16_F = 1; //准备第一个数据包 Ymodem_PrepareIntialPacket(&packet_data[0], FileName, &sizeFile); do { //发送数据包 Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_HEADER); //发送CRC校验 if (CRC16_F) { tempCRC = Cal_CRC16(&packet_data[3], PACKET_SIZE); Send_Byte(tempCRC >> 8); Send_Byte(tempCRC & 0xFF); } else { tempCheckSum = CalChecksum (&packet_data[3], PACKET_SIZE); Send_Byte(tempCheckSum); } //等待响应 if (Receive_Byte(&receivedC[0], 10000) == 0) { if (receivedC[0] == ACK) { //数据包正确传输 ackReceived = 1; } } else { errors++; } } while (!ackReceived && (errors < 0x0A));
/********************************************************************************************************* ** Function name : flash_sector_erase ** Descriptions : Sector erase ** Input parameters : addr -- sector address ** Output parameters : None ** Returned value : The operation result. 1 -- sucess, 0 -- false *********************************************************************************************************/ uint8_t flash_sector_erase (uint32_t addr) { flash_write_enable(); /* Write enable */ SPI_FLASH_CS_LOW(); /* P0.2--0,CS = 0 选中SPI Flash */ Send_Byte(0x20); Send_Byte((addr & 0xFF0000) >> 16); Send_Byte((addr & 0x00FF00) >> 8); Send_Byte(addr & 0x0000FF); SPI_FLASH_CS_HIGH(); /* P0.2--1,CS = 1 释放SPI Flash */ while (flash_read_status() & 0x01 != 0x00); /* Wait for the flash free */ return 1; }
NTSTATUS NTAPI HwSenseInterruptStatus(PCONTROLLER_INFO ControllerInfo) /* * FUNCTION: Send a sense interrupt status command to a controller * ARGUMENTS: * ControllerInfo: controller to queue the command to * RETURNS: * STATUS_SUCCESS if the command is queued successfully * STATUS_UNSUCCESSFUL if not */ { UCHAR Buffer[2]; int i; PAGED_CODE(); if(Send_Byte(ControllerInfo, COMMAND_SENSE_INTERRUPT_STATUS) != STATUS_SUCCESS) { WARN_(FLOPPY, "HwSenseInterruptStatus: failed to write controller\n"); return STATUS_UNSUCCESSFUL; } for(i = 0; i < 2; i++) { if(Get_Byte(ControllerInfo, &Buffer[i]) != STATUS_SUCCESS) { WARN_(FLOPPY, "HwSenseInterruptStatus: failed to read controller\n"); return STATUS_UNSUCCESSFUL; } } INFO_(FLOPPY, "HwSenseInterruptStatus returned 0x%x 0x%x\n", Buffer[0], Buffer[1]); return STATUS_SUCCESS; }
NTSTATUS NTAPI HwGetVersion(PCONTROLLER_INFO ControllerInfo) /* * FUNCTION: Gets the version of the controller * ARGUMENTS: * ControllerInfo: controller to target with the request * ConfigValue: Configuration value to send to the drive (see header) * RETURNS: * Version number returned by the command, or * 0 on failure * NOTE: * - This command doesn't interrupt, so we go right to reading after * we issue the command */ { UCHAR Buffer; PAGED_CODE(); if(Send_Byte(ControllerInfo, COMMAND_VERSION) != STATUS_SUCCESS) { WARN_(FLOPPY, "HwGetVersion: unable to write fifo\n"); return STATUS_UNSUCCESSFUL; } if(Get_Byte(ControllerInfo, &Buffer) != STATUS_SUCCESS) { WARN_(FLOPPY, "HwGetVersion: unable to write fifo\n"); return STATUS_UNSUCCESSFUL; } INFO_(FLOPPY, "HwGetVersion returning version 0x%x\n", Buffer); return Buffer; }
NTSTATUS NTAPI HwRecalibrate(PDRIVE_INFO DriveInfo) /* * FUNCTION: Start a recalibration of a drive * ARGUMENTS: * DriveInfo: Drive to recalibrate * RETURNS: * STATUS_SUCCESS if the command was successfully queued to the controller * STATUS_UNSUCCESSFUL otherwise * NOTES: * - Generates an interrupt */ { PCONTROLLER_INFO ControllerInfo = DriveInfo->ControllerInfo; UCHAR Unit = DriveInfo->UnitNumber; UCHAR Buffer[2]; int i; TRACE_(FLOPPY, "HwRecalibrate called\n"); PAGED_CODE(); Buffer[0] = COMMAND_RECALIBRATE; Buffer[1] = Unit; for(i = 0; i < 2; i++) if(Send_Byte(ControllerInfo, Buffer[i]) != STATUS_SUCCESS) { WARN_(FLOPPY, "HwRecalibrate: unable to write FIFO\n"); return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; }
NTSTATUS NTAPI HwReadId(PDRIVE_INFO DriveInfo, UCHAR Head) /* * FUNCTION: Issue a read id command to the drive * ARGUMENTS: * DriveInfo: Drive to read id from * Head: Head to read the ID from * RETURNS: * STATUS_SUCCESS if the command is queued * STATUS_UNSUCCESSFUL otherwise * NOTES: * - Generates an interrupt */ { UCHAR Buffer[2]; int i; TRACE_(FLOPPY, "HwReadId called\n"); PAGED_CODE(); Buffer[0] = COMMAND_READ_ID | READ_ID_MFM; Buffer[1] = (Head << COMMAND_HEAD_NUMBER_SHIFT) | DriveInfo->UnitNumber; for(i = 0; i < 2; i++) if(Send_Byte(DriveInfo->ControllerInfo, Buffer[i]) != STATUS_SUCCESS) { WARN_(FLOPPY, "HwReadId: unable to send bytes to fifo\n"); return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; }
void super_dead_mode(){ uint16_t counter = 0; while(!config.health){ handle_music(); // Manage base station comms uint8_t b; if(CHECK_CHAR()){ b=AVAIL_CHAR(); if(b == 0x10) { control_transfer(); } } counter++; delay_1_ms(); if(counter > config.death_period){ counter = 0; led_off(); Send_Byte(config.id); play_song((uint16_t*)dead_song,sizeof(dead_song)/sizeof(uint16_t),10000,0); } if(counter == config.death_period-50){ red_led_on(); } } }
NTSTATUS NTAPI HwSenseDriveStatus(PDRIVE_INFO DriveInfo) /* * FUNCTION: Start a sense status command * ARGUMENTS: * DriveInfo: Drive to inquire about * RETURNS: * STATUS_SUCCESS if the command is successfully queued to the controller * STATUS_UNSUCCESSFUL if not * NOTES: * - Generates an interrupt * - hard-wired to head 0 */ { UCHAR Buffer[2]; int i; PAGED_CODE(); TRACE_(FLOPPY, "HwSenseDriveStatus called\n"); Buffer[0] = COMMAND_SENSE_DRIVE_STATUS; Buffer[1] = DriveInfo->UnitNumber; /* hard-wired to head 0 for now */ for(i = 0; i < 2; i++) if(Send_Byte(DriveInfo->ControllerInfo, Buffer[i]) != STATUS_SUCCESS) { WARN_(FLOPPY, "HwSenseDriveStatus: failed to write FIFO\n"); return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; }
/** * @brief Transmit a data packet using the ymodem protocol * @param data * @param length * @retval None */ void Ymodem_SendPacket(uint8_t *data, uint16_t length) { uint16_t i; i = 0; while (i < length) { Send_Byte(data[i]); i++; } }
uint8_t flash_write_word (uint32_t WAddr, uint16_t *buf, uint32_t WLength) { uint32_t i; if (WLength == 0) { return 0; } if(WLength%2!=0) { return 0; } WLength/=2; EBSY(); WREN(); SPI_FLASH_CS_LOW(); Send_Byte(SPI_FLASH_CMD_SST_AAI_WORD_PROGRAM); /* send AAI command */ Send_Byte(((WAddr & 0xFFFFFF) >> 16)); /* send 3 address bytes */ Send_Byte(((WAddr & 0xFFFF) >> 8)); Send_Byte(WAddr & 0xFF); for (i=0; i<WLength; i++) { APP_TRACE("%d ",i); Send_Byte(buf[i] & 0xFF); Send_Byte(((buf[i] & 0xFFFF) >> 8)); SPI_FLASH_CS_HIGH(); CheckBusy(); if(i<WLength-1) { SPI_FLASH_CS_LOW(); Send_Byte(SPI_FLASH_CMD_SST_AAI_WORD_PROGRAM); /* send AAI command */ } } WRDI(); DBSY(); while (flash_read_status() & 0x01 != 0x00); return 1; }
/********************************************************************************************************* ** Function name : flash_all_erase ** Descriptions : Erase the whole flash ** Input parameters : None ** Output parameters : None ** Returned value : The operation result. 1 -- sucess, 0 -- false *********************************************************************************************************/ uint8_t flash_whole_erase( void ) { flash_write_enable(); /* Write enable */ SPI_FLASH_CS_LOW(); /* P0.2--0,CS = 0 选中SPI Flash */ Send_Byte(0xC7); SPI_FLASH_CS_HIGH(); /* P0.2--1,CS = 1 释放SPI Flash */ while (flash_read_status() & 0x01 != 0x00); /* Wait for the flash free */ return 1; }
//----------------------------------------------------------- static void Ymodem_SendPacket(uint8_t *data, uint16_t length) { uint16_t i; luaWdgReload(); i = 0; while (i < length) { Send_Byte(data[i]); i++; } }
/********************************************************************************************************* ** Function name : flash_write_enable ** Descriptions : Enable the flash memory to write ** Input parameters : none ** Output parameters : none ** Returned value : none *********************************************************************************************************/ static void flash_write_enable (void) { while (flash_read_status() & 0x01 != 0x00); /* Wait for flash free */ SPI_FLASH_CS_LOW(); /* P0.2--0,CS = 0 选中SPI Flash */ Send_Byte(0x06); SPI_FLASH_CS_HIGH(); /* P0.2--1,CS = 1 释放SPI Flash */ while (flash_read_status() & 0x03 != 0x02); /* Wait for operation complete */ }
NTSTATUS NTAPI HwFormatTrack(PCONTROLLER_INFO ControllerInfo, UCHAR Unit, UCHAR Head, UCHAR BytesPerSector, UCHAR SectorsPerTrack, UCHAR Gap3Length, UCHAR FillerPattern) /* * FUNCTION: Format a track * ARGUMENTS: * ControllerInfo: controller to target with the request * Unit: drive to format on * Head: head to format on * BytesPerSector: constant from hardware.h to select density * SectorsPerTrack: sectors per track * Gap3Length: gap length to use during format * FillerPattern: pattern to write into the data portion of sectors * RETURNS: * STATUS_SUCCESS if the command is successfully queued * STATUS_UNSUCCESSFUL otherwise */ { UCHAR Buffer[6]; int i; TRACE_(FLOPPY, "HwFormatTrack called\n"); PAGED_CODE(); Buffer[0] = COMMAND_FORMAT_TRACK; Buffer[1] = (Head << COMMAND_HEAD_NUMBER_SHIFT) | Unit; Buffer[2] = BytesPerSector; Buffer[3] = SectorsPerTrack; Buffer[4] = Gap3Length; Buffer[5] = FillerPattern; for(i = 0; i < 6; i++) if(Send_Byte(ControllerInfo, Buffer[i]) != STATUS_SUCCESS) { WARN_(FLOPPY, "HwFormatTrack: unable to send bytes to floppy\n"); return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; }
uint8_t handle_fire(){ static uint16_t timer = 0; // for holdoff static uint16_t counter = 0; // for power uint16_t a; a=ADC_read(); if (a > config.fire_cheating){ cheat(); } if (a > config.fire_threshold && a < config.fire_cheating) { while(!my_random_number){ my_random_number = TMR0; } if(timer < config.fire_holdoff) { timer ++; } else { if(!config.power || counter <= config.power) { if(!counter) { green_led_on(); play_song((uint16_t*)fire_song,sizeof(fire_song)/sizeof(uint16_t),3000,!(config.power)); } Send_Byte(config.id); counter++; } else { led_off(); } } } else { led_off(); if(!config.power && counter) stop_song(); timer = 0; counter = 0; return 0; } return 1; }
NTSTATUS NTAPI HwSpecify(PCONTROLLER_INFO ControllerInfo, UCHAR HeadLoadTime, UCHAR HeadUnloadTime, UCHAR StepRateTime, BOOLEAN NonDma) /* * FUNCTION: Set up timing and DMA mode for the controller * ARGUMENTS: * ControllerInfo: Controller to set up * HeadLoadTime: Head load time (see data sheet for details) * HeadUnloadTime: Head unload time * StepRateTime: Step rate time * NonDma: TRUE to disable DMA mode * RETURNS: * STATUS_SUCCESS if the controller is successfully programmed * STATUS_UNSUCCESSFUL if not * NOTES: * - Does not interrupt * * TODO: Figure out timings */ { UCHAR Buffer[3]; int i; Buffer[0] = COMMAND_SPECIFY; /* Buffer[1] = (StepRateTime << 4) + HeadUnloadTime; Buffer[2] = (HeadLoadTime << 1) + (NonDma ? 1 : 0); */ Buffer[1] = 0xdf; Buffer[2] = 0x2; //INFO_(FLOPPY, "HwSpecify: sending 0x%x 0x%x 0x%x to FIFO\n", Buffer[0], Buffer[1], Buffer[2]); WARN_(FLOPPY, "HWSPECIFY: FIXME - sending 0x3 0xd1 0x2 to FIFO\n"); for(i = 0; i < 3; i++) if(Send_Byte(ControllerInfo, Buffer[i]) != STATUS_SUCCESS) { WARN_(FLOPPY, "HwSpecify: unable to write to controller\n"); return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; }
NTSTATUS NTAPI HwConfigure(PCONTROLLER_INFO ControllerInfo, BOOLEAN EIS, BOOLEAN EFIFO, BOOLEAN POLL, UCHAR FIFOTHR, UCHAR PRETRK) /* * FUNCTION: Sends configuration to the drive * ARGUMENTS: * ControllerInfo: controller to target with the request * EIS: Enable implied seek * EFIFO: Enable advanced fifo * POLL: Enable polling * FIFOTHR: fifo threshold * PRETRK: precomp (see intel datasheet) * RETURNS: * STATUS_SUCCESS if the command is successfully sent * STATUS_UNSUCCESSFUL otherwise * NOTES: * - No interrupt */ { UCHAR Buffer[4]; int i; TRACE_(FLOPPY, "HwConfigure called\n"); PAGED_CODE(); Buffer[0] = COMMAND_CONFIGURE; Buffer[1] = 0; Buffer[2] = (EIS * CONFIGURE_EIS) + (EFIFO * CONFIGURE_EFIFO) + (POLL * CONFIGURE_POLL) + (FIFOTHR); Buffer[3] = PRETRK; for(i = 0; i < 4; i++) if(Send_Byte(ControllerInfo, Buffer[i]) != STATUS_SUCCESS) { WARN_(FLOPPY, "HwConfigure: failed to write the fifo\n"); return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; }
NTSTATUS NTAPI HwSeek(PDRIVE_INFO DriveInfo, UCHAR Cylinder) /* * FUNCTION: Seek the heads to a particular cylinder * ARGUMENTS: * DriveInfo: Drive to seek * Cylinder: cylinder to move to * RETURNS: * STATUS_SUCCESS if the command is successfully sent * STATUS_UNSUCCESSFUL otherwise * NOTES: * - Generates an interrupt */ { LARGE_INTEGER Delay; UCHAR Buffer[3]; int i; TRACE_(FLOPPY, "HwSeek called for cyl 0x%x\n", Cylinder); PAGED_CODE(); Buffer[0] = COMMAND_SEEK; Buffer[1] = DriveInfo->UnitNumber; Buffer[2] = Cylinder; for(i = 0; i < 3; i++) if(Send_Byte(DriveInfo->ControllerInfo, Buffer[i]) != STATUS_SUCCESS) { WARN_(FLOPPY, "HwSeek: failed to write fifo\n"); return STATUS_UNSUCCESSFUL; } /* Wait for the head to settle */ Delay.QuadPart = 10 * 1000; Delay.QuadPart *= -1; Delay.QuadPart *= DriveInfo->FloppyDeviceData.HeadSettleTime; KeDelayExecutionThread(KernelMode, FALSE, &Delay); return STATUS_SUCCESS; }
/********************************************************************************************************* ** Function name : flash_read_id ** Descriptions : Get flash IDcode ** Input parameters : none ** Output parameters : Flash IDcode ** Returned value : Flash IDcode *********************************************************************************************************/ uint_16 flash_read_id (void) { uint_16 IDcode=0; SPI_FLASH_CS_LOW(); /* P0.2--0,CS = 0 选中SPI Flash */ Send_Byte(0x90); Send_Byte(0x00); Send_Byte(0x00); Send_Byte(0x00); // IDcode = (Send_Byte(0xff) << 8) | Send_Byte(0xff); IDcode = (Send_Byte(0x55) << 8) | Send_Byte(0x55); SPI_FLASH_CS_HIGH(); /* P0.2--1,CS = 1 释放SPI Flash */ return IDcode; }
//-------------------------------------------------------------------------- static uint8_t Ymodem_Transmit (const char* sendFileName, uint32_t sizeFile) { uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD]; uint8_t filename[SPIFFS_OBJ_NAME_LEN]; uint16_t blkNumber; uint8_t receivedC[1], i, err; uint32_t size = 0; for (i = 0; i < (SPIFFS_OBJ_NAME_LEN - 1); i++) { filename[i] = sendFileName[i]; } while (MicoUartRecv( MICO_UART_1, &receivedC[0], 1, 10 ) == kNoErr) {}; // Wait for response from receiver err = 0; do { luaWdgReload(); Send_Byte(CRC16); } while (Receive_Byte(&receivedC[0], NAK_TIMEOUT) < 0 && err++ < 45); if (err >= 45 || receivedC[0] != CRC16) { send_CA(); return 99; } // === Prepare first block and send it ======================================= /* When the receiving program receives this block and successfully * opened the output file, it shall acknowledge this block with an ACK * character and then proceed with a normal YMODEM file transfer * beginning with a "C" or NAK tranmsitted by the receiver. */ Ymodem_PrepareIntialPacket(&packet_data[0], filename, &sizeFile); do { // Send Packet Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_OVERHEAD); // Wait for Ack err = Ymodem_WaitACK(ACK, 10); if (err == 0 || err == 4) { send_CA(); return 90; // timeout or wrong response } else if (err == 2) return 98; // abort }while (err != 1); // After initial block the receiver sends 'C' after ACK if (Ymodem_WaitACK(CRC16, 10) != 1) { send_CA(); return 90; } // === Send file blocks ====================================================== size = sizeFile; blkNumber = 0x01; // Resend packet if NAK for a count of 10 else end of communication while (size) { // Prepare and send next packet Ymodem_PreparePacket(&packet_data[0], blkNumber, size); do { Ymodem_SendPacket(packet_data, PACKET_1K_SIZE + PACKET_OVERHEAD); // Wait for Ack err = Ymodem_WaitACK(ACK, 10); if (err == 1) { blkNumber++; if (size > PACKET_1K_SIZE) size -= PACKET_1K_SIZE; // Next packet else size = 0; // Last packet sent } else if (err == 0 || err == 4) { send_CA(); return 90; // timeout or wrong response } else if (err == 2) return 98; // abort }while(err != 1); } // === Send EOT ============================================================== Send_Byte(EOT); // Send (EOT) // Wait for Ack do { // Wait for Ack err = Ymodem_WaitACK(ACK, 10); if (err == 3) { // NAK Send_Byte(EOT); // Send (EOT) } else if (err == 0 || err == 4) { send_CA(); return 90; // timeout or wrong response } else if (err == 2) return 98; // abort }while (err != 1); // === Receiver requests next file, prepare and send last packet ============= if (Ymodem_WaitACK(CRC16, 10) != 1) { send_CA(); return 90; } Ymodem_PrepareLastPacket(&packet_data[0]); do { Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_OVERHEAD); // Send Packet // Wait for Ack err = Ymodem_WaitACK(ACK, 10); if (err == 0 || err == 4) { send_CA(); return 90; // timeout or wrong response } else if (err == 2) return 98; // abort }while (err != 1); return 0; // file transmitted successfully }
//--------------------------------------------------------------------------------- static int32_t Ymodem_Receive ( char* FileName, uint32_t maxsize, uint8_t getname ) { uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], file_size[FILE_SIZE_LENGTH], *file_ptr; int32_t i, packet_length, file_len, write_len, session_done, file_done, packets_received, errors, session_begin, size = 0; for (session_done = 0, errors = 0, session_begin = 0; ;) { for (packets_received = 0, file_done = 0; ;) { switch (Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT)) { case 0: switch (packet_length) { /* Abort by sender */ case -1: Send_Byte(ACK); return 0; /* End of transmission */ case 0: Send_Byte(ACK); file_done = 1; break; /* Normal packet */ default: if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff)) { errors ++; if (errors > MAX_ERRORS) { send_CA(); return 0; } Send_Byte(NAK); } else { errors = 0; if (packets_received == 0) { /* Filename packet */ if (packet_data[PACKET_HEADER] != 0) { // Filename packet has valid data if (getname == 0) { for (i = 0, file_ptr = packet_data + PACKET_HEADER; (*file_ptr != 0) && (i < SPIFFS_OBJ_NAME_LEN);) { FileName[i++] = *file_ptr++; } FileName[i++] = '\0'; } for (i = 0, file_ptr = packet_data + PACKET_HEADER; (*file_ptr != 0) && (i < packet_length);) { file_ptr++; } for (i = 0, file_ptr ++; (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH);) { file_size[i++] = *file_ptr++; } file_size[i++] = '\0'; Str2Int(file_size, &size); // Test the size of the file if (size < 1 || size > maxsize) { file_fd = FILE_NOT_OPENED; /* End session */ send_CA(); return -4; } /* *** Open the file *** */ if (FILE_NOT_OPENED != file_fd) { SPIFFS_close(&fs,file_fd); file_fd = FILE_NOT_OPENED; } file_fd = SPIFFS_open(&fs, (char*)FileName, mode2flag("w"), 0); if (file_fd <= FILE_NOT_OPENED) { file_fd = FILE_NOT_OPENED; /* End session */ send_CA(); return -2; } file_len = 0; Send_Byte(ACK); Send_Byte(CRC16); } /* Filename packet is empty, end session */ else { Send_Byte(ACK); file_done = 1; session_done = 1; break; } } /* Data packet */ else { /* Write received data to file */ if (file_len < size) { file_len = file_len + packet_length; if (file_len > size) { write_len = packet_length - (file_len - size); } else { write_len = packet_length; } if (file_fd <= FILE_NOT_OPENED) { file_fd = FILE_NOT_OPENED; // File not opened, End session send_CA(); return -2; } if (SPIFFS_write(&fs,file_fd, (char*)(packet_data + PACKET_HEADER), write_len) < 0) { //failed SPIFFS_close(&fs,file_fd); file_fd = FILE_NOT_OPENED; /* End session */ send_CA(); return -1; } } //success Send_Byte(ACK); } packets_received ++; session_begin = 1; } } break; case 1: send_CA(); return -3; default: if (session_begin >= 0) { errors ++; } if (errors > MAX_ERRORS) { send_CA(); return 0; } Send_Byte(CRC16); break; } if (file_done != 0) { break; } } if (session_done != 0) { break; } } return (int32_t)size; }
//---------------------------- static void send_CA ( void ) { Send_Byte(CA); Send_Byte(CA); mico_thread_msleep(500); luaWdgReload(); }
int32_t Ymodem_Receive(uint8_t *buf) { uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], file_size[FILE_SIZE_LENGTH], *file_ptr, *buf_ptr; int32_t i,j,packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0; /* Initialize FlashDestination variable */ FlashDestination = ApplicationAddress; for(session_done = 0, errors = 0, session_begin = 0; ;) { for(packets_received = 0, file_done = 0, buf_ptr = buf; ;) { switch(Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT)) { case 0: errors = 0; switch (packet_length) { /* Abort by sender */ case - 1: Send_Byte(ACK); return 0; /* End of transmission */ case 0: Send_Byte(ACK); file_done = 1; break; /* Normal packet */ default: if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff))//数据包编号 { Send_Byte(NAK); } else { if(packets_received == 0)/* 第一次传输文件属性 */ { if(packet_data[PACKET_HEADER] != 0)/* Filename packet has valid data */ { for(i = 0, file_ptr = packet_data + PACKET_HEADER; (*file_ptr != 0) && (i < FILE_NAME_LENGTH);) file_name[i++] = *file_ptr++; file_name[i++] = '\0';/*接收文件名结束*/ for(i = 0, file_ptr ++; (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH);) file_size[i++] = *file_ptr++; file_size[i++] = '\0';/*接收文件名大小结束*/ Str2Int(file_size, &size); if(size > (FLASH_SIZE - SYSTEM_BOOTLOADER_LENGTH -1))//代码长度超过空间大小 { Send_Byte(CA); Send_Byte(CA); return -1; } if ((size % PAGE_SIZE) != 0)//根据代码大小分配块 NbrOfPage = (size / PAGE_SIZE) + 1; else NbrOfPage = size / PAGE_SIZE; for (EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_OK); EraseCounter++) { FLASHStatus = FLASH_EraseSector(FlashDestination/PageSize + EraseCounter);//擦除代码所需要块 FLASHStatus = FLASH_OK; } Send_Byte(ACK); Send_Byte(CRC16); } else/* Filename packet is empty, end session */ { Send_Byte(ACK); file_done = 1; session_done = 1; break; } } else/* Data packet */ { memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length); RamSource = (uint32_t)buf; for (j = 0;(j < packet_length) && (FlashDestination < ApplicationAddress + size);j += 4) { /* Program the data received into STM32F10x Flash */ FLASH_WriteWord(FlashDestination, *(uint32_t*)RamSource); if (*(uint32_t*)FlashDestination != *(uint32_t*)RamSource) { /* End session */ Send_Byte(CA); Send_Byte(CA); return -2; } FlashDestination += 4; RamSource += 4; } Send_Byte(ACK); } packets_received ++; session_begin = 1;//错误计数器 } } break; case 1: Send_Byte(CA); Send_Byte(CA); return -3; default: if (session_begin > 0) { errors ++; } if (errors > MAX_ERRORS) { Send_Byte(CA); Send_Byte(CA); return 0; } Send_Byte(CRC16); break; } if (file_done != 0) { break; } } if (session_done != 0) { break; } } return (int32_t)size; }
/** * @brief Receive a file using the ymodem protocol. * @param buf: Address of the first byte. * @retval The size of the file. */ int32_t Ymodem_Receive (uint8_t *buf) { uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], file_size[FILE_SIZE_LENGTH], *file_ptr, *buf_ptr; int32_t i, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0; uint32_t flashdestination, ramsource; /* Initialize flashdestination variable */ flashdestination = APPLICATION_ADDRESS; for (session_done = 0, errors = 0, session_begin = 0; ;) { for (packets_received = 0, file_done = 0, buf_ptr = buf; ;) { switch (Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT)) { case 0: errors = 0; switch (packet_length) { /* Abort by sender */ case - 1: Send_Byte(ACK); return 0; /* End of transmission */ case 0: Send_Byte(ACK); file_done = 1; break; /* Normal packet */ default: if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff)) { Send_Byte(NAK); } else { if (packets_received == 0) { /* Filename packet */ if (packet_data[PACKET_HEADER] != 0) { /* Filename packet has valid data */ for (i = 0, file_ptr = packet_data + PACKET_HEADER; (*file_ptr != 0) && (i < FILE_NAME_LENGTH);) { FileName[i++] = *file_ptr++; } FileName[i++] = '\0'; for (i = 0, file_ptr ++; (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH);) { file_size[i++] = *file_ptr++; } file_size[i++] = '\0'; Str2Int(file_size, &size); /* Test the size of the image to be sent */ /* Image size is greater than Flash size */ if (size > (USER_FLASH_SIZE + 1)) { /* End session */ Send_Byte(CA); Send_Byte(CA); return -1; } /* erase user application area */ FLASH_If_Erase(APPLICATION_ADDRESS); Send_Byte(ACK); Send_Byte(CRC16); } /* Filename packet is empty, end session */ else { Send_Byte(ACK); file_done = 1; session_done = 1; break; } } /* Data packet */ else { memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length); ramsource = (uint32_t)buf; /* Write received data in Flash */ if (FLASH_If_Write(&flashdestination, (uint32_t*) ramsource, (uint16_t) packet_length/4) == 0) { Send_Byte(ACK); } else /* An error occurred while writing to Flash memory */ { /* End session */ Send_Byte(CA); Send_Byte(CA); return -2; } } packets_received ++; session_begin = 1; } } break; case 1: Send_Byte(CA); Send_Byte(CA); return -3; default: if (session_begin > 0) { errors ++; } if (errors > MAX_ERRORS) { Send_Byte(CA); Send_Byte(CA); return 0; } Send_Byte(CRC16); break; } if (file_done != 0) { break; } } if (session_done != 0) { break; } } return (int32_t)size; }
/** * @brief Receive a file using the ymodem protocol * @param buf: Address of the first byte * @retval The size of the file */ int32_t Ymodem_Receive (uint8_t *buf) { uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], file_size[FILE_SIZE_LENGTH], *file_ptr, *buf_ptr; int32_t i, j, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0; /* Initialize FlashDestination variable */ FlashDestination = ApplicationAddress; for (session_done = 0, errors = 0, session_begin = 0; ;) { for (packets_received = 0, file_done = 0, buf_ptr = buf; ;) { switch (Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT)) { case 0: errors = 0; switch (packet_length) { /* Abort by sender */ case - 1: Send_Byte(ACK); return 0; /* End of transmission */ case 0: Send_Byte(ACK); file_done = 1; break; /* Normal packet */ default: if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff)) { Send_Byte(NAK); } else { if (packets_received == 0) { /* Filename packet */ if (packet_data[PACKET_HEADER] != 0) { /* Filename packet has valid data */ for (i = 0, file_ptr = packet_data + PACKET_HEADER; (*file_ptr != 0) && (i < FILE_NAME_LENGTH);) { file_name[i++] = *file_ptr++; } file_name[i++] = '\0'; for (i = 0, file_ptr ++; (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH);) { file_size[i++] = *file_ptr++; } file_size[i++] = '\0'; Str2Int(file_size, &size); /* Test the size of the image to be sent */ /* Image size is greater than Flash size */ if (size > (FLASH_SIZE - 1)) { /* End session */ Send_Byte(CA); Send_Byte(CA); return -1; } /* Erase the needed pages where the user application will be loaded */ /* Define the number of page to be erased */ NbrOfPage = FLASH_PagesMask(size); /* Erase the FLASH pages */ for (EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++) { FLASHStatus = FLASH_ErasePage(FlashDestination + (PageSize * EraseCounter)); } Send_Byte(ACK); Send_Byte(CRC16); } /* Filename packet is empty, end session */ else { Send_Byte(ACK); file_done = 1; session_done = 1; break; } } /* Data packet */ else { memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length); RamSource = (uint32_t)buf; for (j = 0;(j < packet_length) && (FlashDestination < ApplicationAddress + size);j += 4) { /* Program the data received into STM32F10x Flash */ FLASH_ProgramWord(FlashDestination, *(uint32_t*)RamSource); if (*(uint32_t*)FlashDestination != *(uint32_t*)RamSource) { /* End session */ Send_Byte(CA); Send_Byte(CA); return -2; } FlashDestination += 4; RamSource += 4; } Send_Byte(ACK); } packets_received ++; session_begin = 1; } } break; case 1: Send_Byte(CA); Send_Byte(CA); return -3; default: if (session_begin > 0) { errors ++; } if (errors > MAX_ERRORS) { Send_Byte(CA); Send_Byte(CA); return 0; } Send_Byte(CRC16); break; } if (file_done != 0) { break; } } if (session_done != 0) { break; } } return (int32_t)size; }