koT-34 0 29 марта, 2010 Опубликовано 29 марта, 2010 · Жалоба Добрый день. Пишу на С, компилятор winavr, контроллер atmega64. Знаю, что создать и прочитать переменные, в памяти программ, можно с помощью PROGMEM. Возможно ли средствами С редактировать данные записанные во флеш память МК ? Пример(создаю в памяти программ массив данных, и хочу изменить первый байт): static unsigned char mydata[20] PROGMEM = {0x00,0x01,0x02, ... 0x12,0x13,0x14}; unsigned char temp = 10; mydata[0] = temp; Приведенный способ естественно не работает: error: assignment of read-only location 'mydata[0]' Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mempfis_ 0 29 марта, 2010 Опубликовано 29 марта, 2010 (изменено) · Жалоба Возможно ли средствами С редактировать данные записанные во флеш память МК ? Приведенный способ естественно не работает: error: assignment of read-only location 'mydata[0]' Из application section нельзя. Но можно сделать из boot section. Но там всё не так просто.... Почитайте про бутлоадер в документации на МК. А чем вас не устраивает хранение данных в eeprom которую можно модифицировать из application section? Изменено 29 марта, 2010 пользователем mempfis_ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Палыч 5 29 марта, 2010 Опубликовано 29 марта, 2010 · Жалоба Возможно ли средствами С редактировать данные записанные во флеш память МК ? Смотрите файл boot.h Естественно, что процедуры записи должны быть расположены в области загрузчика (это - Ваша обязанность). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
koT-34 0 29 марта, 2010 Опубликовано 29 марта, 2010 · Жалоба А чем вас не устраивает хранение данных в eeprom которую можно модифицировать из application section? В eeprom мало места. Я правильно понимаю что во флеш можно писать на ассемблере, с помщью команды "SPM"? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mp41 0 29 марта, 2010 Опубликовано 29 марта, 2010 (изменено) · Жалоба Я правильно понимаю что во флеш можно писать на ассемблере, с помщью команды "SPM"? Можно, но опять-таки из области загрузчика и только страницами. Если надо изменить 1 байт, то придётся считать страницу, изменить данные, а потом записать назад. При этом не забыть посчитать расположение нужного байта в пределах страницы и номер самой страницы. А ещё у Flash ресурс в 10 раз меньше по сравнению с внутренней EEPROM... Изменено 29 марта, 2010 пользователем МП41 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
koT-34 0 29 марта, 2010 Опубликовано 29 марта, 2010 (изменено) · Жалоба Смотрите файл boot.h Естественно, что процедуры записи должны быть расположены в области загрузчика (это - Ваша обязанность). т.е. так: 1) BOOTLOADER_SECTION void boot_program_page (uint32_t page, uint8_t *buf) { ... } BOOTLOADER_SECTION void boot_program_byte (uint32_t page, uint8_t byte, uint8_t *buf) { ... } и т.д. 2) В makefile надо пропиcать в параметрах линкера адрес секции: -Wl,--section-start=.bootloader=0x7E00 ? Изменено 29 марта, 2010 пользователем koT-34 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
koT-34 0 8 апреля, 2010 Опубликовано 8 апреля, 2010 · Жалоба Всем спасибо за помощь. Флеш память прекрасно пишется если: 1. Разместить функци работы с ней в области загрузчика: #define BOOTLOADER_SECTION __attribute__ ((section (".bootloader"))) BOOTLOADER_SECTION void boot_program_page (uint32_t page, uint8_t *buf) {} 2. В makefile надо пропиcать в параметрах линкера адрес секции загрузчика: -Wl,--section-start=.bootloader=0x7E00 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vlx 0 17 мая, 2011 Опубликовано 17 мая, 2011 · Жалоба Добрый день! Чтобы не плодить топики, задам вопрос здесь. Не получается записать данные в Flash. Код следующий: #include <avr/io.h> #include <avr/pgmspace.h> #include <avr/boot.h> #include <inttypes.h> #include <avr/interrupt.h> void BOOTLOADER_SECTION boot_program_page (uint32_t page, uint8_t *buf); uint8_t buffer[128] = "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"; int main() { boot_program_page(0x30, buffer); while(1) { } return 0; } void BOOTLOADER_SECTION boot_program_page(uint32_t page, uint8_t *buf) { uint16_t i; uint8_t sreg; // Disable interrupts. sreg = SREG; cli(); eeprom_busy_wait (); boot_page_erase (page); boot_spm_busy_wait (); // Wait until the memory is erased. for (i=0; i<SPM_PAGESIZE; i+=2) { // Set up little-endian word. uint16_t w = *buf++; w += (*buf++) << 8; boot_page_fill (page + i, w); } boot_page_write (page); // Store buffer in flash page. boot_spm_busy_wait(); // Wait until the memory is written. // Reenable RWW-section again. We need this if we want to jump back // to the application after bootloading. boot_rww_enable (); // Re-enable interrupts (if they were ever enabled). SREG = sreg; } контроллер ATmega16L; функция boot_program_page скопирована из документации к avr-libc; линкеру задано -Wl,-section-start=.bootloader=0x1F80; по hex-файлу видно, что код размещается в нужной области памяти. В считанной прошивке никаких изменений не наблюдается... Подскажите, пожалуйста, чего ему не хватает? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NullPointer 0 17 мая, 2011 Опубликовано 17 мая, 2011 · Жалоба Не получается записать данные в Flash. //... контроллер ATmega16L; //.. линкеру задано -Wl,-section-start=.bootloader=0x1F80; 0x1F80 - это в словах (WORD, 2 байта). Здесь указать необходимо в байтах, т.е. на два умножить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vlx 0 17 мая, 2011 Опубликовано 17 мая, 2011 · Жалоба Премного благодарен, всё заработало. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jackkum 0 20 сентября, 2011 Опубликовано 20 сентября, 2011 (изменено) · Жалоба Помогите пожалуйста, устал уже 2 дня бродить по инету ничего не могу найти :( Пишу бутлоадер на AVR Studio 5.0 для меги88 хекс генериться нормально, начинается с адреса 0x0E00 запускается тоже нормально, но при записи во флеш ничего не происходит, скачиваю всю флешь, загрузчик есть а новой прошивки нет, должна запасаться из еепрома внешнего по i2c во флеш с адреса 0x0000 #define F_CPU 14745600 #define BOOTSIZE 512 #define APP_END (FLASHEND - (BOOTSIZE * 2)) #include <avr/io.h> #include <avr/boot.h> #include <avr/wdt.h> #include <avr/pgmspace.h> #include <util/delay.h> #include <stdio.h> #include <string.h> #include "i2c_eeprom.h" uint8_t gBuffer[32]; uint16_t get_hex(uint8_t b){ uint16_t hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}, x = 0; for(x = 0; x < sizeof(hex); x++){ if(b == hex[x]){ return x; } } return 0; } void eraseFlash(void) { // erase only main section (bootloader protection) uint32_t addr = 0; boot_spm_busy_wait(); while (APP_END > addr) { boot_page_erase(addr); // Perform page erase boot_spm_busy_wait(); // Wait until the memory is erased. addr += 32; } boot_rww_enable(); } void boot_program_page(uint32_t page){ uint16_t w; uint8_t i; eeprom_busy_wait(); boot_page_erase(page); boot_spm_busy_wait(); for (i=0; i<32; i+=2){ w = (gBuffer[i]) + ((gBuffer[i+1]) << 8); boot_page_fill(page+i, w); } boot_page_write(page); boot_spm_busy_wait(); } void boot(void){ uint16_t i = 0;//, x = 0, size = 0, type = 0, CS = 0, byte = 0; uint32_t /*e_addr = 32000, */addr = 0; //uint16_t line[43]; //eraseFlash(); /* do { line[0] = 0; for(i=0; i<40; i++){ asm("sei"); byte = eeGetc(e_addr++); RS_putc(byte); asm("cli"); line[i] = byte; } size = get_hex(line[1]); size = (size<<8)|get_hex(line[2]); addr = get_hex(line[3]); addr = (addr<<8)|get_hex(line[4]); addr = (addr<<8)|get_hex(line[5]); addr = (addr<<8)|get_hex(line[6]); type = get_hex(line[7]); type = (type<<8)|get_hex(line[8]); if(type!=0x00){ break; } for(i = 0, x = 9; i < 32; i++, x++){ gBuffer[i] = get_hex(line[x]); } CS = get_hex(line[41]); CS = (CS<<8)|get_hex(line[42]); e_addr++; e_addr++; PORTC ^= (1<<3); writeFlashPage(addr, SPM_PAGESIZE); addr += SPM_PAGESIZE; } while(addr < 0x0E00); */ uint8_t buff[32] = "19C020C01FC01EC01DC01CC01BC01AC0"; for(i=0; i<(sizeof(buff)); i++){ uint8_t s = buff[i]; gBuffer[i] = get_hex(s); } boot_program_page(addr); boot_spm_busy_wait(); boot_rww_enable(); } int main(void) { DDRB = 0xFF; DDRC = 0xFF; eeInit(); //if(get_boarch()){ asm("cli"); boot(); //} //_delay_ms(3000); //asm("rjmp 0x0000"); while(1) { do{ PORTC ^= (1<<3); _delay_ms(500); }while(1); } } уже пробую хотябы просто строку записать не выходит :( Изменено 20 сентября, 2011 пользователем jackkum Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 117 20 сентября, 2011 Опубликовано 20 сентября, 2011 · Жалоба Помогите пожалуйста, устал уже 2 дня бродить по инету ничего не могу найти :(Читайте внимательно ветку, в которую написали. Буквально пару сообщений до вашего: 0x1F80 - это в словах (WORD, 2 байта). Здесь указать необходимо в байтах, т.е. на два умножить. для меги88 хекс генериться нормально, начинается с адреса 0x0E00 В вашем случае "0xE00 - это в словах (WORD, 2 байта). Здесь указать необходимо в байтах, т.е. на два умножить.". А запускается нормально потому что приложения нет и процессор исполняя код 0xFFFF добегает до начала вашего кода. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Палыч 5 20 сентября, 2011 Опубликовано 20 сентября, 2011 · Жалоба уже пробую хотябы просто строку записать не выходит :( Вы бы хотя бы пример boot_test посмотрели, который приведен в файле boot.h Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jackkum 0 20 сентября, 2011 Опубликовано 20 сентября, 2011 · Жалоба :krapula: Блин ведь чувствовал что где-то на поверхности :) Спасибо огромное! :) Работает :08: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 20 сентября, 2011 Опубликовано 20 сентября, 2011 · Жалоба uint16_t get_hex(uint8_t b){ uint16_t hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}, x = 0; for(x = 0; x < sizeof(hex); x++){ if(b == hex[x]){ return x; } } return 0; } Это жесть! Так не проще? uint16_t get_hex(uint8_t b){return b<'A'?b-'0':b-'A'+10;} Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться