Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: AT91SAM9G45
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Sergey1212
Подскажите пожулуйста как настроить GPIO частоту равную мастер клоку 133Мгц, ARM только начал изучать.
Проинициализировал Процессор клок на 400Мгц Мастер клок на 133, далее в безконечном цикле дергаю ногой в своем примере из SRAM без убутов и бутстрапов получаю максимум 2,8 Мгц период т.е. включение выключение. Такой же код вписал в убут собрал запустил получил 11,111111 Мгц период т.е. 11,1111Мгц х 2 х 6 тактов = 133 Мгц.
Интересует есть ли какие либо еще регистры где прописывается частота тактирования GPIO?
В даташите на него ничего не нашел.


Как я понял дело в MMU и кеше
Включил MMU кеш как описано здесь http://electronix.ru/forum/index.php?showt...&hl=SAM9G45
получил 7.8431 МГц но этого тоже мало должно быть как в убуте 11.11111МГц
подскажите пример MMU и кеша на полную катушку так сказать
jcxz
Цитата(Sergey1212 @ Apr 24 2013, 14:02) *
Подскажите пожулуйста как настроить GPIO частоту равную мастер клоку 133Мгц, ARM только начал изучать.
...
подскажите пример MMU и кеша на полную катушку так сказать
Если уж Вы начали изучать ARM9, то сразу отучайтесь от ногодрыганья и изучайте периферию ARM.
Golikov A.
Еще в некоторых процах можно выбрать режим скорости работы ноги, в одних быстро - медленно, а в некоторых стмах (правда уже кортексах) аж 4 уровня скорости есть от 2.5 МГц, до максимума, и если нога настроена на медленную работу, то хоть клок проца на нее выводи быстрее не поедет...

посмотрите в около FAST GPIO и или GPIO SPEED. и так далее...

Но в целом да, АРМ - это использование периферии, GPIO - это не для него, вся моща уйдет в ножки... Частота GPIO обычно половина от системной, а на изменение состояния ноги обычно 2-4 команды, вот и считайте... неоткуда 100 МГц на 400 клоке взяться...
Sergey1212
Цитата(jcxz @ Apr 24 2013, 13:00) *
Если уж Вы начали изучать ARM9, то сразу отучайтесь от ногодрыганья и изучайте периферию ARM.

Я знаю что нужно изучать переферию в данный момент я пытаюсь сделать инициализацию для этого взял безконечный цикл с дерганьем ноги и еще туда добавляю 10 раз i++ смотрю на осциллографе на сколько у меня сдвигается фронт тем самым определяю сколько нс заняли 10 команд i++

Вобщем переферия это да но вопрос сейчас в другом как достигнуть такой же инициализации как и в u-boot'е а может и еще лучше
Golikov A.
какие то интересные исследованияsm.gif можно же всегда поглядеть дизасемблерный код, да и узнать сколько инструкций на что идет. Ведь есть еще разные настройки оптимизации, разворачивание циклов, предсказание ветвлений... в чем смысл этих исследований?
Sergey1212
Цитата(Golikov A. @ Apr 24 2013, 13:59) *
Еще в некоторых процах можно выбрать режим скорости работы ноги, в одних быстро - медленно, а в некоторых стмах (правда уже кортексах) аж 4 уровня скорости есть от 2.5 МГц, до максимума, и если нога настроена на медленную работу, то хоть клок проца на нее выводи быстрее не поедет...

посмотрите в около FAST GPIO и или GPIO SPEED. и так далее...

Но в целом да, АРМ - это использование периферии, GPIO - это не для него, вся моща уйдет в ножки... Частота GPIO обычно половина от системной, а на изменение состояния ноги обычно 2-4 команды, вот и считайте... неоткуда 100 МГц на 400 клоке взяться...


На изменение состояния ноги судя по картинкам из даташита уходит 6 тактов Мастер клока MCK котрый настроен на 133МГц соответственно 133МГц / 6 = 22,2222...
чтобы получился период, а он состоит из включения и выключения, делим 22,22222222 на 2 получается 11,111111МГц который я и вижу когда запускаю этот цикл в u-boot'е
FAST GPIO и GPIO SPEED в даташите опять же не нашел

Вообще дергание ногой я использую для того чтобы замечать смещение фронта (увеличение скважности) импульса на осциллографе при добвлении в тот же код нескольких команд i++


Цитата(Golikov A. @ Apr 24 2013, 15:36) *
какие то интересные исследованияsm.gif можно же всегда поглядеть дизасемблерный код, да и узнать сколько инструкций на что идет. Ведь есть еще разные настройки оптимизации, разворачивание циклов, предсказание ветвлений... в чем смысл этих исследований?

Не могли бы вы поподробнее о настройках оптимизации?

Попробовал я вставить код MMU кеш из убута резальтат такой же 7.84Мгц вместо ожидаемых 11.111...
Fedor
Максимальную скорость выполнения кода можно получить в Internal SRAM
процессора см. TCM Interface это без MMU.
Максимальная частота ногодрыганья из таблицы 46-17 атмеловского мануала на этот процессор.
Sergey1212
OPTIMIZATION = -O3
Решили проблему))
вышел на 12.12 МГц видимо меньше 6 тактов занимает переключение состояния)
Вопрос можно ли еще больше поднять "скорость выполнения" на этом контроллере?

Цитата(Fedor @ Apr 24 2013, 15:55) *
Максимальную скорость выполнения кода можно получить в Internal SRAM
процессора см. TCM Interface это без MMU.
Максимальная частота ногодрыганья из таблицы 46-17 атмеловского мануала на этот процессор.

Похоже так и получается что TCM без MMU т.е. включаю icache_enable а при нем MMU не запускается
Максимальная частота ногодрыгания в той таблице это немного не то что нужно
Fedor
Попробуйте использовать модуль PWM
могу конечно ошибаться но судя по даташиту MCK/2 можно получить.
Sergey1212
Цитата(Fedor @ Apr 24 2013, 16:55) *
Попробуйте использовать модуль PWM
могу конечно ошибаться но судя по даташиту MCK/2 можно получить.

Меня интересует не аппаратная а программная реализация ногодрыгания с точки зрения оптимизации выполняемой программы т.е. как раз кеши и ITCM DTCM MMU и незнаю что там еще может быть чтобы поднять скорость выполнения кода который будет управлять в данном контексте ногами
просто мне так удобнее смотря на осциллограф я чижу чтоо код стал выполняться быстрее или медленее вот и все
если бы я хотел на ноге получить нужную мне частоту я бы использовал PCK0 или PCK1

Кто нибудь может в кратце разъяснить про ITCM DTCM MMU с чем их вообще едят
функция icache_enable взятая из u-boot'a работает и в SRAM и в DDRAM а вот dcache_enable а вместе с ним и MMU что в драме что в сраме приводят к зависанию
Golikov A.
вообщем я думаю самый правильный путь это посмотреть дизасемблер вашего ногодрыганья после оптимизации, посмотреть что там за команды вызываются, и подумать есть ли среди них какие лишние. Если лишних нет - то это предел скорости.

Вам в общих чертах интересно вообще про кэши или именно про кэши этого проца?
Sergey1212
Пока что интересуют именно к этому процу
Как я понимаю тот кусок кода кде уменя цикл и две функции включения и отключения ноги не должен поменяться если я буду компилить с icache'ем?
Если я включаю в коде icache то в дизасемблере смогу видеть что участок кода с циклом включеним выключеним ноги поменялся?
И еще вопрос как мне это дизасемблерром посмотреть?
JTAGA нет использую плату на которой он не выведен.
Компилятор arm-none-eabi-
Golikov A.
Цитата(Sergey1212 @ Apr 24 2013, 17:52) *
Пока что интересуют именно к этому процу
Как я понимаю тот кусок кода кде уменя цикл и две функции включения и отключения ноги не должен поменяться если я буду компилить с icache'ем?
Если я включаю в коде icache то в дизасемблере смогу видеть что участок кода с циклом включеним выключеним ноги поменялся?
И еще вопрос как мне это дизасемблерром посмотреть?
JTAGA нет использую плату на которой он не выведен.
Компилятор arm-none-eabi-


ну я на иарах и кейлах обычно сижу, кеил сам показывает дизасемблер не скрывая ничего, в ИАРе он виден если загрузил по жетагу или в режиме симулятора. В вашей среде нет симулятора? обычно там всегда к обычному коду еще он же в ассемблере добавлен, потому что иначе упаришся в бинарнике искать какой код за какие строки отвечает...

В общей теории кешей кусок кода отвечающий за дерганья ногами меняться не должен, изменениям подвергнется лишь скорость выбора инструкций из памяти. Хотя в код могут быть добавлены некоторые инструкции которые управляют кешированием нужных участков кода. Современные компиляторы иногда делают такие хитрые вещи при оптимизации кода, что никогда не знаешь что ты там увидишь в итогеsm.gif... Но учитывая малость участка кода, думаю он будет неизменен...
Sergey1212
Вот кусок с дизассемблерра получил из eclipsa запустил приложение в qemu-system-arm
с выключенным icache:
i++;
003001d4: ldr r1, [sp, #4]
003001d8: add r1, r1, #1
003001dc: str r1, [sp, #4]
517 pio->PIO_CODR = mask;
003001e0: str r3, [r2, #-3531] ; 0xdcb
512 pio->PIO_SODR = mask;
003001e4: str r3, [r2, #-3535] ; 0xdcf

с включенным icache:
i++;
00300224: ldr r1, [sp, #4]
00300228: add r1, r1, #1
0030022c: str r1, [sp, #4]
517 pio->PIO_CODR = mask;
00300230: str r3, [r2, #-3531] ; 0xdcb
512 pio->PIO_SODR = mask;
00300234: str r3, [r2, #-3535] ; 0xdcf

этот же кусов в С:

i++;
003001d4: ldr r1, [sp, #4]
003001d8: add r1, r1, #1
003001dc: str r1, [sp, #4]
003001e0: str r3, [r2, #-3531] ; 0xdcb
512 pio->PIO_SODR = mask;
003001e4: str r3, [r2, #-3535] ; 0xdcf

Так что код в дизасемблере не меняется а вот в реале частота на ноге меняется

Поскажите как тут понять сколько тактов у меня занимает i++ который занимает три строки в асме?
003001d4: ldr r1, [sp, #4]
003001d8: add r1, r1, #1
003001dc: str r1, [sp, #4]

Цитата(Golikov A. @ Apr 24 2013, 18:27) *
ну я на иарах и кейлах обычно сижу, кеил сам показывает дизасемблер не скрывая ничего, в ИАРе он виден если загрузил по жетагу или в режиме симулятора. В вашей среде нет симулятора? обычно там всегда к обычному коду еще он же в ассемблере добавлен, потому что иначе упаришся в бинарнике искать какой код за какие строки отвечает...

В общей теории кешей кусок кода отвечающий за дерганья ногами меняться не должен, изменениям подвергнется лишь скорость выбора инструкций из памяти. Хотя в код могут быть добавлены некоторые инструкции которые управляют кешированием нужных участков кода. Современные компиляторы иногда делают такие хитрые вещи при оптимизации кода, что никогда не знаешь что ты там увидишь в итогеsm.gif... Но учитывая малость участка кода, думаю он будет неизменен...

Тогда что там смотреть дизассемблером?
Fedor
Смысл использовать MMU если у вас код и данные вертится в SRAM не вижу, там и так все работает на частоте ядра.
MMU как раз и для того чтобы кешировать данные из относительно медленной DDR памяти. Насчет кеша кода неотвечу.
В таблице 46-17 сказано что если у вас VDDPIO имеют питание 3,3В можно получить большую частоту на ноге. При этом указывается значение емкости на ножке для которой вы эту частоту вытянете.
Сколько на вашей плате VDDPIO порта в который вы пишете?


И пропишите для вашей переменой i квалификатор register будет быстрее.
Sergey1212
Цитата(Fedor @ Apr 24 2013, 21:07) *
И пропишите для вашей переменой i квалификатор register будет быстрее.


Смысл в том что я хочу его в ддр запустить но пока что там что там работает одинаково поэтому в сраме и эксперементирую больше чем в ддраме ожидаю увеличения производительности сначало в сраме
VDDPIO 3.3
register завтра попробую добавить
Golikov A.
в дизасемблере надо смотреть что за такты в цикле, нет ли каких лишних на экономию регистров. На самом деле после компилятора на максимальной оптимизации я уверен смотреть нечего, и предложил это больше для вашего самоуспокоения. То есть вы бы увидели код, поняли что меньше 6 инструкций (или сколько там получается) не будет и успокоились бы)...


про кэш все абсолютно понятно. При работе кода из ДДР каждая инструкция требует чтение из памяти. Читать из ДДР - это далеко не 1 такт, там куча задержек на выбор ряда, колонки, потом просто ожидание данных и так далее. Чтение 1 инструкции из ДДР - это реально долго. Но если выбрать область памяти внутри проца, где время чтения 1 такт, и запихивать в нее куски кода из ДДР (а последовательно ДДР читает значительно быстрее, первая задержка считай делиться на все байты последовательности). Эти куски кода будут помещаться в кэш, тем более если есть циклы иногда они будут туда влезать целиком, и каждая инструкция будет выполнятся за 1 такт. Это и дает бешеный прирост производительности, без изменения вида кода.
Fedor
Не мешает проверить также на какую область памяти у вас указывает sp
Если в DRAM то настроить MMU так, чтобы стек тоже кэшировался.
Sergey1212
Цитата(Fedor @ Apr 25 2013, 09:23) *
Не мешает проверить также на какую область памяти у вас указывает sp
Если в DRAM то настроить MMU так, чтобы стек тоже кэшировался.

А как посмотреть куда указывает sp?
Просто не доганяю как в эклипсовском дизасемблере это проделать))
да и думаю если я бутстрапом подгружаю приложение в ддр то наверное и переменная i будет там же
И как настроить MMU чтобы стек кэшировался?
Есть где нибудь примеры или описание с кусками кода в пример как вообще это настраивать этот MMU и все остальное?
Где можно почитать о всяких таблицах и т.д.?

Драм вариант в эмуляторе не запускается поэтому там дизассемблером посмотреть немогу а в срамовсом варианте sp указывает на срам область 0x30ff80
Fedor
Цитата(Sergey1212 @ Apr 25 2013, 15:08) *
А как посмотреть куда указывает sp?...
Драм вариант в эмуляторе не запускается поэтому там дизассемблером посмотреть немогу а в срамовсом варианте sp указывает на срам область 0x30ff80


В конфигурационном файле для линковшика (*.ld, *.lds) обычно прописывается точка-указатель которым инициализируется SP в стартап файле. В самом стартап-файле прописываются вектора прерываний, начальная загрузка и проч. в том числе и загрузка указателя стека. Этот стартап файл написан на ассемблере (*.S, *.asm). Все это должно быть у вас в исходниках проекта. Поскольку в арме стэк это обычная область памяти, настройка MMU не отличается, лишь бы область стека попала в кэшируемую часть памяти.
Sergey1212
Вот lds:
CODE
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(entry)

MEMORY
{
sram (W!RX) : ORIGIN = 0x300000, LENGTH = 64K
ddr_ebi0 (W!RX) : ORIGIN = 0x73f00000, LENGTH = 64M
}

SECTIONS
{
.fixed :
{
. = ALIGN(4);
_sfixed = .;
*(.text*)
*(.rodata*)
*(.glue_7)
*(.glue_7t)
*(.data)
*(.CP15_*)
. = ALIGN(4);
_efixed = .;
} >ddr_ebi0

.prerelocate : AT (_efixed)
{
. = ALIGN(4);
_sprerelocate = .;
. = ALIGN(4);
_eprerelocate = .;
}

.postrelocate : AT (_efixed + SIZEOF(.prerelocate))
{
. = ALIGN(4);
_spostrelocate = .;
*(.vectors);
*(.ramfunc)
. = ALIGN(4);
_epostrelocate = .;
} >sram

.bss (NOLOAD) : {
_szero = .;
*(.bss)
. = ALIGN(4);
_ezero = .;
} >ddr_ebi0

_sstack = 0x73f00000 + 64 * 1024 * 1024;
}
end = .;

А вот стартап:
CODE
#include "board.h"

//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------

#define IRQ_STACK_SIZE 8*3*4

#define ARM_MODE_ABT 0x17
#define ARM_MODE_FIQ 0x11
#define ARM_MODE_IRQ 0x12
#define ARM_MODE_SVC 0x13

#define I_BIT 0x80
#define F_BIT 0x40

//------------------------------------------------------------------------------
// Startup routine
//------------------------------------------------------------------------------

.align 4
.arm

/* Exception vectors
*******************/
.section .vectors, "a", %progbits

resetVector:
ldr pc, =resetHandler /* Reset */
undefVector:
b undefVector /* Undefined instruction */
swiVector:
b swiVector /* Software interrupt */
prefetchAbortVector:
b prefetchAbortVector /* Prefetch abort */
dataAbortVector:
b dataAbortVector /* Data abort */
reservedVector:
b reservedVector /* Reserved for future use */
irqVector:
b irqHandler /* Interrupt */
fiqVector:
/* Fast interrupt */
//------------------------------------------------------------------------------
/// Handles a fast interrupt request by branching to the address defined in the
/// AIC.
//------------------------------------------------------------------------------
fiqHandler:
b fiqHandler

//------------------------------------------------------------------------------
/// Handles incoming interrupt requests by branching to the corresponding
/// handler, as defined in the AIC. Supports interrupt nesting.
//------------------------------------------------------------------------------
irqHandler:

/* Save interrupt context on the stack to allow nesting */
sub lr, lr, #4
stmfd sp!, {lr}
mrs lr, SPSR
stmfd sp!, {r0, lr}

/* Write in the IVR to support Protect Mode */
ldr lr, =AT91C_BASE_AIC
ldr r0, [lr, #AIC_IVR]
str lr, [lr, #AIC_IVR]

/* Branch to interrupt handler in Supervisor mode */
msr CPSR_c, #ARM_MODE_SVC
stmfd sp!, {r1-r3, r4, r12, lr}
blx r0

/* Restore scratch/used registers and LR from User Stack */
/* Disable Interrupt and switch back in IRQ mode */
ldmia sp!, {r1-r3, r4, r12, lr}
msr CPSR_c, #ARM_MODE_IRQ | I_BIT

/* Acknowledge interrupt */
ldr lr, =AT91C_BASE_AIC
str lr, [lr, #AIC_EOICR]

/* Restore interrupt context and branch back to calling code */
ldmia sp!, {r0, lr}
msr SPSR_cxsf, lr
ldmia sp!, {pc}^

//------------------------------------------------------------------------------
/// Initializes the chip and branches to the main() function.
//------------------------------------------------------------------------------
.section .text
.global entry

entry:
resetHandler:

/* Useless instruction for referencing the .vectors section */
ldr r0, =resetVector

/* Set pc to actual code location (i.e. not in remap zone) */
ldr pc, =1f

/* Initialize the prerelocate segment */
1:
ldr r0, =_efixed
ldr r1, =_sprerelocate
ldr r2, =_eprerelocate
1:
cmp r1, r2
ldrcc r3, [r0], #4
strcc r3, [r1], #4
bcc 1b

/* Perform low-level initialization of the chip using LowLevelInit() */
ldr sp, =_sstack
stmfd sp!, {r0}
ldr r0, =LowLevelInit
blx r0

/* Initialize the postrelocate segment */

ldmfd sp!, {r0}
ldr r1, =_spostrelocate
ldr r2, =_epostrelocate
1:
cmp r1, r2
ldrcc r3, [r0], #4
strcc r3, [r1], #4
bcc 1b

/* Clear the zero segment */
ldr r0, =_szero
ldr r1, =_ezero
mov r2, #0
1:
cmp r0, r1
strcc r2, [r0], #4
bcc 1b

/* Setup stacks
**************/
/* IRQ mode */
msr CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT
ldr sp, =_sstack
sub r4, sp, #IRQ_STACK_SIZE

/* Supervisor mode (interrupts enabled) */
msr CPSR_c, #ARM_MODE_SVC | F_BIT
mov sp, r4

/* Branch to main()
******************/
ldr r0, =main
blx r0

/* Loop indefinitely when program is finished */
1:
b 1b


Почему если я запускаю только айкеш производительность возрастает по сравнению с тем когда запускаю ММУ датакеш и айкеш в 1,5 раза

вот на всякий случай мой код включения мму дата и айкешей
CODE
static unsigned char *BufMMU = (unsigned char *) (SRAM_ADDRESS + 0x4000);

#include "cp15/cp15.h" //Atmel at91lib

void InitMMU(unsigned int *pTranslationTable)
{
int i;
int addSRAM;

// Program the TTB
printf("TTB = 0x%X\n\r", (unsigned int)pTranslationTable);

CP15_WriteTTB((unsigned int)pTranslationTable);

// Program the domain access register
CP15_WriteDomainAccessControl(0xFFFFFFFF); // domain 15: access are not checked

// Reset table entries
for (i = 0; i < 4096; i++) {
//printf("0x%X %d \r\n", (i << 20 | (3 << 10) | 0x12), (i << 20 | (3 << 10) | 0x12));
pTranslationTable[i] = i << 20 | (3 << 10) | 0x12;
}
// Program level 1 page table entry

// Vector adress
pTranslationTable[0x0] = (0x00000000)|TLB_NCNB;
// SRAM adress (with D cache)
addSRAM = (SRAM_ADDRESS >> 20);
printf("addSRAM = 0x%X\n\r", addSRAM);
printf("SRAM_ADDRESS = 0x%X\n\r", SRAM_ADDRESS);
pTranslationTable[addSRAM] = (SRAM_ADDRESS)|TLB_WB;
//DDRAM buf1 with write-through
pTranslationTable[0x701] = (AT91C_DDR2 + 0x00100000)|TLB_WT;
//DDRAM buf2 with write-through
pTranslationTable[0x702] = (AT91C_DDR2 + 0x00200000)|TLB_WT;
// Peripherals adress

pTranslationTable[0xFFF] = (0xFFF00000)|TLB_NCNB;
CP15_EnableMMU();
CP15_EnableDcache();
CP15_EnableIcache();
}

void main(void)
{
InitMMU((unsigned int*)BufMMU);

unsigned int mask = (1<<20);

AT91S_PIOM *pioa;
pioa = PIOA_BASE;
pio_enable(pioa, mask);
pio_disable_irq(pioa, mask);
pio_disable_multiple_driver(pioa, mask);
pio_disable_pull_ups(pioa, mask);
pio_output_enable(pioa, mask);

volatile unsigned int i;
while(1)
{
i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++
;i++;
PIO_ClearM(pioa, mask);
i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++
;i++;
PIO_SetM(pioa, mask);
}
}


pTranslationTable[i] = i << 20 | (3 << 10) | 0x12;
Эту строку взял из убута до этого было
pTranslationTable[i] = 0
И при этом не работали мму и дкеш
но производительность при включении мму и дкеша сразу уменьшается чем это можно объяснить?
Fedor
Код
pTranslationTable[i] = i << 20 | (3 << 10) | 0x12;

Эта запись организует TLB и запрещает кеширование выбранных секций.
Т.е. в данном случае для всего адресуемого 4GB.
В убуте это видимо сделанно намеренно чтобы избежать коллизий при перезагрузке из линукса

Код
pTranslationTable[0x701] = (AT91C_DDR2 + 0x00100000)|TLB_WT;
//DDRAM buf2 with write-through
pTranslationTable[0x702] = (AT91C_DDR2 + 0x00200000)|TLB_WT;
// Peripherals adress

Здесь вы почемуто разрешаете кеширование, но для секций которые находятся вообще вне вашей области DRAM, судя по скрипту lds оно начинается с 0x73f00000, а у вас включено на 0x70100000 и на 0x70200000 ?
Код
ddr_ebi0 (W!RX) : ORIGIN = 0x73f00000, LENGTH = 64M

Видимо пример был для другого случая.
И вот такое |TLB_WT по моему больше подходит для перемещения массивов из одной области в другую, вам лучше write-back включить.
Вобщем судя по настройке MMU и DCaсhe хоть и включен, но бестолку.
Думаю, что нужно прочитать ARM926EJ-S Technical Reference Manual Complete.

Код
_sstack = 0x73f00000 + 64 * 1024 * 1024;

это ваш верх стека из lds.

Sergey1212
поправил
pTranslationTable[i] = i << 20 | (3 << 10) | 0xDFE // Write-back 11 0 1111 1 11 10
т.е. как я понимаю разрешил кеширование всех секций?
а чем может быть опасно кеширование секций всмысле почему в том же убуте запрещено?
если кеширование разрешено то какие подводные камни могут выплыть?)
Какие области памяти не стоит кешированть?
зачем отдельно от мму есть возможность оключать датакеш?
зачем их вообще отключать почему нельзя было сделать их все время включеными?
если я буду кешировать все секции кроме 0x00000000 как сейчас получилось могут возникнуть какие-то проблемы?
Genadi Zawidowski
При работе периферии с прямым доступом к памяти (PDC работает с памятью, а данные могут быть в кэше при WB, читаем данные из кэша - а в памяьи данные изменены по PDC).
Периферию вообще как некэшируюмую область описать надо.
Fedor

Не нужно кэшировать область памяти где расположена внутренняя периферия.
Куда читаете или пишете используя DMA, поскольку ЦП не знает про DMA , хотя вроде после каждой транзакции можно принудительно перезаливать кэш.
Смысл кэшировать сегиент кода? Это не данные для этого есть ICache.
Думаю что есть еще нюансы...
Ну и нужно помнить что кэш данных не даст существенного прироста производительности если вы работаете с данными из разрозненных областей памяти вне пределов размера кэша.
taoga
Вот код инициализации MMU из softpack для sam9g35.
Нажмите для просмотра прикрепленного файла
Sergey1212
Цитата(Fedor @ Apr 25 2013, 21:52) *
Смысл кэшировать сегиент кода? Это не данные для этого есть ICache.

Извеняюсь конечно но чет я не понимаю не фига)
бутстрапом приложение копируется в 0x73f00000 это получается сегмент кода для которого достаточно только ICache?
а где тогда сегмент данных?
ICache кеширует только сам код программы?
а чем занимаются DCache и MMU?

taoga
Для измерения скорости работы проца можно использовать basic-dhrystone-project. Я использую его для sam9g35, до этого для sam9xe. Максимальную скорость дает включение полной оптимизации по скорости(iar). Примеры atmel это конечно полный отстой, в плане того, что все они работают только при отключенном MMU. Если немного поискать можно найти много информации по MMU на этом форуме. А если хотите все знать ищите информацию по ARM926EJ.
Sergey1212
Да пожалуй на пока инфы и примеров достаточно, надо теперь все переварить, в субботу выложу результаты полученные с хорошего осциллографа, по предварительным косвенным оценкам производительность вычисления i++ выросла в 25 раз! было 100 нс теперь предположительно должна стать 4 нс. Ногодрыгание имеющимся сейчас осциллографом не разглядеть.
Всем большое спасибо за ответы.
Golikov A.
Цитата(Sergey1212 @ Apr 25 2013, 22:30) *
Извеняюсь конечно но чет я не понимаю не фига)
бутстрапом приложение копируется в 0x73f00000 это получается сегмент кода для которого достаточно только ICache?
а где тогда сегмент данных?
ICache кеширует только сам код программы?
а чем занимаются DCache и MMU?


к дополнительному перевариванию надо в общих чертах про кэши и АРМ.

У вас в проце отдельно шина данных и шина команд. Первые идеи были положить и данные и инструкции в одну память и сложение выглядело так

загрузить адрес инструкции
загрузить инструкцию
распознать ее, понять что надо складывать
загрузить адрес первого операнда
загрузить операнд
загрузить адрес 2 операнда
загрузить операнд
сложить
получить адрес результата
загрузить адрес результата
выложить данные.

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

Кеши имеют разные алгоритмы работы, но в целом они автоматизированы, попали в ячейку памяти забрали ее и некую область вокруг. Попали в область кеша работаем из него, промазали, сбросили кеш загрузили новую область. Размер кеша допустим 4 кбайта, если вы будите тыкаться в ячейки расположенные друг от друга в 5 кбайтах так и будет постоянный сброс кеша и загрузка, будет медленее чем без него.

И вот тут как я понимаю и помогает ММУ, как я понял при помощи него вы можете положить себе поближе нужные куски памяти, и постараться учесть как будет вести себя программа, как она будет и куда прыгать и так далее.. То есть это как бы интеллектуальный, управляемый кеш... Хотя я могу ошибаться, и тогда меня поправятsm.gif...

Если шину данных и адреса использовать для управления чем либо, то есть выставляя биты на ножках адреса и данных, то кешировать это пространство низя, данные будт в кеше, а ножки не будут шевелиться. Так же как и для переферии если надо менять ее регистры, то кеш не даст это делать, вы будите менять внутреннюю память проца (кеш), а не регистры. Ну и при обращении через ДМА - тоже беда, рассинхронизация памяти...
aaarrr
Цитата(Golikov A. @ Apr 26 2013, 00:51) *
Кеши имеют разные алгоритмы работы, но в целом они автоматизированы, попали в ячейку памяти забрали ее и некую область вокруг. Попали в область кеша работаем из него, промазали, сбросили кеш загрузили новую область. Размер кеша допустим 4 кбайта, если вы будите тыкаться в ячейки расположенные друг от друга в 5 кбайтах так и будет постоянный сброс кеша и загрузка, будет медленее чем без него.

Кэш работает строками. Если тыкаться в ячейки, расположенные друг от друга в 5 килобайтах, то в кэше окажутся загружены две строки с соответствующими адресами.
И израсходовано на это дело будет всего 64 байта из допущенных 4 кБайт.

Цитата(Golikov A. @ Apr 26 2013, 00:51) *
И вот тут как я понимаю и помогает ММУ, как я понял при помощи него вы можете положить себе поближе нужные куски памяти, и постараться учесть как будет вести себя программа, как она будет и куда прыгать и так далее.. То есть это как бы интеллектуальный, управляемый кеш... Хотя я могу ошибаться, и тогда меня поправятsm.gif...

MMU нужен исключительно для построения виртуальной памяти. Кэшу он ничуть не помогает, а совсем даже наоборот sm.gif
Golikov A.
Цитата(aaarrr @ Apr 26 2013, 01:13) *
Кэш работает строками. Если тыкаться в ячейки, расположенные друг от друга в 5 килобайтах, то в кэше окажутся загружены две строки с соответствующими адресами.
И израсходовано на это дело будет всего 64 байта из допущенных 4 кБайт.

я условно написал, потому что когда вы израсходуете все строки будет опять та же ситуация. И опять же 64 байта - тоже условность, есть и другие значения. Общий смысл что бывают и промахи по кешу.

Цитата(aaarrr @ Apr 26 2013, 01:13) *
MMU нужен исключительно для построения виртуальной памяти. Кэшу он ничуть не помогает, а совсем даже наоборот sm.gif

А виртуальная память зачем? Удобство? Или возможность перетащить куски из ДДР поближе?
aaarrr
Цитата(Golikov A. @ Apr 26 2013, 07:31) *
я условно написал, потому что когда вы израсходуете все строки будет опять та же ситуация. И опять же 64 байта - тоже условность, есть и другие значения. Общий смысл что бывают и промахи по кешу.

Просто из вашего предыдущего сообщения можно было сделать вывод, что при промахе кэш загружается полностью с одного адреса,
в то время как на самом деле загружена будет только одна строка.

Цитата(Golikov A. @ Apr 26 2013, 07:31) *
А виртуальная память зачем? Удобство? Или возможность перетащить куски из ДДР поближе?

Удобство, прежде всего для "тяжелых" ОС - фиксированный адрес для приложений, защита памяти и т.п.

А есть смысл таскать куски памяти поближе, если процессор может адресовать все 4 Гбайта?

Вот периферию "таскать" приходилось - например, чтобы отразить контроллер прерываний в верхних адресах ради возможности
быстрого перехода по адресу вектора через ldr pc, [pc, #-X].
Golikov A.
Цитата(aaarrr @ Apr 26 2013, 11:57) *
Просто из вашего предыдущего сообщения можно было сделать вывод, что при промахе кэш загружается полностью с одного адреса,
в то время как на самом деле загружена будет только одна строка.


Удобство, прежде всего для "тяжелых" ОС - фиксированный адрес для приложений, защита памяти и т.п.

А есть смысл таскать куски памяти поближе, если процессор может адресовать все 4 Гбайта?

Вот периферию "таскать" приходилось - например, чтобы отразить контроллер прерываний в верхних адресах ради возможности
быстрого перехода по адресу вектора через ldr pc, [pc, #-X].


Да процы разные бывают, и кеши тоже..., Наверное вы правы, для строгости изложения, надо упомянуть что не всегда весь кеш обновляется.

Я обычно пишу маленькие системы, потому ММУ для меня чистая теория. думаю что можно какие то выгоды получить подтащив куски кода, переходы сократить, кешу помочь и так далее... но я не настаиваюsm.gif...

О кстати нашел у себя ММУ в процеsm.gif, там предлагают еще возможность организовать Shadow регистры данных и инструкции. То есть фактически шаг к виртуализации и многопотоковости...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.