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

 
 
> Зависание при попытке записи во Flash
mr.smart
сообщение Feb 8 2011, 20:43
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 28
Регистрация: 2-10-10
Пользователь №: 59 884



Вновь обращаюсь к вам с просьбой о помощи! Использую компилятор WinARM, процессор - AT91SAM7S256.
Есть функция записи во флеш:
CODE

//********************************************************************************
******
// Тут у нас все что касается записи во флеш
//********************************************************************************
******

extern void AT91F_Enable_Interrupt(void);
extern void AT91F_Disable_Interrupt(void);

#define RAMFUNC __attribute__ ((section (".ram_func")))

#define EFC_PAGE_SIZE 256
#define EFC_PAGE_COUNT 1024
#define EFC_PagesInTheLockRegion 64
#define EFC_PAGE_SIZE_UINT (EFC_PAGE_SIZE/4) // Количество unsigned int

unsigned long int RAMFUNC EFC_WritePage(unsigned long int adr, unsigned long int *pbuf) {
unsigned int *pflash;
unsigned int page;
unsigned int region;
unsigned int i;

pflash = (unsigned int *)adr;
page = (adr & 0x3FFFF)/EFC_PAGE_SIZE;
region = (page/EFC_PagesInTheLockRegion);

//Init
while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY)) ;
AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(100 <<16)) | AT91C_MC_FWS_1FWS ;
while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY)) ;

if (AT91C_BASE_MC->MC_FSR & (region << 16)) {
// lock set, clear it
AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(50 <<16)) | AT91C_MC_FWS_2FWS ;
AT91C_BASE_MC->MC_FCR = (0x5A << 24) | (region << 8 ) |AT91C_MC_FCMD_UNLOCK; //!!!проблемное место!!!
}

while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY)) ;

for (i = 0; i < EFC_PAGE_SIZE_UINT; i++)
*(pflash + i ) = *(pbuf + i); //!!!проблемное место!!!

AT91F_PIO_SetOutput( AT91C_BASE_PIOA, 0x400 ) ;
AT91C_BASE_MC->MC_FCR = (0x5A << 24) | (page << 8 ) |AT91C_MC_FCMD_START_PROG; //!!!проблемное место!!!
while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY)) ;

return 1;
}

void RAMFUNC EFCWrite(unsigned long int adr, unsigned char *pbuf, unsigned long int Len, unsigned long int NeedReset) {
unsigned long int l;
if (NeedReset) {
l=0;
}
l=0;
while (l<Len) {
EFC_WritePage(adr, (unsigned long int*)&(pbuf[l]));
l+=EFC_PAGE_SIZE;
adr+=EFC_PAGE_SIZE;
}
if (NeedReset) {
__asm("sub r0, r0,r0;");
__asm("bx r0;");
}
}



//********************************************************************************
******


В основной функции пишу:
Код
unsigned int buf1[1];
#define Tester 0x110001
buf1[1] = 1;
AT91F_Disable_Interrupt();
EFCWrite(Tester,(unsigned char*)buf1,4,0);
AT91F_Enable_Interrupt();


Т.е. прерывания перед записью я отключаю, у функции записи прописал атрибут вызова из RAM... Но при любом обращении ко флеш (в коде пометил как "проблемные места") процессор зависает.
В чем может быть причина?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
mr.smart
сообщение Feb 10 2011, 20:23
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 28
Регистрация: 2-10-10
Пользователь №: 59 884



Я видимо в Linker-script не описал область для ram_func.
Нашел на заморском сайте:
Цитата
Also, in your linker map you need to indicate where .ramsection resides:

.data : AT (_etext)
{
_data =3D . ;
KEEP(*(.vectram)) /* added by mthomas */=09
*(.data)
SORT(CONSTRUCTORS)
. =3D ALIGN(4);
*(.ramsection) /* here your ramsection will be located */
} >DATA
. =3D ALIGN(4);


Компилятор, как водится, сначала ругался на 3D ALIGN(4). Убрал слово 3D и компилятор стал выдавать "cannot find _data". В общем, я не понял что они имели ввиду.

Прописал следующим образом:
Код
MEMORY
{
  FLASH (r) : ORIGIN = 0x00100000, LENGTH = 0x00040000
  DATA (rw)  : ORIGIN = 0x00200000, LENGTH = 0x00010000
  STACK (rw) : ORIGIN = 0x00210000, LENGTH = 0x00000000
}

...

  .data : AT (_etext)
  {
    _data = .;
    *(.data)
    SORT(CONSTRUCTORS)
    *(.ramfunc)
  } >DATA
  . = ALIGN(4);

  _edata = .;
   PROVIDE (edata = .);


main.map мне сообщает:

Код
*(.ramfunc)
.ramfunc       0x00200008       0x14 main.o
                0x00200008                EFC_WritePage


Т.е. вроде бы функция находится в ram, но программа все-равно зависает после записи. Но если переподключить устройство, то окажется что во флеш все успешно записалось.
Меня смущает тег FLASH ( r ) (т.е. только чтение) в блоке MEMORY. Но если поставить rw, то компилятор пишет про какой-то overlap между секциями...

Поможите с советом!

Сообщение отредактировал mr.smart - Feb 10 2011, 22:22
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 11 2011, 07:52
Сообщение #3


Гуру
******

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



QUOTE (mr.smart @ Feb 10 2011, 22:23) *
CODE
  .data : AT (_etext)
  {
    _data = .;
    *(.data)
    SORT(CONSTRUCTORS)
    *(.ramfunc)
  } >DATA
  . = ALIGN(4);
1) Зачем конструкторы засовывать в ОЗУ?
2) входные секции лучше указывать как *(.data*), *(.ramfunc*) и т.д. - это позволит вам корректно линковать код, скомпилированный с опциями -ffunction-sections, -fdata-sections.
3) Какая у вас частота ядра? Правильно ли вы рассчитываете константу FMCN?
4) Почему вы пишите то AT91C_MC_FWS_1FWS то AT91C_MC_FWS_2FWS?
5) Переход на адрес 0 - это совсем не reset. Рекомендую собаку.
6) А запрещаете ли вы прерывания?

Выкиньте из проекта все лишнее, запакуйте в zip и прикрепите к сообщению - посмотрим. Не нравится мне ваш скрипт в части .data : AT (_etext). вот что у меня:
CODE
ENTRY(_start)
IRQ_STACK_SIZE = 0x100;
SYS_STACK_SIZE = 0x1800;

/* memory layout */
MEMORY
{
VECTORS (rx) : ORIGIN = 0x00100000, LENGTH = 0x40
ROM (rx) : ORIGIN = 0x00100040, LENGTH = 0x00001000 - 0x40
RAM (rwx) : ORIGIN = 0x00200000, LENGTH = 0x00004000
REMAPPED (rwx) : ORIGIN = 0x00000000, LENGTH = LENGTH(RAM)
}

SECTIONS
{
.vectors :
{
KEEP(*(.vectors))
} > REMAPPED AT > VECTORS

.text :
{
__ctors_start = .;
KEEP(SORT(*)(.ctors))
KEEP(SORT(*)(.init_array))
__ctors_end = .;
__dtors_start = .;
KEEP(SORT(*)(.dtors))
__dtors_end = .;

. = ALIGN(4);

*(.text*) /* code */

*(.rodata) /* read-only data (constants) */
*(.rodata*)

*(.glue_7)
*(.glue_7t)
} > ROM

. = ALIGN(4);
_etext = .;

/* .data section which is used for initialized data */
.data : /* place init values immediatly after .text section */
{
_data = .;
*(.ramfunc*)

*(.data*)

PROVIDE (_edata = .);
_data_image = LOADADDR(.data);

} > RAM AT > ROM

/* .bss section which is used for uninitialized data */
.bss: (NOLOAD) :
{
. = ALIGN(4);
__bss_start = . ;
__bss_start__ = . ;
*(.bss*)
*(COMMON)
. = ALIGN(4);
PROVIDE (__bss_end = .);
} > RAM

.noinit (NOLOAD) :
{
. = ALIGN(4);
PROVIDE (__noinit_start = .) ;
*(.noinit*)
PROVIDE (__noinit_end = .) ;
PROVIDE (__heap_start = .) ;
} > RAM

.stack :
{
. = ALIGN(4);
. += SYS_STACK_SIZE;
PROVIDE (__stack = .);
. += IRQ_STACK_SIZE;
PROVIDE (__stack_irq = .);
/* allocate stacks if needed */
PROVIDE (__stack_fiq = .);
PROVIDE (__stack_und = .);
PROVIDE (__stack_abort = .);
PROVIDE (__stack_svc = .);

} > RAM

_end = . ;
PROVIDE (end = .);

/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}



P.S. Вообще-то в озу достаточно расположить только команду записи в AT91C_BASE_MC->MC_FCR и цикл ожидания AT91C_MC_FRDY.


--------------------
На любой вопрос даю любой ответ
"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



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

 


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


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