Пример #1
0
usbMsgLen_t usbFunctionSetup(uint8_t data[8])
{
    usbRequest_t *rq = (void *)data;

    usbMsgPtr = usbOutputBuffer;

    if (rq->bRequest == REQ_TEST_PROGRAMMER) {
        usbOutputBuffer[0] = ERROR_OK;
        usbOutputBuffer[1] = MAJOR_VERSION;
        usbOutputBuffer[2] = MINOR_VERSION;
        usbOutputBuffer[3] = rq->wValue.bytes[0];
        usbOutputBuffer[4] = rq->wValue.bytes[1];
        usbOutputBuffer[5] = rq->wIndex.bytes[0];
        usbOutputBuffer[6] = rq->wIndex.bytes[1];
        return 7;
    } else if (rq->bRequest == REQ_TURN_PROG_ON) {
        return turnProgOn();
    } else if (rq->bRequest == REQ_TURN_PROG_OFF) {
        return turnProgOff();
    } else if (rq->bRequest == REQ_TEST_NRF) {
        return nrfTest();
    } else if (rq->bRequest == REQ_PROGRAM_PAGE) {
        return programPage(rq->wValue.word, rq->wIndex.word);
    } else if(rq->bRequest == REQ_READ) {
        return readMemory(rq->wValue.word, rq->wIndex.word);
    } else if(rq->bRequest == REQ_ERASE_PAGE) {
        return erasePage(rq->wValue.word);
    }

    return 0;
}
Пример #2
0
void avrisp()
{
	static uint16_t address = 0;
	uint8_t ch = getch();
	switch (ch)
	{
	case '0': // signon
		_error = 0;
		reply();
		break;
	case '1':
		if (receiveEop())
		{
			Serial.print("AVR ISP");
			Serial.write(STK_OK);
		}
		break;
	case 'A':
		replyVersion(getch());
		break;
	case 'B':
		fill(20);
		setParameters();
		reply();
		break;
	case 'E': // extended parameters - ignore for now
		fill(5);
		reply();
		break;
	case 'P':
		_programming ? pulse(LED_ERROR, 3) : beginProgramming();
		reply();
		break;
	case 'U': // set address (word)
		address = getch() | (getch() << 8);
		reply();
		break;
	case 0x60: //STK_PROG_FLASH
		getch();
		getch();
		reply();
		break;
	case 0x61: //STK_PROG_DATA
		getch();
		reply();
		break;
	case 0x64: //STK_PROG_PAGE
		programPage(address);
		break;
	case 0x74: //STK_READ_PAGE 't'
		readPage(address);
		break;
	case 'V': //0x56
		universal();
		break;
	case 'Q': //0x51
		_error = 0;
		endProgramming();
		reply();
		break;
	case 0x75: //STK_READ_SIGN 'u'
		readSignature();
		break;
		// expecting a command, not CRC_EOP
		// this is how we can get back in sync
	case CRC_EOP:
		_error = true;
		Serial.write(STK_NOSYNC);
		break;
	default: // anything else we will return STK_UNKNOWN
		_error = true;
		if (receiveEop())
			Serial.write(STK_UNKNOWN);
		break;
	}
}
Пример #3
0
// main start
int main(void) {	
	
	asm volatile ("clr __zero_reg__");
	// reset MCU status register	
	MCUSR = 0;
	
	// enable watchdog to avoid deadlock
	watchdogConfig(WATCHDOG_8S);

	// initialize SPI
	SPIinit();
		
	// initialize RF module	
	RFinit();

	// Read node config from EEPROM, i.e. nodeId, parent nodeId, distance
	eeprom_read_block((void*)&nc, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(struct NodeConfig));
	// Read firmware config from EEPROM, i.e. type, version, CRC, blocks
	eeprom_read_block((void*)&fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(NodeFirmwareConfig));
	
	// find nearest node during reboot: invalidate parent node settings, since we have to re-discover them for every single reboot
	configuredParentID = nc.parentNodeId;
	// nc.parentNodeId = 0xFF;
	nc.distance = 0xFF;
	
	// prepare for I_FIND_PARENTS
	outMsg.sender = nc.nodeId;
	outMsg.last = nc.nodeId;
	outMsg.sensor = 0xFF;
	outMsg.destination = BROADCAST_ADDRESS;
	
	// set header
	mSetVersion(outMsg, PROTOCOL_VERSION);
	mSetLength(outMsg, 0);
	mSetCommand(outMsg, C_INTERNAL);
	mSetAck(outMsg,false);
	mSetPayloadType(outMsg, P_STRING);
	
	// set reading & writing pipe address
	setAddress(nc.nodeId);

	// network up? get neighbors, else startup
	if (!sendAndWait(I_FIND_PARENT, I_FIND_PARENT_RESPONSE)) {
		startup();
	}
	
	// all messages to gateway
	outMsg.destination = GATEWAY_ADDRESS;
	
	// if no node id assigned, request new id
	if (nc.nodeId == AUTO) {
		// listen to broadcast
		openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(BROADCAST_ADDRESS));
		if (sendAndWait(I_ID_REQUEST, I_ID_RESPONSE)) {
			// save id to eeprom
			eeprom_update_byte((uint8_t*)EEPROM_NODE_ID_ADDRESS, atoi(inMsg.data));
		}
		// we could go on and set everything right here, but rebooting will take care of that - and saves some bytes :)
		reboot();				
	}
	
	// wuff
	watchdogReset();
	// prepare for FW config request
	RequestFirmwareConfig *reqFWConfig = (RequestFirmwareConfig *)outMsg.data;	
	mSetLength(outMsg, sizeof(RequestFirmwareConfig));
	mSetCommand(outMsg, C_STREAM);
	mSetPayloadType(outMsg,P_CUSTOM);
	// copy node settings to reqFWConfig
	memcpy(reqFWConfig,&fc,sizeof(NodeFirmwareConfig));
	// add bootloader information
	reqFWConfig->BLVersion = MYSBOOTLOADER_VERSION;
	
	// send node config and request FW config from controller
	if (!sendAndWait(ST_FIRMWARE_CONFIG_REQUEST, ST_FIRMWARE_CONFIG_RESPONSE)) {
		startup();
	}
	
	NodeFirmwareConfig *firmwareConfigResponse = (NodeFirmwareConfig *)inMsg.data;
	
	// bootloader commands
	if (firmwareConfigResponse->blocks == 0) {
		// verify flag
		if (firmwareConfigResponse->crc == 0xDA7A){
			// cmd 0x01 clear eeprom
			if(firmwareConfigResponse->bl_command == 0x01) {
				for(uint16_t i = 0; i < EEPROM_SIZE; i++) eeprom_update_byte((uint8_t *)i,0xFF);
			} else 
			// cmd 0x02 set id
			if(firmwareConfigResponse->bl_command == 0x02) {
				eeprom_update_byte((uint8_t*)EEPROM_NODE_ID_ADDRESS, (uint8_t)firmwareConfigResponse->bl_data);
			}
		}
		// final step
		reboot();
	}
	
	// compare with current node configuration, if equal startup
	if (!memcmp(&fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig))) {
		startup();
	}
	
	// *********** from here on we will fetch new FW
	
	// invalidate current CRC
	fc.crc = 0xFFFF;
	// write fetched type and version in case OTA fails (BL will reboot and re-request FW with stored settings)
	eeprom_update_block(&fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS,sizeof(NodeFirmwareConfig));
	
	// copy new FW config
	memcpy(&fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig));
	RequestFWBlock *firmwareRequest = (RequestFWBlock *)outMsg.data;
	mSetLength(outMsg, sizeof(RequestFWBlock));
	
	firmwareRequest->type = fc.type;
	firmwareRequest->version = fc.version;
	
	// request FW from controller, load FW counting backwards
	uint16_t block = fc.blocks;
	do {
		firmwareRequest->block = block - 1;
		
		// request FW block
		if (!sendAndWait(ST_FIRMWARE_REQUEST, ST_FIRMWARE_RESPONSE)) {
			reboot();
		}
		
		ReplyFWBlock *firmwareResponse = (ReplyFWBlock *)inMsg.data;
		
		// did we receive requested block?
		if (!memcmp(firmwareRequest,firmwareResponse,sizeof(RequestFWBlock))) {
			// calculate page offset
			uint8_t offset = ((block - 1) * FIRMWARE_BLOCK_SIZE) % SPM_PAGESIZE;
			// write to buffer
			memcpy(progBuf + offset, firmwareResponse->data, FIRMWARE_BLOCK_SIZE);
			// program if page full
			if (offset == 0) {
				programPage(((block - 1) * FIRMWARE_BLOCK_SIZE), progBuf);
			}
			block--;	
		}	
	} while (block);
	
	// wuff
	watchdogReset();
	
	// all blocks transmitted, calc CRC and write to eeprom if valid	
	if (IsFirmwareValid()) {
		// if FW is valid, write settings to eeprom 
		eeprom_update_block(&fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(NodeFirmwareConfig));
	} 
	// final step
	reboot();
}