|
|
  |
Редактирование данных в памяти программ. |
|
|
|
Mar 29 2010, 10:25
|
Группа: Участник
Сообщений: 6
Регистрация: 20-03-06
Пользователь №: 15 391

|
Добрый день. Пишу на С, компилятор 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]'
|
|
|
|
|
Mar 29 2010, 10:43
|

Профессионал
    
Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409

|
Цитата(koT-34 @ Mar 29 2010, 13:25)  Возможно ли средствами С редактировать данные записанные во флеш память МК ?
Приведенный способ естественно не работает: error: assignment of read-only location 'mydata[0]' Из application section нельзя. Но можно сделать из boot section. Но там всё не так просто.... Почитайте про бутлоадер в документации на МК. А чем вас не устраивает хранение данных в eeprom которую можно модифицировать из application section?
Сообщение отредактировал mempfis_ - Mar 29 2010, 10:44
|
|
|
|
|
Mar 29 2010, 11:47
|
Группа: Участник
Сообщений: 6
Регистрация: 20-03-06
Пользователь №: 15 391

|
Цитата(mempfis_ @ Mar 29 2010, 14:43)  А чем вас не устраивает хранение данных в eeprom которую можно модифицировать из application section? В eeprom мало места. Я правильно понимаю что во флеш можно писать на ассемблере, с помщью команды "SPM"?
|
|
|
|
|
Mar 29 2010, 13:53
|
Группа: Участник
Сообщений: 6
Регистрация: 20-03-06
Пользователь №: 15 391

|
Цитата(Палыч @ Mar 29 2010, 14:44)  Смотрите файл 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 ?
Сообщение отредактировал koT-34 - Mar 29 2010, 13:54
|
|
|
|
|
Apr 8 2010, 09:19
|
Группа: Участник
Сообщений: 6
Регистрация: 20-03-06
Пользователь №: 15 391

|
Всем спасибо за помощь. Флеш память прекрасно пишется если: 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
|
|
|
|
|
May 17 2011, 10:44
|

Группа: Новичок
Сообщений: 7
Регистрация: 17-05-11
Из: Харьков
Пользователь №: 65 054

|
Добрый день! Чтобы не плодить топики, задам вопрос здесь. Не получается записать данные в Flash. Код следующий: CODE #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-файлу видно, что код размещается в нужной области памяти. В считанной прошивке никаких изменений не наблюдается... Подскажите, пожалуйста, чего ему не хватает?
|
|
|
|
|
May 17 2011, 11:31
|

Группа: Новичок
Сообщений: 7
Регистрация: 17-05-11
Из: Харьков
Пользователь №: 65 054

|
Премного благодарен, всё заработало.
|
|
|
|
|
Sep 20 2011, 07:23
|
Группа: Новичок
Сообщений: 2
Регистрация: 20-09-11
Пользователь №: 67 287

|
Помогите пожалуйста, устал уже 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); } } уже пробую хотябы просто строку записать не выходит
Сообщение отредактировал jackkum - Sep 20 2011, 07:25
|
|
|
|
|
Sep 20 2011, 07:57
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (jackkum @ Sep 20 2011, 10:23)  Помогите пожалуйста, устал уже 2 дня бродить по инету ничего не могу найти  Читайте внимательно ветку, в которую написали. Буквально пару сообщений до вашего: QUOTE (SysRq @ May 17 2011, 14:10)  0x1F80 - это в словах (WORD, 2 байта). Здесь указать необходимо в байтах, т.е. на два умножить. QUOTE (jackkum @ Sep 20 2011, 10:23)  для меги88 хекс генериться нормально, начинается с адреса 0x0E00 В вашем случае "0xE00 - это в словах (WORD, 2 байта). Здесь указать необходимо в байтах, т.е. на два умножить.". А запускается нормально потому что приложения нет и процессор исполняя код 0xFFFF добегает до начала вашего кода.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 20 2011, 08:16
|
Группа: Новичок
Сообщений: 2
Регистрация: 20-09-11
Пользователь №: 67 287

|
 Блин ведь чувствовал что где-то на поверхности  Спасибо огромное!  Работает
|
|
|
|
|
Sep 20 2011, 09:26
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Цитата(jackkum @ Sep 20 2011, 11:23)  Код 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;}
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|