示例#1
0
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);
}
示例#3
0
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);
}