Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: запись в EPCS из ниоса
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Системы на ПЛИС - System on a Programmable Chip (SoPC)
torik
Надо иногда записывать несколько байт в EPCS.

В EPCS64 128 секторов. Хочу последний сектор для данных отвести.

Пишу код:

Код
#include "epcs_commands.h"


unsigned char * epcs_dst;
unsigned int epcs_buff[4];
epcs_dst = &epcs_buff[0];
fprintf(stdout, "\nepcs id = %x", epcs_read_device_id(EPCS_FLASH_CONTROLLER_BASE + EPCS_FLASH_CONTROLLER_REGISTER_OFFSET));
epcs_read_buffer(EPCS_FLASH_CONTROLLER_BASE, 65536*127, epcs_dst, 16);
    fprintf(stdout, "\n1 = %x", epcs_buff[0]);


На функции чтения тупо виснет.

Что интересно, если написать:

Код
fprintf(stdout, "\nepcs id = %x", epcs_read_device_id(EPCS_FLASH_CONTROLLER_BASE));


Тоже виснет.




Где примерчик можно посмотреть? Чё ему не нравится? Всякие галки small в bsp сняты...
















Попробовал везде использовать EPCS_FLASH_CONTROLLER_BASE + EPCS_FLASH_CONTROLLER_REGISTER_OFFSET
Зависать перестало.
Теперь добавляем запись:
Код
epcs_write_enable(EPCS_FLASH_CONTROLLER_BASE + EPCS_FLASH_CONTROLLER_REGISTER_OFFSET);
epcs_sector_erase(EPCS_FLASH_CONTROLLER_BASE + EPCS_FLASH_CONTROLLER_REGISTER_OFFSET, 127);
res = epcs_write_buffer(EPCS_FLASH_CONTROLLER_BASE + EPCS_FLASH_CONTROLLER_REGISTER_OFFSET, 65536*127, epcs_src, 16);

После сброса питания, выяснилось, что прошивка накрылась. Куда-то не туда стер и записал...
Stewart Little
А девайс открывать Вы не забываете?
torik
А надо ли? Вот функции "epcs_commands.h":
Код
alt_u8 epcs_read_device_id(alt_u32 base);
alt_u8 epcs_read_electronic_signature(alt_u32 base);
alt_u8 epcs_read_status_register(alt_u32 base);
void epcs_sector_erase(alt_u32 base, alt_u32 offset);
alt_32 epcs_read_buffer(alt_u32 base, int offset, alt_u8 *dest_addr, int length);
void epcs_write_enable(alt_u32 base);
void epcs_write_status_register(alt_u32 base, alt_u8 value);
alt_32 epcs_write_buffer(alt_u32 base, int offset, const alt_u8 *src_addr, int length);


А открыть файл - это уже "altera_avalon_epcs_flash_controller.h" и другие функции.


В функцию epcs_sector_erase надо указывать только номер сектора, например 127?

Что-то и с открыванием файлов не получается:
Код
    alt_flash_fd    *p_epcs_fd;
    flash_region    *p_epcs_reg_info;
    int             num_epcs_regs;
    unsigned int epcs_buff[4];

    p_epcs_fd = alt_flash_open_dev("/dev/epcs_flash_controller");
    alt_epcs_flash_get_info(p_epcs_fd, &(p_epcs_reg_info), &(num_epcs_regs));
    alt_epcs_flash_read(p_epcs_fd, 65536*126, (void*)epcs_buff, 16);
    alt_flash_close_dev(p_epcs_fd);


А запись так:
Код
    p_epcs_fd = alt_flash_open_dev("/dev/epcs_flash_controller");
    alt_epcs_flash_erase_block(p_epcs_fd, 126);
    alt_epcs_flash_write_block(p_epcs_fd, 126, 0, (void*)epcs_buff, 16);
    alt_flash_close_dev(p_epcs_fd);


Оно конечно не виснет. Однако после записи, вычитываю все те же ffffffff. И начинает глючить вся программа вообще. Что-то эта запись во влеш где-то не дружит с fprintf.

Stewart Little
Какое значение возвращается из alt_flash_open_dev? Сделайте проверку на NULL.
sergtsa
и не забывайте , в EPCS _xxx ограниченное число записей/стираний 100 000 раз.
Stewart Little
upd:
Цитата(torik @ Aug 8 2011, 17:37) *
А надо ли? Вот функции "epcs_commands.h":

Вы уж определитесь, с чем хотите работать - с fprintf или с epcs_command.h.
И посмотрите вот эту тему: http://electronix.ru/forum/index.php?showt...st&p=955010

Цитата(sergtsa @ Aug 8 2011, 19:00) *
и не забывайте , в EPCS _xxx ограниченное число записей/стираний 100 000 раз.

Не вводите в заблуждение!!!
Цитата из DS: "Re-programmable memory with more than 100,000 erase/program cycles" (см. http://www.altera.com/literature/hb/cfg/cyc_c51014.pdf).
А насколько "more than", там не написано sm.gif
Т.о., имеет смысл говорить, что гарантированное кол-во циклов записи-стирания для EPCS не менее 100000 (и это во всем диапазоне температур и напряжений питания).
vadimuzzz
примеры чтения/записи с использованием epcs_commands.h
Код
void    RdEPCS_Set()
{
    epcs_read_buffer(EPCS_CONTROLLER_BASE+EPCS_CONTROLLER_REGISTER_OFFSET,
    EPCS_SET_OFFS, EPCS_buffer, EPCS_BUF_SIZE);
}
//---------------------------------------------------------------------------------------------
void    WrEPCS_Set()
{
    epcs_sector_erase(EPCS_CONTROLLER_BASE+EPCS_CONTROLLER_REGISTER_OFFSET,EPCS_SET_OFFS);
    epcs_write_buffer(EPCS_CONTROLLER_BASE+EPCS_CONTROLLER_REGISTER_OFFSET,
                              EPCS_SET_OFFS, EPCS_buffer, EPCS_BUF_SIZE);
}

EPCS_CONTROLLER_REGISTER_OFFSET - смещение контроллера SPI, который встроен в компонент EPCS_CONTROLLER (см. system.h)
EPCS_SET_OFFS - смещение на флешке в байтах, а не в номерах страниц
остальное - указатель на буфер и его размер
sergtsa
Цитата(Stewart Little @ Aug 8 2011, 19:10) *
upd:

Не вводите в заблуждение!!!
Цитата из DS: "Re-programmable memory with more than 100,000 erase/program cycles" (см. http://www.altera.com/literature/hb/cfg/cyc_c51014.pdf).
А насколько "more than", там не написано sm.gif
Т.о., имеет смысл говорить, что гарантированное кол-во циклов записи-стирания для EPCS не менее 100000 (и это во всем диапазоне температур и напряжений питания).

не хотел никого ввести в заблуждение.
я так и написал )) 100 000 записей / стираний. (это то на что можно рассчитывать, а расчитывать на "более чем 100 000" я бы не стал)
при хранении в EPCS перезаписываемых данных, просто не надо забывать про это , чтоб не убить частыми записями.
torik
Цитата
Вы уж определитесь, с чем хотите работать - с fprintf или с epcs_command.h.

Не понял связи. Не вижу где написано, что нельзя одновременно работать с fprintf и с epcs_command.h. Чё-то упустил?

Переделал все по-другому. Во-первых, в этой теме
http://electronix.ru/forum/index.php?showt...l=alt_flash_dev
вычитал про
Код
#define ALT_USE_EPCS_FLASH
#include "altera_avalon_epcs_flash_controller.h"

в system_init.c
Это неудобно, т.к. после перегенерации bsp приходится по-новой добавлять эту строку. Но если снять галку reduced_devices_drivers, то глюки возвращаются.

Чтение делаю так:
Код
alt_flash_fd    *fd;
unsigned int epcs_buff[4];
fd = alt_flash_open_dev("/dev/epcs_flash_controller");
if (fd != NULL) {
    printf ("\nopen OK");
    alt_epcs_flash_read(fd, 65536*126, (void*)epcs_buff, 16);
}
alt_flash_close_dev(fd);


А запись делаю так:
Код
fd = alt_flash_open_dev("/dev/epcs_flash_controller");
if (fd != NULL) {
   alt_epcs_flash_erase_block(fd, 126);
   alt_epcs_flash_write_block(fd, 0, 65536*126, (void*)epcs_buff, 16);
}
alt_flash_close_dev(fd);

Вот тут особенность, которую вычитал где-то на альтеровском форуме.
при стирании указывается номер сектора. Взял предпоследний для EPCS64. В функции запими, по идее, второй аргумнт должен соответсвовать номеру сектора, а третий смещению внутри него. Так вот, второй аргумент игнорируется, а в третьем нужно указывать адрес целиком.
Сейчас все работает. И даже fprintf не глючит.
Кто ошибки видит?


vadimuzzz
Цитата(torik @ Aug 9 2011, 11:50) *
Взял предпоследний для EPCS64. В функции запими, по идее, второй аргумнт должен соответсвовать номеру сектора, а третий смещению внутри него. Так вот, второй аргумент игнорируется, а в третьем нужно указывать адрес целиком.


Код
/* Write, assuming that someone has kindly erased the appropriate
* sector(s).
* Note: "block_offset" is the base of the current erase block.
* "data_offset" is the absolute address (from the 0-base of this
* device's memory) of the beginning of the write-destination.
* This device has no need for "block_offset", but it's included for
* function type compatibility.
*/
int alt_epcs_flash_write_block
все адреса абсолютные.
а вариант, что я выше предлагал чем не нравится? памяти, кстати, меньше будет жрать. и с reduced device drivers будет работать
torik
Код
а вариант, что я выше предлагал чем не нравится? памяти, кстати, меньше будет жрать. и с reduced device drivers будет работать

Что-то он у меня глючил. Но проверю еще разок.
Код
alt_epcs_flash_erase_block(fd, 126)
- рушит прошивку.
оставил только
Код
alt_epcs_flash_write(fd, 65536*126, (void*)epcs_buff, 16);

Похоже что в этой функции автоматически стирается нужный блок.
vadimuzzz
Цитата(torik @ Aug 9 2011, 13:03) *
Код
alt_epcs_flash_erase_block(fd, 126)
- рушит прошивку.

естественно, стирается нулевой сектор. я же писал, все адреса в байтах
torik
Цитата
а вариант, что я выше предлагал чем не нравится? памяти, кстати, меньше будет жрать. и с reduced device drivers будет работать

Попробовал. Что-то не записывает нифига то что надо:
Код
epcs_sector_erase(EPCS_FLASH_CONTROLLER_BASE+EPCS_FLASH_CONTROLLER_REGISTER_OFFSET, 65536*126);
epcs_write_buffer(    EPCS_FLASH_CONTROLLER_BASE+EPCS_FLASH_CONTROLLER_REGISTER_OFFSET, 65536*126,
        (void*)epcs_buff, 16);

epcs_read_buffer(EPCS_FLASH_CONTROLLER_BASE+EPCS_FLASH_CONTROLLER_REGISTER_OFFSET, 65536*126, (void*)epcs_buff, 16);

Опять небось какой-нибудь флеш_инит нужно делать или еще чего забыл?



Stewart Little
Цитата(torik @ Aug 9 2011, 08:50) *
Не понял связи. Не вижу где написано, что нельзя одновременно работать с fprintf и с epcs_command.h. Чё-то упустил?

Упустил, упустил.
Если Вы собираетесь писать в файл (то бишь в девайс) - fprintf - то этот файл нужно как минимум открыть.
( bb-offtopic.gif навевает аналогию - Рецепт приготовления кролика: пункт 1. Поймайте кролика...).

Если собираетесь работать с EPCS'кой на низком уровне (с использованием функций из epcs_command.h) - как предлагаем уважаемый vadimuzzz, то забудьте про форматированный вывод.

А смешивать первое со вторым в одном и том же приложении - это прямой путь к выносу мозга sm.gif
vadimuzzz
Цитата(torik @ Aug 9 2011, 13:52) *
Опять небось какой-нибудь флеш_инит нужно делать или еще чего забыл?

скорее epcs_write_enable.
вот только что проверил:
CODE

unsigned char e_buf[16];
epcs_write_enable(EPCS_FLASH_CONTROLLER_0_BASE+EPCS_FLASH_CONTROLLER_0_REGISTER_
OFFSET);
epcs_sector_erase(EPCS_FLASH_CONTROLLER_0_BASE+EPCS_FLASH_CONTROLLER_0_REGISTER_
OFFSET,EPCS_SET_OFFS);
epcs_read_buffer(EPCS_FLASH_CONTROLLER_0_BASE+EPCS_FLASH_CONTROLLER_0_REGISTER_O
FFSET,EPCS_SET_OFFS,e_buf,16);
for(t=0;t<16;t++)
alt_printf("e_buf[%x]=%x\n",t,e_buf[t]);
for(t=0;t<16;t++)
e_buf[t] = t;
epcs_write_buffer(EPCS_FLASH_CONTROLLER_0_BASE+EPCS_FLASH_CONTROLLER_0_REGISTER_
OFFSET,EPCS_SET_OFFS,e_buf,16);
for(t=0;t<16;t++)
alt_printf("e_buf[%x]=%x\n",t,e_buf[t]);
for(t=0;t<16;t++)
e_buf[t]=0;
for(t=0;t<16;t++)
alt_printf("e_buf[%x]=%x\n",t,e_buf[t]);
epcs_read_buffer(EPCS_FLASH_CONTROLLER_0_BASE+EPCS_FLASH_CONTROLLER_0_REGISTER_O
FFSET,EPCS_SET_OFFS,e_buf,16);
for(t=0;t<16;t++)
alt_printf("e_buf[%x]=%x\n",t,e_buf[t]);

выхлоп:
CODE
e_buf[0]=ff
e_buf[1]=ff
e_buf[2]=ff
e_buf[3]=ff
e_buf[4]=ff
e_buf[5]=ff
e_buf[6]=ff
e_buf[7]=ff
e_buf[8]=ff
e_buf[9]=ff
e_buf[a]=ff
e_buf[b]=ff
e_buf[c]=ff
e_buf[d]=ff
e_buf[e]=ff
e_buf[f]=ff
e_buf[0]=0
e_buf[1]=1
e_buf[2]=2
e_buf[3]=3
e_buf[4]=4
e_buf[5]=5
e_buf[6]=6
e_buf[7]=7
e_buf[8]=8
e_buf[9]=9
e_buf[a]=a
e_buf[b]=b
e_buf[c]=c
e_buf[d]=d
e_buf[e]=e
e_buf[f]=f
e_buf[0]=0
e_buf[1]=0
e_buf[2]=0
e_buf[3]=0
e_buf[4]=0
e_buf[5]=0
e_buf[6]=0
e_buf[7]=0
e_buf[8]=0
e_buf[9]=0
e_buf[a]=0
e_buf[b]=0
e_buf[c]=0
e_buf[d]=0
e_buf[e]=0
e_buf[f]=0
e_buf[0]=0
e_buf[1]=1
e_buf[2]=2
e_buf[3]=3
e_buf[4]=4
e_buf[5]=5
e_buf[6]=6
e_buf[7]=7
e_buf[8]=8
e_buf[9]=9
e_buf[a]=a
e_buf[b]=b
e_buf[c]=c
e_buf[d]=d
e_buf[e]=e
e_buf[f]=f
torik
Цитата
скорее epcs_write_enable

Точно, вот только замечание Stewart Little по поводу fprintf напрягает.
А разве закрытие файла alt_flash_close_dev(fd); пепред форматным выводом не решает проблему?
vadimuzzz
я, откровенно говоря, вообще не понимаю, почему вы решили использовать форматированный вывод. он предназначен для символьных устройств (поток символов), а флешка - типичное блочное устройство (оперирует блоками), с ними принято работать через read/write. вот и в HAL упоминаются следующие функции для работы с flash:
Цитата
alt_flash_open_dev()
alt_erase_flash_block()
alt_flash_close_dev()
alt_get_flash_info()
alt_read_flash()
alt_write_flash()
alt_write_flash_block()
torik
Причем тут флешка и форматный вывод. Форматный вывод fprintf используется только для отладки, для вывода всякой фигни в консоль ниоса. Т.е. только через stdout.

И к флешке не имеет отношения
Stewart Little
Цитата(torik @ Aug 9 2011, 15:51) *
Причем тут флешка и форматный вывод. Форматный вывод fprintf используется только для отладки, для вывода всякой фигни в консоль ниоса. Т.е. только через stdout.

Да, похоже я ступил. Приношу свои извинения. laughing.gif
Ну а Вы постарайтесь писать более удобочитаемый код.
vadimuzzz
Цитата(torik @ Aug 9 2011, 18:51) *
И к флешке не имеет отношения

простите, а в чем вопрос-то? sm.gif
torik
Цитата
Ну а Вы постарайтесь писать более удобочитаемый код.

Ок.

Цитата
простите, а в чем вопрос-то?


Пожалуй, этот вопрос исчерпан на данный момент. Большое спасибо.

Reanimator++
Код
#include "flash.h"
#include "sys/alt_flash.h"
#include "string.h"

void flash_test (void)
{
    alt_flash_fd * flash_descriptor;
    int ret_code, i;
    alt_u8 source[100] = {0,1,2,3,4,5,6,7,8,9};
    alt_u8 dest[100];


    flash_descriptor = alt_flash_open_dev ("/dev/epcs_flash_controller");
    if (flash_descriptor != NULL)
    {
        printf ("Flash open success!\n");

        ret_code = alt_read_flash (flash_descriptor, 0x70000, dest, 10);
        if (ret_code == 0)
        {
            printf ("read success\n");
            for (i=0; i<10; i++)
            {
                printf ("%d - %d\n", dest[i], source[i]);

            }

            ret_code = alt_write_flash (flash_descriptor, 0x70000, source, 10);
            if (ret_code == 0)
                printf ("write success\n");
            else
                printf ("write fail \n");

        }
        else printf ("read fail\n");

        alt_flash_close_dev (flash_descriptor);
    }
    else printf ("Can't open flash!\n");

}


int flash_read (alt_u8 * buf, alt_u32 addr, alt_u32 length)
{
    alt_flash_fd * flash_descriptor;
    int ret_code;
//    alt_u8 tempbuf[40];

    flash_descriptor = alt_flash_open_dev ("/dev/epcs_flash_controller");
    if (flash_descriptor != NULL)
    {
        ret_code = alt_read_flash (flash_descriptor, addr, buf, length);
        if (ret_code == 0)
        {
            alt_flash_close_dev (flash_descriptor);
            return (1);
        }
        else return (0);
        alt_flash_close_dev (flash_descriptor);
    }
    else return (0);
}

У меня в проекте что-то такое было для теста работы с флешой..
wpost
описание структуры
Код
struct EPCS_STRUCT
{
    char *NAME;                           // name EPCS
    alt_flash_fd *p_epcs_fd;             // pointer to EPCS
    flash_region *p_epcs_reg_info;       // Regs info    
    int num_epcs_regs;                   // num regs
    int type;
    alt_u8 sid;
};


функция инициализации
Код
int init_epsc(struct EPCS_STRUCT *EPCS)
{
EPCS->sid =0xff;
EPCS->p_epcs_fd=alt_flash_open_dev(EPCS->NAME); // Get pointer to flash info structure

alt_epcs_flash_get_info(EPCS->p_epcs_fd, &EPCS->p_epcs_reg_info, &EPCS->num_epcs_regs); // Verify flash details

switch (EPCS->p_epcs_reg_info->region_size*EPCS->num_epcs_regs)
    {
        case 131072   : /*printf("Detected EPCS1\n");*/ {EPCS->type =1;EPCS->sid =0x10; break;}
        case 524288   : /*printf("Detected EPCS4\n");*/ {EPCS->type =4;EPCS->sid =0x12; break;}
        case 2097152  : /*printf("Detected EPCS16\n");*/ {EPCS->type =16;EPCS->sid =0x14; break;}
        case 8388608  : /*printf("Detected EPCS64\n");*/ {EPCS->type =64;EPCS->sid =0x16; break;}
        case 16777216 : /*printf("Detected EPCS128\n");*/ {EPCS->type =128;EPCS->sid =0x18; break;}
        EPCS->sid =0xff;return(1);
    }

return(0);
}


Код
int EPCS_READ(struct EPCS_STRUCT *EPCS, int offset, alt_u8 *buf, int len)
{
    int res;

    res = alt_epcs_flash_read(EPCS->p_epcs_fd, offset, buf,len);

    return(res);
}

int EPCS_FULL_ERASE(struct EPCS_STRUCT *EPCS)
{
    int res;
    int i;
    int j;
    alt_u8 bar;

    res = 0;
    switch (EPCS->type)
        {
            case 1   :  for (i=0;i<4;i++)
                                            {    res = res + alt_epcs_flash_erase_block(EPCS->p_epcs_fd, ((i*8)<<12)&(0xff000));
                                                for (j=0;j<1000;j++);
                                            }    break;
            case 4   :  for (i=0;i<8;i++)     {    res = res + alt_epcs_flash_erase_block(EPCS->p_epcs_fd, i*0x010000);
                                                if (i==4)
                                                    for (j=0;j<100000;j++);
                                                for (j=0;j<1000;j++);
                                            }    break;
            case 16  :  for (i=0;i<32;i++)     {    res = res + alt_epcs_flash_erase_block(EPCS->p_epcs_fd, i*0x010000);
                                                if (i==15)
                                                    for (j=0;j<100000;j++);
                                                for (j=0;j<1000;j++);
                                            }    break;
            case 64  :  for (i=0;i<128;i++) {    res = res + alt_epcs_flash_erase_block(EPCS->p_epcs_fd, 0x010000*i);
                                                if (i==63)
                                                    for (j=0;j<100000;j++);
                                            }     break;
            case 128 :  for (i=0;i<64;i++)     {    res = res + alt_epcs_flash_erase_block(EPCS->p_epcs_fd, ((i*4)<<16)&(0xff0000));
                                                bar=1.5625*(i+1);
                                                if (i==10)
                                                    for (j=0;j<100000;j++);
                                                if (i==20)
                                                    for (j=0;j<100000;j++);
                                                if (i==30)
                                                    for (j=0;j<100000;j++);
                                                if (i==40)
                                                    for (j=0;j<100000;j++);
                                                for (j=0;j<1000;j++);
                                            }    break;
                        res = 1;break;
        }

      
    return(res);
}



int EPCS_WRITE(struct EPCS_STRUCT *EPCS,  alt_u32 PTR, int len, alt_u8 *buf)
{
    int res;
   // len <= 256!!!

    res = alt_epcs_flash_write_block(EPCS->p_epcs_fd,0, PTR,
                                          buf,
                                              len);
    return(res);
}



Код
    // инициализация epcs
    EPCS.NAME = EPCNAME;
    if (init_epsc(&EPCS)!= 0)
    printf("EPCS ID %x\n",EPCS.sid);

// ну и дальше пошли читать, стирать, писать....
torik
Читабельно. Спасибо.

Перед записью, кстати, нет необходимости стирать записываемый блок (в alt_epcs_flash_write_block это уже предусмотрено)? Вроде не стираю и все пишется нормально.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.