void read_one_bank_params_from_FLASH(uint8_t bank_i){ flash_bankstatus[bank_i] = flash_read_byte(FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_bankstatus + (FLASH_SIZE_parambank * bank_i)); flash_read_array((uint8_t *)flash_note[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_note + (FLASH_SIZE_parambank * bank_i), 6); flash_read_array((uint8_t *)flash_scale[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_scale + (FLASH_SIZE_parambank * bank_i), 6); flash_read_array((uint8_t *)flash_scale_bank[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_scale_bank + (FLASH_SIZE_parambank * bank_i), 6); flash_read_array((uint8_t *)flash_lock[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_lock + (FLASH_SIZE_parambank * bank_i), 6); flash_read_array((uint8_t *)flash_q_locked[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_q_locked + (FLASH_SIZE_parambank * bank_i), 6); flash_read_array((uint8_t *)flash_qval[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_qval + (FLASH_SIZE_parambank * bank_i), 24); flash_read_array((uint8_t *)flash_freq_nudge[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_freq_nudge + (FLASH_SIZE_parambank * bank_i), 24); flash_freqblock[bank_i] = flash_read_word(FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_freqblock + (FLASH_SIZE_parambank * bank_i)); flash_filter_type[bank_i] = flash_read_byte(FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_filter_type + (FLASH_SIZE_parambank * bank_i)); flash_filter_mode[bank_i] = flash_read_byte(FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_filter_mode + (FLASH_SIZE_parambank * bank_i)); //Force ONEPASS if we read a legacy slot as BPRE if (flash_filter_type[bank_i] == BPRE) flash_filter_mode[bank_i] = ONEPASS; //Force TWOPASS for legacy banks if (flash_filter_mode[bank_i] != ONEPASS) flash_filter_mode[bank_i] = TWOPASS; flash_cur_colsch[bank_i] = flash_read_byte(FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_cur_colsch + (FLASH_SIZE_parambank * bank_i)); }
/* * int ifs_init(void): Initialize IFS files */ int ifs_init(void) { uint8_t *src, *dest; #if FLASHEND >0xffff uint32_t flash_src; #define flash_read_byte(addr) pgm_read_byte_far(addr) #else uint16_t flash_src; #define flash_read_byte(addr) pgm_read_byte_near(addr) #endif /* FLASHEND */ // initialize .ifs_int_0 for(dest = __ifs_int_0_start; dest < __ifs_int_0_end; dest++) { *dest = 0x00; } // poll until eeprom is ready while(!eeprom_is_ready()) ; src =__ifs_int_eep_loadstart; for(dest = __ifs_int_eep_start; dest < __ifs_int_eep_end; dest++) { *dest = eeprom_read_byte(src++); } #if FLASHEND >0xffff flash_src = ptr_to_ui32(__ifs_int_flash_loadstart); #else flash_src = __ifs_int_flash_loadstart; #endif /* FLASHEND */ for(dest = __ifs_int_flash_start; dest < __ifs_int_flash_end; dest++) { *dest = flash_read_byte(flash_src++); } #if defined (USE_EXT_RAM) // initialize .ifs_ext_0 for(dest = __ifs_ext_0_start; dest < __ifs_ext_0_end; dest++) { *dest = 0x00; } // poll until eeprom is ready while(!eeprom_is_ready()) ; src =__ifs_ext_eep_loadstart; for(dest = __ifs_ext_eep_start; dest < __ifs_ext_eep_end; dest++) { *dest = eeprom_read_byte(src++); } #if FLASHEND >0xffff flash_src = ptr_to_ui32(__ifs_ext_flash_loadstart); #else flash_src = __ifs_ext_flash_loadstart; #endif /* FLASHEND */ for(dest = __ifs_ext_flash_start; dest < __ifs_ext_flash_end; dest++) { *dest = flash_read_byte(flash_src++); } #endif /* USE_EXT_RAM */ return 0; }
/** * Calculate ADCS boot counter and save in flash. The boot counter is available * in global variable adcs_boot_counter. * @return The status of Flash memory and if the boot counter is valid */ adcs_error_status increment_boot_counter() { adcs_boot_cnt = 0; uint8_t adcs_boot_cnt_8[4] = { 0 }; uint32_t flash_read_address = BOOT_CNT_BASE_ADDRESS; for (uint8_t i = 0; i < 4; i++) { if (flash_read_byte(&adcs_boot_cnt_8[i], flash_read_address) == FLASH_NORMAL) { flash_read_address = flash_read_address + BOOT_CNT_OFFSET_ADDRESS; } else { return ERROR_FLASH; } } cnv8_32(adcs_boot_cnt_8, &adcs_boot_cnt); adcs_boot_cnt++; if (flash_erase_block4K(BOOT_CNT_BASE_ADDRESS) == FLASH_ERROR) { return ERROR_FLASH; } cnv32_8(adcs_boot_cnt, &adcs_boot_cnt_8); if (flash_write_page(adcs_boot_cnt_8, sizeof(adcs_boot_cnt_8), BOOT_CNT_BASE_ADDRESS) == FLASH_ERROR) { return FLASH_ERROR; } return error_propagation(ERROR_OK); }
/** * @fn static void eeprom_format_page(U16 phy_addr) * @brief erase page and write erase count plus 1 in TAG position. * for erase count equal 0xFFFFFF, plus '1' will get 0x1000000, and will only * write 24 bits 0x000000 into flash. * @param phy_addr physical page address * * @return none */ static void eeprom_format_page(U16 phy_addr) { UU32 erase_count; /* Ignore first byte in page, it is flash status byte*/ erase_count.U8[0] = 0; erase_count.U8[1] = flash_read_byte(phy_addr + 1); erase_count.U8[2] = flash_read_byte(phy_addr + 2); erase_count.U8[3] = flash_read_byte(phy_addr + 3); erase_count.U32 += 1; flash_erase_page(phy_addr); flash_write_byte(phy_addr + 1, erase_count.U8[1]); flash_write_byte(phy_addr + 2, erase_count.U8[2]); flash_write_byte(phy_addr + 3, erase_count.U8[3]); }
U8 eeprom_read_byte(U8 log_addr, U8 *byte) { U16 phy_addr; if (log_addr >= EE_SIZE) return ERROR; phy_addr = page.addr + page.tail - EE_VARIABLE_SIZE; while(phy_addr >= (page.addr + EE_TAG_SIZE)){ if (log_addr == flash_read_byte(phy_addr)) { *byte = flash_read_byte(phy_addr + 1); return SUCCESS; } phy_addr -= EE_VARIABLE_SIZE; } *byte = 0xFF; return SUCCESS; }
//Reads from FLASH memory and stores it in SRAM variables void read_all_params_from_FLASH(void){ //~200uS uint8_t bank_i; uint32_t t; flash_firmware_version = flash_read_word(FLASH_ADDR_firmware_version) - FLASH_SYMBOL_firmwareoffset; flash_startupbank = flash_read_byte(FLASH_ADDR_startupbank) - FLASH_SYMBOL_startupoffset; flash_clipmode = flash_read_byte(FLASH_ADDR_clipmode); t = flash_read_word(FLASH_ADDR_trackcomp1); if (t==0xFFFFFFFF) t=1; flash_trackcomp[0]=*(float *)&t; t = flash_read_word(FLASH_ADDR_trackcomp2); if (t==0xFFFFFFFF) t=1; flash_trackcomp[1]=*(float *)&t; flash_trackoffset[0] = flash_read_word(FLASH_ADDR_trackoffset1); flash_trackoffset[1] = flash_read_word(FLASH_ADDR_trackoffset2); for (bank_i=0;bank_i<6;bank_i++){ flash_bankstatus[bank_i] = flash_read_byte(FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_bankstatus + (FLASH_SIZE_parambank * bank_i)); flash_read_array((uint8_t *)flash_note[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_note + (FLASH_SIZE_parambank * bank_i), 6); flash_read_array((uint8_t *)flash_scale[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_scale + (FLASH_SIZE_parambank * bank_i), 6); flash_read_array((uint8_t *)flash_scale_bank[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_scale_bank + (FLASH_SIZE_parambank * bank_i), 6); flash_read_array((uint8_t *)flash_lock[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_lock + (FLASH_SIZE_parambank * bank_i), 6); flash_read_array((uint8_t *)flash_q_locked[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_q_locked + (FLASH_SIZE_parambank * bank_i), 6); flash_read_array((uint8_t *)flash_qval[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_qval + (FLASH_SIZE_parambank * bank_i), 24); flash_filter_type[bank_i] = flash_read_byte(FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_filter_type + (FLASH_SIZE_parambank * bank_i)); flash_cur_colsch[bank_i] = flash_read_byte(FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_cur_colsch + (FLASH_SIZE_parambank * bank_i)); flash_read_array((uint8_t *)flash_freq_nudge[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_freq_nudge + (FLASH_SIZE_parambank * bank_i), 24); } flash_read_array((uint8_t *)flash_COLOR_CH, FLASH_ADDR_colschem, FLASH_SIZE_colschem); flash_read_array((uint8_t *)flash_user_scalebank, FLASH_ADDR_user_scalebank, FLASH_SIZE_user_scalebank); }
/** * @fn static void eeprom_scan_page(U16 phy_addr, U8 idx) * @brief scan page and update page information * * @param phy_addr page physical address, * @param idx page index */ static void eeprom_scan_page(U16 phy_addr, U8 idx) { U16 tail; for (tail = EE_TAG_SIZE; tail < FL_PAGE_SIZE; tail += EE_VARIABLE_SIZE) { if( 0xFF == flash_read_byte(phy_addr + tail)) break; } eeprom_update_page_info(idx, phy_addr, tail); }
void read_one_bank_params_from_FLASH(uint8_t bank_i){ flash_bankstatus[bank_i] = flash_read_byte(FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_bankstatus + (FLASH_SIZE_parambank * bank_i)); flash_read_array((uint8_t *)flash_note[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_note + (FLASH_SIZE_parambank * bank_i), 6); flash_read_array((uint8_t *)flash_scale[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_scale + (FLASH_SIZE_parambank * bank_i), 6); flash_read_array((uint8_t *)flash_scale_bank[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_scale_bank + (FLASH_SIZE_parambank * bank_i), 6); flash_read_array((uint8_t *)flash_lock[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_lock + (FLASH_SIZE_parambank * bank_i), 6); flash_read_array((uint8_t *)flash_q_locked[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_q_locked + (FLASH_SIZE_parambank * bank_i), 6); flash_read_array((uint8_t *)flash_qval[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_qval + (FLASH_SIZE_parambank * bank_i), 24); flash_read_array((uint8_t *)flash_freq_nudge[bank_i], FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_freq_nudge + (FLASH_SIZE_parambank * bank_i), 24); flash_filter_type[bank_i] = flash_read_byte(FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_filter_type + (FLASH_SIZE_parambank * bank_i)); flash_cur_colsch[bank_i] = flash_read_byte(FLASH_ADDR_START_PARAMBANKS + FLASH_OFFSET_cur_colsch + (FLASH_SIZE_parambank * bank_i)); }
// Sends model number and firmware version number to host. static void sendInitAck() { // Send model number and firmware number send_buf[1] = MODEL_NUM; send_buf[2] = flash_read_byte(FW_NUMBER); send(CMD_ACK,3); if (send_success) state = CONNECTED; else state = PINGING; }
/* * read the Flash status byte */ static uint8_t flash_read_status( void ) { uint8_t status; cs_low( ); flash_write_byte( AT_STATUS ); status = flash_read_byte( ); cs_high( ); return status; }
/** * @fn static void eeprom_check_pages(void) * @brief Check page status, handle different page status. * * The first byte of flash page is status byte. It contains three status: * RECEIVING, ACTIVE, ERASED. We will format RECEIVING page; if ERASED page * is not blank, we will format it too. If we have two more ACTIVE pages, * we will erase full one * * @return none */ static void eeprom_check_pages(void) { U8 i, status, idx, active_pages = 0; U16 phy_addr ,active_page_addr = EE_BASE_ADDR; for (i = 0; i < FL_PAGES; i++) { phy_addr = EE_BASE_ADDR + i * FL_PAGE_SIZE; status = flash_read_byte(phy_addr); switch (status) { case PAGE_STATUS_RECEIVING: eeprom_format_page(phy_addr); break; case PAGE_STATUS_ERASED: if (!eeprom_is_formatted(phy_addr)) eeprom_format_page(phy_addr); break; case PAGE_STATUS_ACTIVE: if (active_pages++) { U16 tmp = phy_addr + FL_PAGE_SIZE - EE_VARIABLE_SIZE; /* erase a full contents page*/ if (flash_read_byte(tmp) == 0xFF) { eeprom_format_page(phy_addr); }else{ eeprom_format_page(active_page_addr); active_page_addr = phy_addr; idx = i; } }else{ active_page_addr = phy_addr; idx = i; } break; default: break; } } /* If there is no active page, we update page status position with active status flag*/ if (0 == active_pages) flash_write_byte(active_page_addr,PAGE_STATUS_ACTIVE); eeprom_scan_page(active_page_addr,idx); }
/** * @fn static U8 eeprom_is_formatted(U16 phy_addr) * @brief Check page formatted or not. * * @param phy_addr page physical address * @return TRUE: page is formatted; FALSE: page is not formatted */ static U8 eeprom_is_formatted(U16 phy_addr) { U16 i; UU32 tag; tag.U8[0] = flash_read_byte(phy_addr++); tag.U8[1] = flash_read_byte(phy_addr++); tag.U8[2] = flash_read_byte(phy_addr++); tag.U8[3] = flash_read_byte(phy_addr++); /* Change status is erased or erase count not equal 0xFFFFFF*/ if((tag.U8[0] != PAGE_STATUS_ERASED) || ((tag.U8[1] == 0xFF)&&(tag.U8[2] = 0xFF)&&(tag.U8[3] = 0xFF))) { return FALSE; } for (i = EE_TAG_SIZE; i < FL_PAGE_SIZE; i++) { if (flash_read_byte(phy_addr++) != 0xFF) { return FALSE; } } return TRUE; }
/* * simple test: dump all contents of built-in cartridge */ void flash_test( void ) { uint8_t i = 0; long size = 2048L * 264L; flash_write_cmd( AT_CAR, 0 ); flash_clocks( 32 ); while( --size >= 0 && usb_peek() != 3 ) { printf( "%02x%c", flash_read_byte(), ++i % 16 ? ' ' : '\n' ); } cs_high( ); }
/** * @fn void flash_copy_page() * @brief move valid data from one page to another page. * * When an active page is full, it will find next available page, and write data * in it, and then call this function. It copies data from source page to * destination page. * * @note When calling this function, be aware that destination page already write * a pair of the data. Before copy loop start, we need to read it out and set * bitmap correspond bit to '1'. * * @return none */ static void flash_copy_page() { U16 src, dest, tail; U8 log_addr,idx; U8 eeprom_bitmap[EE_BITMAP_SIZE]; for (idx = 0; idx < EE_BITMAP_SIZE; idx++) { eeprom_bitmap[idx] = 0; } /* Source page scan start from bottom*/ src = page.addr + FL_PAGE_SIZE - EE_VARIABLE_SIZE; dest = eeprom_get_next_page(page.idx); /* Mark destination page as receiving status */ flash_write_byte(dest,PAGE_STATUS_RECEIVING); EE_SET_BITMAP(flash_read_byte(dest + EE_TAG_SIZE)); tail =EE_TAG_SIZE + EE_VARIABLE_SIZE; /* Read data from source page and copy it to destination page*/ while (src >= (page.addr + EE_TAG_SIZE)) { log_addr = flash_read_byte(src); if (log_addr < EE_SIZE) { if (!EE_GET_BITMAP(log_addr)) { flash_write_byte(dest + tail, log_addr); flash_write_byte(dest + tail + 1, flash_read_byte(src + 1)); tail += EE_VARIABLE_SIZE; EE_SET_BITMAP(log_addr); } } src -= EE_VARIABLE_SIZE; } /* Mark destination page as active status*/ flash_write_byte(dest,PAGE_STATUS_ACTIVE); /* Erase source page and update erase count in page TAG position*/ eeprom_format_page(page.addr); /* Update page information*/ idx = (dest - EE_BASE_ADDR) / FL_PAGE_SIZE; eeprom_update_page_info(idx, dest, tail); }
char flash_read(short size, int offset, uint32 * value){ switch(size){ case 8: *(uint8 *)value = (uint8)flash_read_byte (offset); break; case 16: *(uint16 *)value = (uint16)flash_read_halfword(offset); break; case 32: *value = flash_read_word(offset); break; default: return -1; } return 0; }
static unsigned char dump_address( unsigned int address, unsigned char area ) { unsigned char c = 0xff; switch( area ) { case 0: /* idata/SFR */ if( (unsigned char)address < 0x80 ) c = *(unsigned char __idata *)address; else c = read_mcs51_sfr( (unsigned char)address ); break; case 1: /* xdata/code */ c = *(unsigned char __xdata *)address; break; case 2: /* code (anywhere in the SPI flash) */ c = flash_read_byte(m.address_page, m.address); break; } puthex( c ); return c; }
// Bootloader protocol logic // static void bootloader(void) { uint8_t c; uint8_t count, i; static uint16_t address; // Wait for a command byte LED_BOOTLOADER = LED_ON; c = cin(); LED_BOOTLOADER = LED_OFF; // common tests for EOC switch (c) { case PROTO_GET_SYNC: case PROTO_GET_DEVICE: case PROTO_CHIP_ERASE: case PROTO_PARAM_ERASE: case PROTO_READ_FLASH: case PROTO_DEBUG: if (cin() != PROTO_EOC) goto cmd_bad; } switch (c) { case PROTO_GET_SYNC: // sync break; case PROTO_GET_DEVICE: cout(BOARD_ID); cout(board_frequency); break; case PROTO_CHIP_ERASE: // erase the program area flash_erase_app(); break; case PROTO_PARAM_ERASE: flash_erase_scratch(); break; case PROTO_LOAD_ADDRESS: // set address address = cin(); address |= (uint16_t)cin() << 8; if (cin() != PROTO_EOC) goto cmd_bad; break; case PROTO_PROG_FLASH: // program byte c = cin(); if (cin() != PROTO_EOC) goto cmd_bad; flash_write_byte(address++, c); break; case PROTO_READ_FLASH: // readback byte c = flash_read_byte(address++); cout(c); break; case PROTO_PROG_MULTI: count = cin(); if (count > sizeof(buf)) goto cmd_bad; for (i = 0; i < count; i++) buf[i] = cin(); if (cin() != PROTO_EOC) goto cmd_bad; for (i = 0; i < count; i++) flash_write_byte(address++, buf[i]); break; case PROTO_READ_MULTI: count = cin(); if (cin() != PROTO_EOC) goto cmd_bad; for (i = 0; i < count; i++) { c = flash_read_byte(address++); cout(c); } break; case PROTO_REBOOT: // generate a software reset, which should boot to the application RSTSRC |= (1 << 4); case PROTO_DEBUG: // XXX reserved for ad-hoc debugging as required break; default: goto cmd_bad; } sync_response(); cmd_bad: return; }
/* Ma-ma-ma-main function! */ void main() { command_t cmd = CMD_NO_CMD; uint16_t channel_timer = 0, bootloader_timer = 0, connection_timer = 0; uint8_t ch_i = 0; bool running; // Disable global interrupt cli(); // Set up parameters for RF communication. configureRF(); #ifdef DEBUG_LED_ P0DIR = 0; P0 = 0x55; #endif running = true; // Boot loader loop. // Will terminate after a couple of seconds if firmware has been successfully // installed. send(CMD_PING,1); while(running) { if(send_success){ if (packet_received) { connection_timer = 0; cmd = MSG_CMD; switch (cmd) { // Host initiates contact with the device. case CMD_INIT: // Send ACK to host, go to CONNECTED state if successful. sendInitAck(); // Reset timers channel_timer = bootloader_timer = 0; break; // Host starts a firmware update. case CMD_UPDATE_START: if (state == CONNECTED) { // Initiate firmware updates, go to RECEIVING_FIRMWARE state // if successful. startFirmwareUpdate(); } #ifdef DEBUG_LED_ P0 = state; #endif break; // Write message containing one hex record. case CMD_WRITE: if (state == RECEIVING_FIRMWARE) { writeHexRecord( ); } #ifdef DEBUG_LED_ P0 = 0x40; #endif break; // Firmware update has been completed. case CMD_UPDATE_COMPLETE: // Check that every byte is received. if (bytes_received == bytes_total) { // Mark firmware as successfully installed. flash_write_byte(FW_NUMBER, firmware_number); state = CONNECTED; send(CMD_ACK,1); } else { send(CMD_NACK,1); } if (!send_success) { state = ERROR; } #ifdef DEBUG_LED_ P0 = 0x10; #endif break; // Host request data from flash at specified address. case CMD_READ: readHexRecord(); #ifdef DEBUG_LED_ P0 = 0x20; #endif break; // Host sends pong to keep connections with device. case CMD_PONG: send(CMD_PING,1); #ifdef DEBUG_LED_ P0 = 0x80; #endif break; // Host sends disconnect case CMD_EXIT: send(CMD_ACK,1); if(send_success)running=false; state = PINGING; break; // These commands should no be received. case CMD_NO_CMD: default: state = ERROR; break; } // Clear command cmd = CMD_NO_CMD; }else{ //Host app do not reply, reping send(CMD_PING,1); } }else{ //host unreached if (state == PINGING) { // Will ping to one channel for 'a while' before changing. if (++channel_timer > CHANNEL_TIMEOUT) { channel_timer = 0; // Go to next channel ch_i = (ch_i+1)%CHANNEL_SIZE; rf_set_channel(default_channels[ch_i]); #ifdef DEBUG_LED_ P0 = ch_i; #endif // After changing channels and being in the PINGING state // for 'a while', boot loader loop will check if there is firmware // installed, and if so end the while(running) loop. if (++bootloader_timer > BOOTLOADER_TIMEOUT) { bootloader_timer = 0; running = (flash_read_byte(FW_NUMBER) != 0xFF) ? false : true; }else send(CMD_PING,1); } }else { if (++connection_timer > CONNECTION_TIMEOUT) state = PINGING; send(CMD_PING,1); } } } resetRF(); #ifdef DEBUG_LED_ // Default value for P0DIR P0 = 0x00; P0DIR = 0xFF; #endif // Reads address of firmware's reset vector. temp_data[0] = flash_read_byte(FW_RESET_ADDR_H); temp_data[1] = flash_read_byte(FW_RESET_ADDR_L); // sti(); //Should we enable irqs? or should the firmware enable it later? // Jump to firmware. Goodbye! ((firmware_start)(((uint16_t)temp_data[0]<<8) | (temp_data[1])))(); }