Omnicake
Apr 30 2014, 02:57
Здравствуйте, хотелось узнать несколько подробностей по поводу работы с микропроцессором STM32f10x в Keil uVision 5:
1) На процессорах C55x на ассемблере командами:
AMOV #Label, xar0
MOV dbl(*ar0), xar0
MOV dbl(*ar0), xar0
MOV *ar0, ac0
Метка Label была указателем на массив, заданный во внешнем файле C, первые две команды mov выгружали каким-то образом сначала адрес массива, потом его структуру, а потом отдельный элемент.
Хотелось сделать аналог такой же выгрузки на STM32F10x но не нашел в Instruction Set аналога обозначения *ar0 – то есть выгрузки значения из адреса r0 (заменять на LDR?), а также что такое dbl и как зовется его аналог в Cortex-M3 командах.
2) Знаю, что в Cortex-M3 существуют так называемые "теневые регистры", которые, как я понял, включаются на момент прерывания. Как обозначаются эти регистры при работе с ними, и сохраняется ли их значения после выхода из прерывания?
Заранее спасибо.
adnega
Apr 30 2014, 04:26
1. Попробуйте
push {r0}. В скобках можно передавать список регистров, например, push {r0-r3, lr}.
2. Не совсем понятна задача. Вот пример копирования массива (r0 - куда копировать, r1 - откуда копировать, r2 - сколько слов копировать)
Код
memcpy_dw_loop:
ldr r3, [r1], #4
str r3, [r0], #4
subs r2, #1
bne memcpy_dw_loop
3. В Cortex-M3 теневых регистров нет (правда, есть два стека MSP и PSP). При входе в прерывание некоторые регистры автоматически сохраняются
в стек, при выходе - извлекаются. Отключить этот механизм нельзя. Соответственно ответ на вопрос: "не сохраняются".
Omnicake
Apr 30 2014, 04:52
1. Да, действительно нужно было регистры брать в фигурные скобки, спасибо.
2. Задача в том, что есть некий массив, в котором хранятся числа (например 1,2,3,4) из массива нужно в ассемблере вытаскивать только одно число, чтобы потом использовать его для сравнения. Как реализовать загрузку именно не всего массива, а одного числа на выбор (например только 2го по порядку, или последнего и.т.д.)?
3. Вот здесь
http://www.arm.com/files/pdf/introToCortex-M3.pdf нашел такую строчку "To reduce gate count and enhance system flexibility the Cortex-M3 has migrated from the banked shadow register exception model of the ARM7 processor to a stack based exception model. When an exception takes place, the Program Counter, Program Status Register, Link Register and the R0-R3,R12 general purpose registers are pushed on to the stack." То есть как я понимаю перед входом и выходом в прерывание мне не нужно сохранять состояние регистров R0-R3, R12, LR, SR и PC, так как это делается автоматически?
Golikov A.
Apr 30 2014, 05:50
чтобы получить доступ ко 2 элементу массива надо делать так
объявить массив
int32_t array[10];
выбрать 2 элемент массива
array[1];
к чему трудно поддерживаемый ассемблер в элементарных операциях? После того как сделаете то что хотите, можно проверить листинг на асме что получилось у компилятора, и если уж очень не понравиться переписать асемблерными вставками, но надо обязательно дать шанс компилятору, уверен что в вопросах копирования массивов и выбора их из памяти он вас не разочарует...
Omnicake
Apr 30 2014, 06:48
Использование ассемблера обусловлено спецификой проекта, скажем так, но ваш совет попробую. Спасибо большое за ответы.
adnega
Apr 30 2014, 06:56
Цитата(Omnicake @ Apr 30 2014, 08:52)

Вот здесь
http://www.arm.com/files/pdf/introToCortex-M3.pdf нашел такую строчку "To reduce gate count and enhance system flexibility the Cortex-M3 has migrated from the banked shadow register exception model of the ARM7 processor to a stack based exception model. When an exception takes place, the Program Counter, Program Status Register, Link Register and the R0-R3,R12 general purpose registers are pushed on to the stack." То есть как я понимаю перед входом и выходом в прерывание мне не нужно сохранять состояние регистров R0-R3, R12, LR, SR и PC, так как это делается автоматически?
Написано, что ушли от модели теневых регистров, принятой в ARM7, к модели сохранения регистров на стеке.
Ничего сохранять/восстанавливать не нужно, если в прерывании используются только указанные регистры.
Вообще, в Cortex-M практически все можно делать на C (startup, обработчики).
Omnicake
May 1 2014, 03:03
В дизассемблере происходят странные вещи:
SUB sp,sp,#0x18
MOVS r2,#0x14
LDR r1,|L0.24|
ADD r0,sp,#4
BL __aeabi_memcpy4
LDR r1,|L0.28|
LDR r0,[sp,#0xc]
STR r0,[r1,#0] ; x
По метке |L0.28| находится DCD x
По метке |L0.24| находится DCD ||.constdata||
__aeabi_memcpy4:
PUSH {r4,lr}
SUBS r2,r2,#0x20
BCC.W 0x080001FA
LDM r1!,{r3-r4,r12,lr}
SUBS r2,r2,#0x20
STM r0!,{r3-r4,r12,lr}
LDM r1!,{r3-r4,r12,lr}
STM r0!,{r3-r4,r12,lr}
BCS.W 0x080001E4
LSLS r12,r2,#28
ITT CS
LDM r1!,{r3-r4,r12,lr}
STM r0!,{r3-r4,r12,lr}
ITT MI
LDM r1!,{r3-r4}
STM r0!,{r3-r4}
POP {r4,lr}
LSLS r12,r2,#30
ITT CS
LDR r3,[r1],#0x04
STR r3,[r0],#0x04
IT EQ
BX lr
Это реакция на команду:
int32_t array[5]={1,2,3,4,5};
x=array[2];
Я вообще не понимаю логику того, что там происходит и что такое __aeabi_memcpy4.
Я опишу еще раз подробнее то, что мне нужно сделать, возможно я просто неправильно задал вопрос:
У меня есть файл task1.c содержащий простейшую команду и описание des1 ddd1={1,2,3}; где des1 ddd1 берется из header файла descriptors.h и выглядит так:
typedef struct {
int Status;
int CurrentTic;
int NumberTic;
int Command;
long CurrentPC;
long StartPC;
long CurrentSP;
long StartSP;
long CurrentSSP;
long StartSSP;
long temp;
} des1;
При импорте ddd1 в ассемблерную подпрограмму структура корректно грузится и задает значения Status=1, CurrentTic=2 и NumberTic=3, мне нужно там же в ассемблерной вставке вытащить из структуры в регистр значение, например Status и сравнить с 1. В микропроцессоре C55x это делалось последовательностью команд:
amov #TaskPointer, xar0
mov dbl(*ar0), xar0
mov dbl(*ar0), xar0
mov *ar0, ac0 ; getting Status
TaskPointer:
.long TaskTableStart
TaskTableStart:
.long _ddd1
.long _ddd2
.long _ddd3
.long _ddd4
TaskTableEnd:
Как можно сделать то же самое, но на Cortex-M3?
Golikov A.
May 1 2014, 05:42
Вы поставили уровень оптимизации проекта на 0? Изначально он в кейле, например, дефалт, а это -2 а не 0. А оптимизит он здорово, потому код легко не узнать.
Omnicake
May 1 2014, 06:00
Нет, стоит нулевой уровень оптимизации.
Сергей Борщ
May 1 2014, 06:33
Omnicake, используйте, пожалуйста, кнопочку

когда выкладываете код.
Цитата(Omnicake @ May 1 2014, 06:03)

В дизассемблере происходят странные вещи:
...
Это реакция на команду:
int32_t array[5]={1,2,3,4,5};
x=array[2];
Я вообще не понимаю логику того, что там происходит и что такое __aeabi_memcpy4.
Абсолютно ничего странного тут не происходит.
Код
SUB sp,sp,#0x18 // Сдвинули указатель стека на 24 байта, зарезервировав 20 байт под array и 4 байта под что-то еще
MOVS r2,#0x14 // загрузили размер array в R2
LDR r1,|L0.24| // загрузили в R1 адрес {1, 2, 3, 4, 5}
ADD r0,sp,#4 // загрузили в R0 адрес array[0]
BL __aeabi_memcpy4 // вызвали библиотечную функцию memcpy, скопировали {1, 2, 3, 4, 5} в array
LDR r1,|L0.28| // загрузили в R1 адрес x
LDR r0,[sp,#0xc] // загрузили в R0 содержимое array[2]
STR r0,[r1,#0]; x // сохранили R0 в х
memcpy - стандартная библиотечная функция.
Цитата(Omnicake @ May 1 2014, 06:03)

Как можно сделать то же самое, но на Cortex-M3?
Код
LDR r1,=ddd1 // загрузили в R1 адрес ddd1
LDR r1,[r0,#0] // загрузили в R0 ddd1.Status (0 - смещение Status относительно начала des)
Omnicake
May 1 2014, 06:47
Извиняюсь, в дальнейшем не повторится. Спасибо большое за разъяснения, буду пробовать дальше.
Цитата(Omnicake @ Apr 30 2014, 08:57)

1) На процессорах C55x на ассемблере командами:
AMOV #Label, xar0
MOV dbl(*ar0), xar0
MOV dbl(*ar0), xar0
MOV *ar0, ac0
си:
{
uint ac0 = *(typ *)*(void **)*(void **)Label;
}
typ здесь - это или signed short или unsigned short (в зависимости от соотв.флага C55-ядра).
асм Cortex:
Код
LDR R0, =Label;или ADR R0, Label - если Label находится в const-секции рядом с кодом
LDR R0, [R0]
LDR R0, [R0]
LDRSH R0, [R0] ;или LDRH R0, [R0] - см. выше
;R0==AC0
PS: Давненько не имел дела с C55x, может что напутал.
Но до сих пор помню, что конструкция приведённая Вами вызовет кучу stalls на C55x, так как написана очень плохо.