/** * Check if an flash page is equal to a flash page buffer in SRAM */ static bool is_flash_page_equal_to_buffer(flash_addr_t page_addr, uint16_t *buffer) { uint16_t i; for (i = 0; i < FLASH_PAGE_SIZE / 2; i++) { if (nvm_flash_read_word(page_addr) != buffer[i]) { return false; } page_addr += 2; } return true; }
/** * \brief Simulate corruption of a part of Flash * * This function simulates corruption of the Flash by modifying one of the * strings in the error insertion menu. More specifically it replaces the * "-- Error insertion --" menu title with "Out of cheese!". If called again, * the original string is reverted. */ static void oven_classb_flash_corrupter(void) { /* Flash page base address of the menu title string */ flash_addr_t page_addr = ((uintptr_t)error_menu_title / FLASH_PAGE_SIZE) * FLASH_PAGE_SIZE; /* Address within the page */ uintptr_t string_addr = (uintptr_t)error_menu_title % FLASH_PAGE_SIZE; /* New string that we will replace it with */ const char newstring[] = " Out of cheese! "; const char oldstring[] = "-- Error insertion --"; /* Load page with strings from flash into our buffer */ nvm_flash_flush_buffer(); for (uint16_t addr = 0; addr < FLASH_PAGE_SIZE / 2; addr++) { flash_scramble_buf[addr] = nvm_flash_read_word((addr * 2) + page_addr); oven_wdt_periodic_reset(); } /* Check which string is the current and change it accordingly */ if (strcmp((char *)flash_scramble_buf + string_addr, oldstring) == 0) { strcpy((char *)flash_scramble_buf + string_addr, newstring); } else { strcpy((char *)flash_scramble_buf + string_addr, oldstring); } oven_wdt_periodic_reset(); /* Fill page buffer with our buffered data, then write it to flash */ for (uint16_t addr = 0; addr < FLASH_PAGE_SIZE / 2; addr++) { nvm_flash_load_word_to_buffer(addr * 2, flash_scramble_buf[addr]); oven_wdt_periodic_reset(); } nvm_flash_atomic_write_app_page(page_addr); }
/** * \brief Erase and write specific parts of application flash section * * \param address the address to where to write * \param buf pointer to the data * \param len the number of bytes to write * \param b_blank_check if True then the page flash is checked before write * to run or not the erase page command. * * Set b_blank_check to false if all application flash is erased before. */ void nvm_flash_erase_and_write_buffer(flash_addr_t address, const void *buf, uint16_t len, bool b_blank_check) { uint16_t w_value; uint16_t page_pos; bool b_flag_erase; #if (FLASH_SIZE>0x10000) uint32_t page_address; uint32_t opt_address = address; #else uint16_t page_address; uint16_t opt_address = (uint16_t)address; #endif // Compute the start of the page to be modified page_address = opt_address-(opt_address%FLASH_PAGE_SIZE); // For each page while ( len ) { b_flag_erase = false; nvm_wait_until_ready(); for (page_pos=0; page_pos<FLASH_PAGE_SIZE; page_pos+=2 ) { if (b_blank_check) { // Read flash to know if the erase command is mandatory w_value = nvm_flash_read_word(page_address); if (w_value!=0xFFFF) { b_flag_erase = true; // The page is not empty } }else{ w_value = 0xFFFF; } // Update flash buffer if (len) { if (opt_address == page_address) { // The MSB of flash word must be changed // because the address is even len--; opt_address++; LSB(w_value)=*(uint8_t*)buf; buf=(uint8_t*)buf+1; } } if (len) { if (opt_address == (page_address+1)) { // The LSB of flash word must be changed // because the user buffer is not empty len--; opt_address++; MSB(w_value)=*(uint8_t*)buf; buf=(uint8_t*)buf+1; } } // Load flash buffer nvm_flash_load_word_to_buffer(page_address,w_value); page_address+=2; } // Write flash buffer if (b_flag_erase) { nvm_flash_atomic_write_app_page(page_address-FLASH_PAGE_SIZE); }else{ nvm_flash_split_write_app_page(page_address-FLASH_PAGE_SIZE); } } }
static uint8_t sim900_wait_data_on_usart(uint8_t seconds) { for(uint8_t d1=seconds;d1>0;--d1) { for(uint16_t d2=10000;d2>0;--d2) { #ifdef SIM900_USART_POLLED if(usart_rx_is_complete(USART_GPRS)) { #else if(USART_RX_CBuffer_Data_Available(&sim900_usart_data)) { #endif return 0xFF; } delay_us(100); } } debug_string(VERY_VERBOSE,PSTR("(sim900_wait_data_on_usart) timed-out\r\n"),PGM_STRING); return 0; } static uint8_t sim900_read_string(char * const szBuf,uint8_t * const lenBuf) { const uint8_t ec = *lenBuf; uint8_t l = 0; uint8_t r = 0; char c; #ifndef SIM900_USART_POLLED usart_buffer_flush(&sim900_usart_data); #endif while(1) { if(!sim900_wait_data_on_usart(10)) { debug_string(NORMAL,PSTR("(sim900_read_string) got timeout waiting for a character\r\n"),true); r=1; break; } #ifdef SIM900_USART_POLLED c = usart_get(USART_GPRS); #else c = USART_RX_CBuffer_GetByte(&sim900_usart_data); #endif if(c=='\r') { if(g_log_verbosity > NORMAL) usart_putchar(USART_DEBUG,'@'); } else if(c=='\n') { if(g_log_verbosity > NORMAL) usart_putchar(USART_DEBUG,'#'); } else break; } if(r==0) while(l<ec) { szBuf[l++] = c; if(!sim900_wait_data_on_usart(10)) { debug_string(NORMAL,PSTR("(sim900_read_string) got timeout waiting for a character\r\n"),true); r=1; break; } #ifdef SIM900_USART_POLLED c = usart_get(USART_GPRS); #else c = USART_RX_CBuffer_GetByte(&sim900_usart_data); #endif if(c=='\r') { //if(g_log_verbosity > NORMAL) usart_putchar(USART_DEBUG,'@'); break; } else if(c=='\n') { //if(g_log_verbosity > NORMAL) usart_putchar(USART_DEBUG,'#'); break; } //if(g_log_verbosity > NORMAL) usart_putchar(USART_DEBUG,'.'); } if(ec==l) { r = 2; debug_string(NORMAL,PSTR("(sim900_read_string) Provided buffer is not big enough. Discarding chars\r\n"),true); l -= 1; } szBuf[l] = 0; //debug_string(VERBOSE,szBuf,RAM_STRING); //debug_string(VERBOSE,szCRLF,PGM_STRING); //debug_string(VERBOSE,PSTR("(sim900_read_string) out\r\n"),true); *lenBuf = l; return r; } static const char * sim900_wait4dictionary(const char * const dictionary[],uint8_t len) { uint8_t num = len; const char * p[len]; #ifndef SIM900_USART_POLLED usart_buffer_flush(&sim900_usart_data); #endif //debug_string(VERBOSE,PSTR("(sim900_wait4dictionary) IN\r\n"),true); while(num--) { p[num] = nvm_flash_read_word(dictionary+num); } while(1) { if(!sim900_wait_data_on_usart(20)) { debug_string(NORMAL,PSTR("(sim900_wait4dictionary) timeout waiting for sim900 response\r\n(sim900_wait4dictionary) OUT\r\n"),true); return NULL; } #ifdef SIM900_USART_POLLED const char c1 = usart_get(USART_GPRS); #else const char c1=USART_RX_CBuffer_GetByte(&sim900_usart_data); #endif for(uint8_t i=0;i<len;++i) { const char c2 = nvm_flash_read_byte(p[i]); if(c1!=c2) { p[i]=(char *) nvm_flash_read_word(dictionary+i); continue; } p[i]++; if(nvm_flash_read_byte(p[i])==0) { const char * const r = nvm_flash_read_word(dictionary+i); //debug_string(VERY_VERBOSE,PSTR("(sim900_wait4dictionary) got: "),true); //debug_string(VERY_VERBOSE,r,true); //debug_string(VERY_VERBOSE,szCRLF,true); //debug_string(NORMAL,PSTR("(sim900_wait4dictionary) OUT\r\n"),true); return r; } } } }