Jump to content

    
Sign in to follow this  
Сергей Борщ

Написал порт scmRTOS под ARM

Recommended Posts

Написал порт scmRTOS (http://scmrtos.narod.ru/) для ARM. Отлаживал на AT91SAM7S64. Поскольку опыта в ARMах пока маловато (второй проект на ARM и первый с асмом), то перед тем как связываться с автором хотелось бы чтобы кто-то более опытный глянул. Порт лежит тут: http://upload.caxapa.ru/scmRTOS_arm.zip

Спасибо всем.

Share this post


Link to post
Share on other sites
чтобы кто-то более опытный глянул. Порт лежит тут:

Я не шибко опытный, но что то компилер не находит идентификатор AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE.

Share this post


Link to post
Share on other sites

>Я не шибко опытный, но что то компилер не находит идентификатор AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE.

 

Виноват, ставил патч от ИАРа.

#ifndef AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE

#define AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED

#endif

Share this post


Link to post
Share on other sites

Скомпилир все ОК.

Запускаю отладку в симуляторе.

После выполнения подпрограммы в файле OS_Target_asm.s79

 

ContextRestore
        MOV        LR, R0            ; use LR_svc as stack pointer

        LDMFD    LR!, {R0}        ; pop saved CPSR
        MSR        SPSR_cxsf, R0    ;
        LDMFD    LR, {R0-LR}^    ; restore all regs and reti
        NOP
        ADD        LR, LR, #15*4
        LDMFD    LR, {PC}^        ; reti

 

Улетает в неизвесном направлении.

 

Еще не хочет компилироваться в режиме ARM пишет

Internal Error: [symbol_lookup_M31]: symbol not found for mode 1 (backend generating) (P0: 0, P1: 0)

Share this post


Link to post
Share on other sites
Скомпилир все ОК.

Запускаю отладку в симуляторе.

После выполнения подпрограммы в файле OS_Target_asm.s79

Улетает в неизвесном направлении.

Действительно. Хотя в железе работает. Завтра попробую найти где разница и кто же работает правильно - ядро или симулятор :-). Кстати, в симуляторе не будут вызываться прерывания таймера со всеми вытекающими.

 

Еще не хочет компилироваться в режиме ARM пишет

Internal Error: [symbol_lookup_M31]: symbol not found for mode 1 (backend generating) (P0: 0, P1: 0)

компилятор падает от конструкции

    if(SysTickCount == 146)
        __no_operation();

в void OS::TKernel::SystemTimer(). Это рудимент - я ошибку искал. Но почему такая безобидная конструкция выбивает компилятор - наверное вопрос к его разработчикам. Причем __no_operation() без условия или другое действие в условии компилится нормально. В общем выкинуть этот кусок кода.

Share this post


Link to post
Share on other sites
Запускаю отладку в симуляторе.

После выполнения подпрограммы в файле OS_Target_asm.s79

Улетает в неизвесном направлении.

Проблема в команде

    LDMFD    LR, {R0-LR}^    ; restore all regs and reti

(коментарий в ней конечно неправильный)

согласно документу ARM DDI 0029E:

LDM with R15 in transfer list and S bit set (Mode changes)

If the instruction is a LDM then SPSR_<mode> is transferred to CPSR at the same time as R15 is loaded.

 

R15 not in list and S bit set (User bank transfer)

For both LDM and STM instructions, the User bank registers are transferred rather than the register bank corresponding to the current mode.

 

В данной же ситуации симулятор загружает SPSR_irq в CPSR хотя R15 отсутствует в списке регистров.

 

Получается это ошибка симулятора. Или я где-то недопонял?

Share this post


Link to post
Share on other sites
В данной же ситуации симулятор загружает SPSR_irq в CPSR хотя R15 отсутствует в списке регистров.

Данная команда в любом случае должна перегрузить CPSR. Если в списке будет R15, то они обновятся одновременно. Это делается в обработчиках прерываний. Если R15 в списке нету, то выполнение продолжится дальше, но CPSR будет перегружен, при этом сменится режим привилегий и банк регистров на тот, который был указан в SPSR.

 

Вы вообще сами написали этот ASM-файл или сильно переделали чужой? Каким-то очень страшным он мне показался.

Share this post


Link to post
Share on other sites
В данной же ситуации симулятор загружает SPSR_irq в CPSR хотя R15 отсутствует в списке регистров.

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

Странно, но почему-то в моем макете с AT91SAM7S64 при отладке через MT-Link перегрузки CPSR не происходит. Могу попробовать на LPC2119, но не думаю что будет большая разница.

Если в списке будет R15, то они обновятся одновременно. Это делается в обработчиках прерываний.
Пробовал так (через MT-Link). Получалось что загружаются привилегированные регистры после чего переключается режим и SP, LR содержат совсем не то.

Вы вообще сами написали этот ASM-файл или сильно переделали чужой? Каким-то очень страшным он мне показался.

Первый блин :-) Поэтому и прошу советов что можно сделать лучше. Долго смотрел на переключатель контекстов FreeRTOS, потом правил файл порта от MSP430.

Share this post


Link to post
Share on other sites

Напишите комментарии в ASM-файле к каждой команде. И ещё отдельно текстом что вообще должен делать этот файл. (каждая точка входа (Public Name)) Может тогда я смогу помочь исправить. А то ооочень трудно воспринимаемая прога. Код перемешан с какими-то отладочными командами. А вообще, я писал пол года назад на асме что-то похожее. Там была организована мультизадачность с временным разделением. Для каждой задачи был свой стек и сохранялся контекст. Очень быстрая (2 мкс переключение задач), но без каких-либо наворотов. Все задачи писались как обычные процедуры на Си, только прерывание переключения задач на асме. Процессор LPC2138.

Share this post


Link to post
Share on other sites

Вопрос: почему у вас в xcl-файле начальные адреса RAM и ROM совпадают? У 7-ых армов одно общее адресное пространство, поэтому адреса должны быть разными. В LPC-шке ROM начинается с 0x00, а внутренняя RAM с 0x40000000.

Share this post


Link to post
Share on other sites
Напишите комментарии в ASM-файле к каждой команде.
все описал, отладочное убрал.

 

 

Вопрос: почему у вас в xcl-файле начальные адреса RAM и ROM совпадают?
Проект отлаживаю в ОЗУ, файл .xcl из ИАРовского примера для проекта в ОЗУ.

src.zip

Share this post


Link to post
Share on other sites

Всё-равно как-то запутанно. Попробуйте разобраться с моим обработчиком. Может переделаете после этого свой.

 

MODULE MULTI_TASK

 

PUBLIC TASK_IRQ

EXTERN TASK_DATA

RSEG IRQ_STACK

 

RSEG ICODE

CODE32

 

VIC_ORG EQU 0xFFFFF000

VICSoftInt EQU 0xFFFFF018

VICSoftIntClear EQU 0xFFFFF01C

VICVectAddr EQU 0xFFFFF030

 

VIC_TIMER1 EQU 5

T1_ORG EQU 0xE0008000

T1IR EQU 0xE0008000

T1TC EQU 0xE0008008

T1MR0 EQU 0xE0008018

 

 

TASK_IRQ: sub lr,lr,#4

stmdb sp!,{lr}

mrs lr,SPSR

stmdb sp!,{r12,lr}

mov r12,sp ; указатель в стеке IRQ

msr CPSR_cf,lr ; перек. в SYSTEM с разреш. прерыван.

stmdb sp!,{r0-r11,lr}

ldmia r12!,{r9-r11}

stmdb sp!,{r9-r11} ; R12, CPSR, PC

 

ldr lr,=TASK_DATA+8

ldr r11,[lr,#-4] ; TaskCur

str sp,[lr,+r11,LSL #3]

add r11,r11,#1

ldr r10,[lr,#-8] ; TaskMax

cmp r11,r10

bcc TaskIrq50

mov r11,#0

TaskIrq50: str r11,[lr,#-4] ; TaskCur

add lr,lr,r11,LSL #3

TaskIrq60: ldr sp,[lr,#+0] ; указатель SP новой задачи

ldr r11,[lr,#+4] ; период задачи в тиках

ldr lr,=T1_ORG

str r11,[lr, #+T1MR0 - T1_ORG]

mov r11,#0

str r11,[lr, #+T1TC - T1_ORG] ; сброс таймера в 0

mov r11,#0xff

str r11,[lr, #+T1IR - T1_ORG] ; сброс установленных битов

 

ldmia sp!,{r9-r11}

stmdb r12!,{r9-r11} ; R12, CPSR, PC

ldmia sp!,{r0-r11,lr}

mrs r12,CPSR

orr r12,r12,#0xD2

bic r12,r12,#0x0D

msr cpsr_cf,r12 ; перезагрузка LR и SP

ldr r12,=VIC_ORG

mov lr,#(1 << VIC_TIMER1)

str lr,[r12,#+VICSoftIntClear - VIC_ORG]

str lr,[r12,#+VICVectAddr - VIC_ORG]; сброс приоритетов VIC

ldmia sp!,{r12,lr}

msr SPSR_cf,lr

ldmia sp!,{pc}^

 

LTORG

 

END

____________________________________

Из си-шного файла:

 

#define TaskMax 3

 

typedef struct

{ void (*Task)();

xLong Ticks;

} st_task_rec;

 

typedef struct

{ xLong Max;

xLong Cur;

st_task_rec List[TaskMax];

} st_task;

 

st_task TASK_DATA;

 

void RegisterTask(void (*task)(), xInt prior)

{

static const xLong priorTime[speedTaskMax] = {PCLKFREQ/50,PCLKFREQ/100,PCLKFREQ/200};

 

if (TASK_DATA.Max >= TaskMax) return;

if (prior >= SpeedTaskMax) prior = SpeedTaskMax-1;

 

TASK_DATA.List[TASK_DATA.Max].Task = task;

TASK_DATA.List[TASK_DATA.Max++].Ticks = priorTime[prior];

}

 

Вообще, у каждой задачи свой стек, в котором по прерыванию таймера (или по команде симуляции аппаратного прерывания) сначала сохраняется контекст (R0-R12,LR, SP, CPSR_main, PC), затем происходит переключение на стек новой задачи и обратная загрузка контекста и переход на прерванную задачу. При всём этом немного используется IRQ-стек. Иначе нельзя.

Share this post


Link to post
Share on other sites
Всё-равно как-то запутанно. Попробуйте разобраться с моим обработчиком. Может переделаете после этого свой.

Спасибо, изучу.

Сходу нарвался на ошибку:

    sub lr,lr,#4    ; подвинули адрес возврата
    stmdb sp!,{lr}; сохранили его на стеке прерываний
    mrs lr,SPSR    ; взяли CPSR процесса в LR
    stmdb sp!,{r12,lr}; сохранили его и R12
    mov r12,sp     ; указатель в стеке IRQ
    msr CPSR_cf,lr ; перек. в SYSTEM с разреш. прерыван.
            ; а также в THUMB если процесс был в THUMB
            ; тут все и упало

Проблема еще и в том, что scmRTOS написана на С++ и там к данных объектов добраться из АСМа в общем случае нельзя (или настоятельно не рекомендуется - я так понял).

При всём этом немного используется IRQ-стек. Иначе нельзя.
Ну, у меня кажется получилось :-)

Share this post


Link to post
Share on other sites
msr CPSR_cf,lr ; перек. в SYSTEM с разреш. прерыван.

; а также в THUMB если процесс был в THUMB

; тут все и упало

Не, разумеется вы это должны доработать. В моей системе THUMB задачи не использовались. Важна была скорость исполнения, а размер не существеннен. Добавьте сброс THUMB-бита. А команды сохранения и восстановления контекста как бы парные (точнее префиксы stmDB и ldmIA). У вас они почему-то одни и те же. К тому же лишние инкременты указателей после этих команд, когда всё это можно сделать прямо в команде. Кстати, 12 байт используемых в стеке IRQ - это просто смешно как мало.

 

Разбирайтесь. Если что - пишите сюда.

Share this post


Link to post
Share on other sites
Первый блин :-) Поэтому и прошу советов что можно сделать лучше. Долго смотрел на переключатель контекстов FreeRTOS, потом правил файл порта от MSP430.
Еще думаю можно посмотреть на порты uCOS-II для ARM. (http://www.ucos-ii.com/)

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.
Sign in to follow this