00001
00028
00029 #include "roboot.h"
00030 #include <avr/boot.h>
00031 #include <avr/pgmspace.h>
00032
00033 static uint32_t FlashUnlock(uint32_t page_address);
00034 static void FlashLock(uint32_t page_address);
00035 static uint32_t FlashErasePage(uint32_t page_address);
00036 static uint32_t FlashWriteData(uint32_t write_addr, const uint8_t *chunk, uint32_t chunk_len);
00037
00038 static uint8_t memcmp_prog(const uint8_t* s1, uint32_t s2, size_t len);
00039 static uint8_t read_byte_prog(uint32_t addr);
00040
00041 const ROBOOT_FLASH_Operations_T flash_oper = { FlashUnlock, FlashLock, FlashErasePage, FlashWriteData };
00042
00043
00044
00045
00046
00047 static uint32_t FlashUnlock(uint32_t page_address)
00048 {
00049 (void) page_address;
00050
00051 return 0;
00052
00053 }
00054
00055
00056
00057
00058
00059 static void FlashLock(uint32_t page_address)
00060 {
00061 (void) page_address;
00062
00063 }
00064
00065
00066
00067
00068
00069 static uint32_t FlashErasePage(uint32_t page_address)
00070 {
00071 boot_page_erase(page_address);
00072 boot_spm_busy_wait();
00073 return 0;
00074 }
00075
00076
00077
00078
00079
00080 static uint32_t FlashWriteData(uint32_t data_address, const uint8_t *chunk, uint32_t chunk_len)
00081 {
00082 uint16_t i;
00083 const uint8_t *flash_data;
00084 uint16_t check_len;
00085
00086 flash_data = chunk;
00087
00088
00089 if (chunk_len & 1U)
00090 {
00091 chunk_len++;
00092 }
00093
00094 while (chunk_len)
00095 {
00096 check_len = (chunk_len > SPM_PAGESIZE) ? SPM_PAGESIZE : chunk_len;
00097 for (i=0; i < check_len; i += 2)
00098 {
00099 #if 0
00100 uint16_t w = *flash_data++;
00101 w += (*flash_data++) << 8;
00102 boot_page_fill(data_address+i, w);
00103 #else
00104
00105
00106 boot_page_fill(data_address+i, *(uint16_t*)flash_data);
00107 flash_data += 2;
00108 #endif
00109 }
00110
00111 boot_page_write(data_address);
00112 boot_spm_busy_wait();
00113
00114
00115 boot_rww_enable();
00116 if (memcmp_prog(chunk, data_address, check_len))
00117 {
00118 return 1;
00119 }
00120
00121 chunk_len -= check_len;
00122 data_address += SPM_PAGESIZE;
00123 chunk += SPM_PAGESIZE;
00124 }
00125
00126 return 0;
00127 }
00128
00129
00130
00131
00132
00133 static uint8_t memcmp_prog(const uint8_t* s1, uint32_t s2, size_t len)
00134 {
00135 while (len)
00136 {
00137 if (read_byte_prog(s2) != *s1)
00138 {
00139 return 1;
00140 }
00141 s1++;
00142 s2++;
00143 len--;
00144 }
00145
00146 return 0;
00147
00148 }
00149
00150
00151
00152
00153
00154 static uint8_t read_byte_prog(uint32_t addr)
00155 {
00156 uint8_t pgm_byte;
00157
00158 #if FLASHEND <= 0xFFFFUL
00159 pgm_byte = pgm_read_byte_near((uint16_t) addr);
00160 #else
00161 #if 0
00162 __asm__
00163 (
00164 "out %2, %C1" "\n\t"
00165 "mov r31, %B1" "\n\t"
00166 "mov r30, %A1" "\n\t"
00167 "elpm %0, Z" "\n\t"
00168 : "=r" (pgm_byte)
00169 : "r" (addr),
00170 "I" (_SFR_IO_ADDR(RAMPZ))
00171 : "r30", "r31"
00172 );
00173 #else
00174 pgm_byte = pgm_read_byte_far(addr);
00175 #endif
00176 #endif
00177
00178 return pgm_byte;
00179
00180 }