uint8_t serialPoll(void) { if(UART_STATUS_REG & _BV(UART_RECEIVE_COMPLETE)) { resetTick(); serialFlashing = TRUE; #if defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega1284P__) return(processOptiboot()); #elif defined(__AVR_ATmega2560__) return(processStk500boot()); #endif } return(1); }
/** * Looks for a connection */ uint8_t tftpPoll() { uint8_t response = ACK; // Get the size of the recieved data uint16_t packetSize = netReadWord(REG_S3_RX_RSR0); if(packetSize) { if(!tftpFlashing) resetTick(); tftpFlashing = TRUE; for(;;) { if(!(netReadReg(REG_S3_IR) & IR_RECV)) break; netWriteReg(REG_S3_IR, IR_RECV); //FIXME: is this right after all? smaller delay but //still a delayand it still breaks occasionally _delay_ms(400); } // Process Packet and get TFTP response code #ifdef _DEBUG_TFTP response = processPacket(packetSize); #else response = processPacket(); #endif // Send the response sendResponse(response); } if(response==FINAL_ACK) { netWriteReg(REG_S3_CR, CR_CLOSE); // Complete return(0); } // Tftp continues return(1); }
uint8_t processPacket() { #endif uint8_t buffer[TFTP_PACKET_MAX_SIZE]; uint16_t readPointer; uint16_t writeAddr; // Transfer entire packet to RAM uint8_t* bufPtr = buffer; uint16_t count; #ifdef _DEBUG_TFTP traceln("Tftp: ----"); traceln("Tftp: Starting processing packet of size "); tracenum(packetSize); if(packetSize >= 0x800) traceln("Tftp: Overflow"); // step(); #endif readPointer = netReadWord(REG_S3_RX_RD0); #ifdef _DEBUG_TFTP traceln("Tftp: readPointer at position "); tracenum(readPointer); #endif if(readPointer == 0) readPointer += S3_RX_START; for(count = TFTP_PACKET_MAX_SIZE; count--;) { #ifdef _DEBUG_TFTP if((count == TFTP_PACKET_MAX_SIZE - 1) || (count == 0)) { traceln("Tftp: Reading from position "); tracenum(readPointer); } #endif *bufPtr++ = netReadReg(readPointer++); if(readPointer == S3_RX_END) readPointer = S3_RX_START; } netWriteWord(REG_S3_RX_RD0, readPointer); // Write back new pointer netWriteReg(REG_S3_CR, CR_RECV); while(netReadReg(REG_S3_CR)); #ifdef _DEBUG_TFTP traceln("Tftp: Bytes left to read "); tracenum(netReadWord(REG_S3_RX_RSR0)); #endif #ifdef _DEBUGMORE_TFTP // Dump packet bufPtr = buffer; traceln(""); for(count = TFTP_PACKET_MAX_SIZE / 2; count--;) { uint16_t val = *bufPtr++; val |= (*bufPtr++) << 8; tracenum(val); if((count % 8) == 0 && count != 0) traceln(""); else trace(" "); } #endif #ifdef _DEBUG_TFTP traceln("Tftp: Setting return address"); #endif // Set up return IP address and port uint8_t i; for(i = 0; i < 6; i++) netWriteReg(REG_S3_DIPR0 + i, buffer[i]); // Parse packet uint16_t tftpDataLen = (buffer[6] << 8) + buffer[7]; uint16_t tftpOpcode = (buffer[8] << 8) + buffer[9]; uint16_t tftpBlock = (buffer[10] << 8) + buffer[11]; #ifdef _DEBUG traceln("Tftp: This is block "); tracenum(tftpBlock); trace(" with opcode "); tracenum(tftpOpcode); trace(" and data length "); tracenum(tftpDataLen - (TFTP_OPCODE_SIZE + TFTP_BLOCKNO_SIZE)); #endif uint8_t returnCode = ERROR_UNKNOWN; uint16_t packetLength; switch(tftpOpcode) { case TFTP_OPCODE_RRQ: // Read request #ifdef _DEBUG_TFTP traceln("Tftp: Read request"); #endif break; case TFTP_OPCODE_WRQ: // Write request #ifdef _VERBOSE traceln("Tftp: Write request"); #endif // Flagging image as invalid since the flashing process has started eeprom_write_byte(EEPROM_IMG_STAT, EEPROM_IMG_BAD_VALUE); netWriteReg(REG_S3_CR, CR_RECV); netWriteReg(REG_S3_CR, CR_CLOSE); do { netWriteReg(REG_S3_MR, MR_UDP); netWriteReg(REG_S3_CR, CR_OPEN); #ifdef _TFTP_RANDOM_PORT netWriteWord(REG_S3_PORT0, (buffer[4] << 8) | ~buffer[5]); // Generate a 'random' TID (RFC1350) #else netWriteWord(REG_S3_PORT0, tftpPort); #endif if(netReadReg(REG_S3_SR) != SOCK_UDP) netWriteReg(REG_S3_CR, CR_CLOSE); } while(netReadReg(REG_S3_SR) != SOCK_UDP); #ifdef _DEBUG_TFTP traceln("Tftp: Changed to port "); #ifdef _TFTP_RANDOM_PORT tracenum((buffer[4] << 8) | (buffer[5] ^ 0x55)); #else tracenum(tftpPort); #endif #endif lastPacket = 0; returnCode = ACK; // Send back acknowledge for packet 0 break; case TFTP_OPCODE_DATA: // Valid packet with data so reset timer resetTick(); packetLength = tftpDataLen - (TFTP_OPCODE_SIZE + TFTP_BLOCKNO_SIZE); lastPacket = tftpBlock; writeAddr = (tftpBlock - 1) << 9; // Flash write address for this block #ifdef _VERBOSE traceln("Tftp: Data for block "); tracenum(lastPacket); #endif if((writeAddr + packetLength) > MAX_ADDR) { // Flash is full - abort with an error before a bootloader overwrite occurs // Application is now corrupt, so do not hand over. #ifdef _VERBOSE traceln("Tftp: Flash is full"); #endif returnCode = ERROR_FULL; } else { #ifdef _DEBUG_TFTP traceln("Tftp: Writing data from address "); tracenum(writeAddr); #endif uint8_t* pageBase = buffer + (UDP_HEADER_SIZE + TFTP_OPCODE_SIZE + TFTP_BLOCKNO_SIZE); // Start of block data uint16_t offset = 0; // Block offset // Set the return code before packetLength gets rounded up if(packetLength < TFTP_DATA_SIZE) returnCode = FINAL_ACK; else returnCode = ACK; // Round up packet length to a full flash sector size while(packetLength % SPM_PAGESIZE) packetLength++; #ifdef _DEBUG_TFTP traceln("Tftp: Packet length adjusted to "); tracenum(packetLength); #endif if(writeAddr == 0) { // First sector - validate if(!validImage(pageBase)) { returnCode = INVALID_IMAGE; /* FIXME: Validity checks. Small programms (under 512 bytes?) don't * have the the JMP sections and that is why app.bin was failing. * When flashing big binaries is fixed, uncomment the break below.*/ #ifndef _DEBUG_TFTP break; #endif } } // Flash packets for(offset = 0; offset < packetLength;) { uint16_t writeValue = (pageBase[offset]) | (pageBase[offset + 1] << 8); boot_page_fill(writeAddr + offset, writeValue); #ifdef _DEBUGMORE if((offset == 0) || ((offset == (packetLength - 2)))) { traceln("Tftp: Writing "); tracenum(writeValue); trace(" at offset "); tracenum(writeAddr + offset); } #endif offset += 2; if(offset % SPM_PAGESIZE == 0) { boot_page_erase(writeAddr + offset - SPM_PAGESIZE); boot_spm_busy_wait(); boot_page_write(writeAddr + offset - SPM_PAGESIZE); boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); #endif } } if(returnCode == FINAL_ACK) { // Flash is complete // Hand over to application #ifdef _VERBOSE traceln("Tftp: Flash is complete"); #endif // Flag the image as valid since we received the last packet eeprom_write_byte(EEPROM_IMG_STAT, EEPROM_IMG_OK_VALUE); } } break; // Acknowledgment case TFTP_OPCODE_ACK: #ifdef _DEBUG_TFTP traceln("Tftp: Acknowledge"); #endif break; // Error signal case TFTP_OPCODE_ERROR: #ifdef _DEBUG_TFTP traceln("Tftp: Error"); #endif /* FIXME: Resetting might be needed here too */ break; default: #ifdef _DEBUG_TFTP traceln("Tftp: Invalid opcode "); tracenum(tftpOpcode); #endif /* FIXME: This is where the tftp server should be resetted. * It can be done by reinitializig the tftpd or * by resetting the device. I should find out which is best... * Right now it is being done by resetting the timer if we have a * data packet. */ // Invalid - return error returnCode = ERROR_INVALID; break; } return(returnCode); }