Jump to content

    

Редактирование данных в памяти программ.

Добрый день.

 

Пишу на С, компилятор 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]'

Share this post


Link to post
Share on other sites
Возможно ли средствами С редактировать данные записанные во флеш память МК ?

 

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

 

Из application section нельзя.

Но можно сделать из boot section.

Но там всё не так просто....

Почитайте про бутлоадер в документации на МК.

 

А чем вас не устраивает хранение данных в eeprom которую можно модифицировать из application section?

Edited by mempfis_

Share this post


Link to post
Share on other sites
Возможно ли средствами С редактировать данные записанные во флеш память МК ?

Смотрите файл boot.h

Естественно, что процедуры записи должны быть расположены в области загрузчика (это - Ваша обязанность).

Share this post


Link to post
Share on other sites
А чем вас не устраивает хранение данных в eeprom которую можно модифицировать из application section?

 

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

 

Я правильно понимаю что во флеш можно писать на ассемблере, с помщью команды "SPM"?

Share this post


Link to post
Share on other sites
Я правильно понимаю что во флеш можно писать на ассемблере, с помщью команды "SPM"?

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

Edited by МП41

Share this post


Link to post
Share on other sites
Смотрите файл 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

?

Edited by koT-34

Share this post


Link to post
Share on other sites

Всем спасибо за помощь.

 

Флеш память прекрасно пишется если:

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

Share this post


Link to post
Share on other sites

Добрый день!

Чтобы не плодить топики, задам вопрос здесь.

Не получается записать данные в 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-файлу видно, что код размещается в нужной области памяти.

В считанной прошивке никаких изменений не наблюдается...

Подскажите, пожалуйста, чего ему не хватает?

Share this post


Link to post
Share on other sites
Не получается записать данные в Flash.

//...

контроллер ATmega16L;

//..

линкеру задано -Wl,-section-start=.bootloader=0x1F80;

0x1F80 - это в словах (WORD, 2 байта). Здесь указать необходимо в байтах, т.е. на два умножить.

Share this post


Link to post
Share on other sites

Премного благодарен, всё заработало.

Share this post


Link to post
Share on other sites

Помогите пожалуйста, устал уже 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);
        
        
    }
}

 

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

Edited by jackkum

Share this post


Link to post
Share on other sites
Помогите пожалуйста, устал уже 2 дня бродить по инету ничего не могу найти :(
Читайте внимательно ветку, в которую написали. Буквально пару сообщений до вашего:

0x1F80 - это в словах (WORD, 2 байта). Здесь указать необходимо в байтах, т.е. на два умножить.

 

для меги88 хекс генериться нормально, начинается с адреса 0x0E00

В вашем случае "0xE00 - это в словах (WORD, 2 байта). Здесь указать необходимо в байтах, т.е. на два умножить.". А запускается нормально потому что приложения нет и процессор исполняя код 0xFFFF добегает до начала вашего кода.

Share this post


Link to post
Share on other sites
уже пробую хотябы просто строку записать не выходит :(

Вы бы хотя бы пример boot_test посмотрели, который приведен в файле boot.h

Share this post


Link to post
Share on other sites

:krapula: Блин ведь чувствовал что где-то на поверхности :)

Спасибо огромное! :) Работает :08:

Share this post


Link to post
Share on other sites
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;}

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this