Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Редактирование данных в памяти программ.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
koT-34
Добрый день.

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

Приведенный способ естественно не работает: error: assignment of read-only location 'mydata[0]'


Из application section нельзя.
Но можно сделать из boot section.
Но там всё не так просто....
Почитайте про бутлоадер в документации на МК.

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

Смотрите файл boot.h
Естественно, что процедуры записи должны быть расположены в области загрузчика (это - Ваша обязанность).
koT-34
Цитата(mempfis_ @ Mar 29 2010, 14:43) *
А чем вас не устраивает хранение данных в eeprom которую можно модифицировать из application section?


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

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

Можно, но опять-таки из области загрузчика и только страницами. Если надо изменить 1 байт, то придётся считать страницу, изменить данные, а потом записать назад. При этом не забыть посчитать расположение нужного байта в пределах страницы и номер самой страницы. А ещё у Flash ресурс в 10 раз меньше по сравнению с внутренней EEPROM...
koT-34
Цитата(Палыч @ 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
Всем спасибо за помощь.

Флеш память прекрасно пишется если:
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
Добрый день!
Чтобы не плодить топики, задам вопрос здесь.
Не получается записать данные в 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-файлу видно, что код размещается в нужной области памяти.
В считанной прошивке никаких изменений не наблюдается...
Подскажите, пожалуйста, чего ему не хватает?
SysRq
Цитата(vlx @ May 17 2011, 14:44) *
Не получается записать данные в Flash.
//...
контроллер ATmega16L;
//..
линкеру задано -Wl,-section-start=.bootloader=0x1F80;
0x1F80 - это в словах (WORD, 2 байта). Здесь указать необходимо в байтах, т.е. на два умножить.
vlx
Премного благодарен, всё заработало.
jackkum
Помогите пожалуйста, устал уже 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
Сергей Борщ
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 добегает до начала вашего кода.
Палыч
Цитата(jackkum @ Sep 20 2011, 11:23) *
уже пробую хотябы просто строку записать не выходит sad.gif

Вы бы хотя бы пример boot_test посмотрели, который приведен в файле boot.h
jackkum
krapula.gif Блин ведь чувствовал что где-то на поверхности sm.gif
Спасибо огромное! sm.gif Работает 08.gif
XVR
Цитата(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;}

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.