реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Редактирование данных в памяти программ.
koT-34
сообщение Mar 29 2010, 10:25
Сообщение #1





Группа: Участник
Сообщений: 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]'
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Mar 29 2010, 10:43
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
Палыч
сообщение Mar 29 2010, 10:44
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(koT-34 @ Mar 29 2010, 13:25) *
Возможно ли средствами С редактировать данные записанные во флеш память МК ?

Смотрите файл boot.h
Естественно, что процедуры записи должны быть расположены в области загрузчика (это - Ваша обязанность).
Go to the top of the page
 
+Quote Post
koT-34
сообщение Mar 29 2010, 11:47
Сообщение #4





Группа: Участник
Сообщений: 6
Регистрация: 20-03-06
Пользователь №: 15 391



Цитата(mempfis_ @ Mar 29 2010, 14:43) *
А чем вас не устраивает хранение данных в eeprom которую можно модифицировать из application section?


В eeprom мало места.

Я правильно понимаю что во флеш можно писать на ассемблере, с помщью команды "SPM"?
Go to the top of the page
 
+Quote Post
МП41
сообщение Mar 29 2010, 12:24
Сообщение #5


4 синих кубика
****

Группа: Участник
Сообщений: 526
Регистрация: 19-09-08
Из: полупроводника, металла и стекла
Пользователь №: 40 326



Цитата(koT-34 @ Mar 29 2010, 13:47) *
Я правильно понимаю что во флеш можно писать на ассемблере, с помщью команды "SPM"?

Можно, но опять-таки из области загрузчика и только страницами. Если надо изменить 1 байт, то придётся считать страницу, изменить данные, а потом записать назад. При этом не забыть посчитать расположение нужного байта в пределах страницы и номер самой страницы. А ещё у Flash ресурс в 10 раз меньше по сравнению с внутренней EEPROM...

Сообщение отредактировал МП41 - Mar 29 2010, 12:25


--------------------
p-n-p-p-n-p-n-n-p-n-p структура однако очень эффективна
Go to the top of the page
 
+Quote Post
koT-34
сообщение Mar 29 2010, 13:53
Сообщение #6





Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
koT-34
сообщение Apr 8 2010, 09:19
Сообщение #7





Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
vlx
сообщение May 17 2011, 10:44
Сообщение #8





Группа: Новичок
Сообщений: 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-файлу видно, что код размещается в нужной области памяти.
В считанной прошивке никаких изменений не наблюдается...
Подскажите, пожалуйста, чего ему не хватает?
Go to the top of the page
 
+Quote Post
SysRq
сообщение May 17 2011, 11:10
Сообщение #9


Чайник, 1 литр
****

Группа: Свой
Сообщений: 655
Регистрация: 17-05-06
Из: Moscow
Пользователь №: 17 168



Цитата(vlx @ May 17 2011, 14:44) *
Не получается записать данные в Flash.
//...
контроллер ATmega16L;
//..
линкеру задано -Wl,-section-start=.bootloader=0x1F80;
0x1F80 - это в словах (WORD, 2 байта). Здесь указать необходимо в байтах, т.е. на два умножить.
Go to the top of the page
 
+Quote Post
vlx
сообщение May 17 2011, 11:31
Сообщение #10





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



Премного благодарен, всё заработало.
Go to the top of the page
 
+Quote Post
jackkum
сообщение Sep 20 2011, 07:23
Сообщение #11





Группа: Новичок
Сообщений: 2
Регистрация: 20-09-11
Пользователь №: 67 287



Помогите пожалуйста, устал уже 2 дня бродить по инету ничего не могу найти sad.gif
Пишу бутлоадер на 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);
        
        
    }
}


уже пробую хотябы просто строку записать не выходит sad.gif

Сообщение отредактировал jackkum - Sep 20 2011, 07:25
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 20 2011, 07:57
Сообщение #12


Гуру
******

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



QUOTE (jackkum @ Sep 20 2011, 10:23) *
Помогите пожалуйста, устал уже 2 дня бродить по инету ничего не могу найти sad.gif
Читайте внимательно ветку, в которую написали. Буквально пару сообщений до вашего:
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)
Go to the top of the page
 
+Quote Post
Палыч
сообщение Sep 20 2011, 08:07
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(jackkum @ Sep 20 2011, 11:23) *
уже пробую хотябы просто строку записать не выходит sad.gif

Вы бы хотя бы пример boot_test посмотрели, который приведен в файле boot.h
Go to the top of the page
 
+Quote Post
jackkum
сообщение Sep 20 2011, 08:16
Сообщение #14





Группа: Новичок
Сообщений: 2
Регистрация: 20-09-11
Пользователь №: 67 287



krapula.gif Блин ведь чувствовал что где-то на поверхности sm.gif
Спасибо огромное! sm.gif Работает 08.gif
Go to the top of the page
 
+Quote Post
XVR
сообщение Sep 20 2011, 09:26
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 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;}

Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 31st July 2025 - 19:24
Рейтинг@Mail.ru


Страница сгенерированна за 0.01487 секунд с 7
ELECTRONIX ©2004-2016