Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вопрос по прерываниям
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Paramon
У меня вопрос:
1) при выполнении __swi возможна ли работа простых __int ?
2) Если невозможна, то как сбросить влаг программного прерывания (__swi), не выходя из самой функции __swi, чтобы разрешить INTы во время её выполнения ? Или что можно ещё сделать.
/проверять флаги __INTов нежелательно/
/ __fiq не предлагать, он уже занят /

(ADuC7024 и AT91SAM7S256)

с уважением PARAMON !
kichkine
Цитата
1) при выполнении __swi возможна ли работа простых __int ?

Из ARM Architecture Reference Manual, инструкция SWI:

if CondidtionPassed(<cond>) then
R14_svc = address of SWI instruction + 4
SPSR_svc = CPSR
CPSR[5:0] = 0b010011; enter Supervisor mode
CPSR[7] = 1; disable IRQ -- прерывания запрещены
PC = 0x08

Цитата
2) Если невозможна, то как сбросить влаг программного прерывания (__swi), не выходя из самой функции __swi, чтобы разрешить INTы во время её выполнения ? Или что можно ещё сделать.


Прерывания запрещены и процессор в режиме Supervisor. Но ведь ничто не мешает нам разрешить прерывания в рег. CPSR (бит I).
Paramon
Цитата(kichkine @ Mar 19 2007, 14:39) *
Из ARM Architecture Reference Manual, инструкция SWI:

if CondidtionPassed(<cond>) then
R14_svc = address of SWI instruction + 4
SPSR_svc = CPSR
CPSR[5:0] = 0b010011; enter Supervisor mode
CPSR[7] = 1; disable IRQ -- прерывания запрещены
PC = 0x08
Прерывания запрещены и процессор в режиме Supervisor. Но ведь ничто не мешает нам разрешить прерывания в рег. CPSR (бит I).


Спасибо огромное kichkine! Хорошо бы ещё незапутаться с вызовом __SWI из разных мест (приложение под ARTX) /будем смотреть и ставить флаг выполнения самого __swi/
abcdefg
Цитата(kichkine @ Mar 19 2007, 14:39) *
Из ARM Architecture Reference Manual, инструкция SWI:
Прерывания запрещены и процессор в режиме Supervisor. Но ведь ничто не мешает нам разрешить прерывания в рег. CPSR (бит I).


А как бы красиво оформить обратную ситуацию - в прерывании возникает необходимость запустить при выходе из прерывания "фоновую задачу"? Фоновой задаче назначить какой-нибудь вектор и выставлять соответствующий бит в VICSoftInt?
Paramon
Цитата(abcdefg @ Mar 20 2007, 16:15) *
А как бы красиво оформить обратную ситуацию - в прерывании возникает необходимость запустить при выходе из прерывания "фоновую задачу"? Фоновой задаче назначить какой-нибудь вектор и выставлять соответствующий бит в VICSoftInt?



Извините не понял высказывания.

Мне требуется такая ситуация:
__swi может быть очень длинным с ветвлением, при его выполнении итак должны работать фоновые задачи (функции). При этом должны работать таймеры!!! и другие устр-ва по прерываниям т.е __int - работает,а __fiq - работает всегда(выбор из таблицы в ШИМ). (Из супервизора НАДО выйти, но непрекращая __swi). из __swi(он у меня вектор) выходить как из обычной вызываемой ф-и.
вход в __swi(он содержит набор своих векторов на каждую процедуру), из любого(даже загружаемого модуля), ну почти как в BIOS
/вот было бы здорово/

С уважением PARAMON!
abcdefg
Цитата(Paramon @ Mar 20 2007, 17:03) *
Извините не понял высказывания.

С уважением PARAMON!


Да это не относится к вашему вопросу, просто в тему вложенных прерываний.
В упрощенном варианте - хочу из обработчика прерывания irq при выходе попадать в обработчик софтового прерывания (который разрешает вложенность прерываний)
Сергей Борщ
Цитата(abcdefg @ Mar 20 2007, 16:14) *
В упрощенном варианте - хочу из обработчика прерывания irq при выходе попадать в обработчик софтового прерывания (который разрешает вложенность прерываний)


Код
#define CONTEXT_SWITCH_INT      VIC_SW

#define    RaiseContextSwitch()                        \
    do                                              \
    {                                               \
        VICSoftInt = (1<<CONTEXT_SWITCH_INT);       \
        VICIntEnable = (1<<CONTEXT_SWITCH_INT);     \
    }                                               \
    while (0) // set flag and enable interrupt
#endif
Оно?

Цитата(Paramon @ Mar 20 2007, 16:03) *
(Из супервизора НАДО выйти, но непрекращая __swi).
Вы путаетесь в понятиях. Вам нужно переключить режим процессора из Supervisor в System. Как это сделать - трудно посоветовать, не зная каким компилятором вы пользуетесь. При этом можно одновременно разрешить прерывания.
Цитата(Paramon @ Mar 20 2007, 16:03) *
вход в __swi(он содержит набор своих векторов на каждую процедуру), из любого(даже загружаемого модуля), ну почти как в BIOS
В IAR это примерно так и реализовано. Ветвление по номеру swi компилятор выполняет сам. Ищите в описании компилятора по ключевому слову swiю
bzx
Цитата(abcdefg @ Mar 20 2007, 17:14) *
Да это не относится к вашему вопросу, просто в тему вложенных прерываний.
В упрощенном варианте - хочу из обработчика прерывания irq при выходе попадать в обработчик софтового прерывания (который разрешает вложенность прерываний)

Компилятор не важен. Это делается через стек. При выходе из irq в стек заносишь указатель, на который хочешь попасть.
Paramon
Цитата(Сергей Борщ @ Mar 20 2007, 21:52) *
Код
#define CONTEXT_SWITCH_INT      VIC_SW

#define    RaiseContextSwitch()                        \
    do                                              \
    {                                               \
        VICSoftInt = (1<<CONTEXT_SWITCH_INT);       \
        VICIntEnable = (1<<CONTEXT_SWITCH_INT);     \
    }                                               \
    while (0) // set flag and enable interrupt
#endif
Оно?

Вы путаетесь в понятиях. Вам нужно переключить режим процессора из Supervisor в System. Как это сделать - трудно посоветовать, не зная каким компилятором вы пользуетесь. При этом можно одновременно разрешить прерывания.
В IAR это примерно так и реализовано. Ветвление по номеру swi компилятор выполняет сам. Ищите в описании компилятора по ключевому слову swiю


(Из супервизора НАДО выйти, но непрекращая __swi). - это просто неправильная фраза, никто никуда сейчас не выходит - мы еще работаем. Извините.
/работаю с Keil uVision3 V3.20a с родным комполятором/
Надо испытать под ARTX:

/ARTX config/ (кусок)
/*--------------------------- os_switch_tasks -------------------------------*/

void os_switch_tasks (P_TCB p_new) __swi (0) {
/* Switch to next task (identified by "p_new"). Saving old and restoring */
/* new context is written in assembly (module: Swi_ARTX.s) */

/////// тут что-то типа:
t_Command=os_tsk_create(Command,0); //что-то нужное
///////


os_runtask->full_ctx = FALSE;
os_runtask = p_new;
p_new->state = RUNNING;
#if (OS_ROBIN == 1)
os_tsk_robin = p_new;
#endif
/* Tsk_Unlock */
OS_UNLOCK();
} /* end of os_switch_tasks */

//то самое нужное
void Command(void) __task
{
.... //какой - то код
}

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

А как бы красиво оформить обратную ситуацию - в прерывании возникает необходимость запустить при выходе из прерывания "фоновую задачу"? -вы наверное это имели ввиду?

Извините если что не так! с уважением PARAMON!
Сергей Борщ
Цитата(Paramon @ Mar 21 2007, 06:57) *
Надо испытать под ARTX:
...
при этом не трогать никакие переключения режимов ядра.
и про разрешение прерывания забыь?
сработает?
Так и не понял чего вы хотели выразить этими фразами и причем тут приведенный вами кусок кода.

Цитата(Paramon @ Mar 21 2007, 06:57) *
А как бы красиво оформить обратную ситуацию - в прерывании возникает необходимость запустить при выходе из прерывания "фоновую задачу"? -вы наверное это имели ввиду?
Что я имел ввиду, то я и отцитировал:
Цитата
В упрощенном варианте - хочу из обработчика прерывания irq при выходе попадать в обработчик софтового прерывания (который разрешает вложенность прерываний)

P.S. Давайте вы попробуете спокойно, обстоятельно, подробно (как для первокласника) и без восклицаний изложить: что вы хотите получить, что вы для этого пытаетесь (если) сделать и что не получается/не понятно.

P.P.S. Старайтесь оставлять в цитатах только самое необходимое для понимания ваших ответов.
Paramon
Цитата(Сергей Борщ @ Mar 21 2007, 11:00) *
Так и не понял чего вы хотели выразить этими фразами и причем тут приведенный вами кусок кода.

Что я имел ввиду, то я и отцитировал:
P.S. Давайте вы попробуете спокойно, обстоятельно, подробно (как для первокласника) и без восклицаний изложить: что вы хотите получить, что вы для этого пытаетесь (если) сделать и что не получается/не понятно.

P.P.S. Старайтесь оставлять в цитатах только самое необходимое для понимания ваших ответов.


требуется собрать макет устройства, пока на базе макеток:
A) AT91SAM7256 (USB,COM,SD/MMC)
cool.gif ADuC7024 (ADC,PWM)
с ADuC всё решено.
с AT91SAM7 сделать возможным загрузку короткого кода из SD/MMC в RAM и его запуск.
Проблемы:
1) работа с SD/MMS (файловая система) - решаю сейчас.(нужно компактное решение)
2) организация вызова необходимых функций из флеш AT91SAM7,запущенным в RAM кодом.
При всём этом обмен между AT91 и ADuC должен быть стабильным.
За основу выбран ARTX/Keil/
Буду рад советам.
Сергей Борщ
Ага, теперь понятнее.
Цитата(Paramon @ Mar 21 2007, 12:48) *
1) работа с SD/MMS (файловая система) - решаю сейчас.(нужно компактное решение)
Поищите по форуму. Я искал недавно и понял что вариантов немного: EFSL, uC/FS. Я смотрел еще вот это: FAT File System Module. С виду довольно компактно, но функции нижнего уровня придется писать самому. Мне за день удалось прикрутить к AT45DB321, вроде даже заработало, но глубоко не проверял. Можете посмотреть как вариант (там есть один баг, должно быть ST_WORD(tbl+510, 0xAA55); вместо *(WORD*)(tbl+510) = 0xAA55;, автору я уже отписал).
Цитата(Paramon @ Mar 21 2007, 12:48) *
2) организация вызова необходимых функций из флеш AT91SAM7,запущенным в RAM кодом.
При всём этом обмен между AT91 и ADuC должен быть стабильным.
Тут видятся два пути: первый - swi, но каждая swi-функция в самом начале должна переключать процессор обратно в system mode и разрешать прерывания, а в самом конце делать обратное переключение. Как оформляются swi в Кейле я не знаю (пользую IAR), но в документации должно быть.
второй путь: зачем swi? Почему бы в фиксированной области флеш не разместить таблицу указателей на функции и вызывать функции через эту таблицу? прерывания запрещаться не будут вообще.
Paramon
Цитата(Сергей Борщ @ Mar 21 2007, 15:39) *
Ага, теперь понятнее.
Поищите по форуму. Я искал недавно и понял что вариантов немного: EFSL, uC/FS. Я смотрел еще вот это: FAT File System Module. С виду довольно компактно, но функции нижнего уровня придется писать самому. Мне за день удалось прикрутить к AT45DB321, вроде даже заработало, но глубоко не проверял. Можете посмотреть как вариант (там есть один баг, должно быть ST_WORD(tbl+510, 0xAA55); вместо *(WORD*)(tbl+510) = 0xAA55;, автору я уже отписал).
Тут видятся два пути: первый - swi, но каждая swi-функция в самом начале должна переключать процессор обратно в system mode и разрешать прерывания, а в самом конце делать обратное переключение. Как оформляются swi в Кейле я не знаю (пользую IAR), но в документации должно быть.
второй путь: зачем swi? Почему бы в фиксированной области флеш не разместить таблицу указателей на функции и вызывать функции через эту таблицу? прерывания запрещаться не будут вообще.


По поводу файловой системы - понятно. Сейчас уже реализую.
Я был по этой ссылке. Баг на определение системных секторов? Незнал ! Большое спасибо!
По поводу __swi - мне казалось удобнее и универсальнее. Код который приведён мной - НЕВЕРНЫЙ!
Наткнулся на пример, правда для LPC21xx. Там есть формирование записей таблиц для этого.
Пока непонятно.Вечером буду разбираться.
Если это будет то,что надо - выложу, иначе последую вашему примеру!

С уважением PARAMON!
Сергей Борщ
Цитата(Paramon @ Mar 21 2007, 15:43) *
Я был по этой ссылке. Баг на определение системных секторов? Незнал ! Большое спасибо!
В функции mkfs. Он проявляется только на процессорах которые умеют обращаться по указателю только на выровненные адреса (ARM в частности).


Цитата(Paramon @ Mar 21 2007, 15:43) *
По поводу __swi - мне казалось удобнее и универсальнее.
Но учтите, что на ветвление по номеру swi тоже расходуется время и еще неизвестно что будет быстрее - доступ через таблицу или swi. А с учетом разрешения вложенных прерываний в режиме supervisor - точно быстрее будет через таблицу.
Paramon
Цитата(Сергей Борщ @ Mar 21 2007, 18:35) *
В функции mkfs. Он проявляется только на процессорах которые умеют обращаться по указателю только на выровненные адреса (ARM в частности).
Но учтите, что на ветвление по номеру swi тоже расходуется время и еще неизвестно что будет быстрее - доступ через таблицу или swi. А с учетом разрешения вложенных прерываний в режиме supervisor - точно быстрее будет через таблицу.


вчера испытывал пример с таблицами - не вышло.
получилось следующее:
//пример. даже не пример а проба
#include <ARTX.H>
OS_TID t_Func1; //
OS_TID t_Func2; //
OS_TID t_Func3;
unsigned int counter;
int par1;
int par2;
void Func2 (void) __task;
void Func3 (void) __task;

void SWI_Handler(int set) __swi(8) //set - потом будет номером ф-ии
//__swi работает короткое время, только для вызова
{
if(set==1) par1++;
if((par1 > par2))
{
t_Func2 = os_tsk_create (Func3,2); // start task 2
}
else if(par1==0xFFFFFFFF)
{
par1=0;
par2=0;
};
}
//
void Func3(void) __task
{
if(par2>=par1) os_tsk_delete_self(); //удаление ф-ии "Func3"
while(1)
{
os_itv_set(50);
os_itv_wait();
};
}
// * Task 1
void Func1 (void) __task {
t_Func1 = os_tsk_self ();
t_Func2 = os_tsk_create (Func2,2);

while (1) {
SWI_Handler(1);
os_dly_wait (1);
};
}
// * Task 2
void Func2 (void) __task {
while (1) {
SWI_Handler(2);
os_dly_wait (5);
}
}

void init(void) __task
{
t_Func1=os_tsk_create(Func1,0);
os_itv_set(5);
os_itv_wait();
os_tsk_delete_self(); //удаление модуля инициализации "init"
}
void main(void)
{
os_sys_init(init); //инициализация модулей
}

через SWI_Handler(2); вызывается ф-я Func3, причём много раз.
после свего исполнения каждый экземпляр удаляется.
Думаю то, что мне надо. Можно с любой точки вызвать свой экземпляр.
под ARTX они работают параллельно.
Пока незнаю как быть с передачей параметров, без глобальных описаний???????
Спасибо вам всем огромное, особенноо вам Сергей Борщ !!!
Пока я это всё непереварю, навряд ли осмелюсь задавать вопросы.

С уважением PARAMON!!!
Сергей Борщ
Цитата(Paramon @ Mar 22 2007, 07:13) *
вчера испытывал пример с таблицами - не вышло.

Странно. Я правда с ARTX не знаком, но предполагал нечто такое:
Код
void (*pFunc_t)(void);
pFunc_t pFuncTable[] =
{
   &Func1, &Func2, &Func3
};

void Task1 (void) __task
{
   for(;;)
   {
      pFuncTable[0]();
      ............
   }

}

Цитата(Paramon @ Mar 22 2007, 07:13) *
void SWI_Handler(int set) __swi(8) //set - потом будет номером ф-ии
Вот здесь мне кажется неправильный подход. У вас уже есть возможность номер фукции задать в аргументе __swi(). В проекте, в котором описаны flash-функции:
Код
void BIOSFunc1Implementation(int param1, int param2)  __swi(0)  // нужный список параметров и возвращаемое значение
{

}
int  BIOSFunc2Implementation(void)  __swi(1)
{

}
.........
//и так все функции.

в проекте, из которого функции вызываются:
Код
extern void  BIOSFunc1(int, int)  __swi(0);
extern int  BIOSFunc2(void)  __swi(1);

/ * Task 1
void Func1 (void) __task {
........
int a;
while (1) {
  BIOSFunc1(100,200);
  os_dly_wait (1);
  a = BIOSFunc2();
};
Paramon
Цитата(Сергей Борщ @ Mar 22 2007, 12:22) *
Странно. Я правда с ARTX не знаком, но предполагал нечто такое:
Код
void (*pFunc_t)(void);
pFunc_t pFuncTable[] =
{
   &Func1, &Func2, &Func3
};

void Task1 (void) __task
{
   for(;;)
   {
      pFuncTable[0]();
      ............
   }

}

Вот здесь мне кажется неправильный подход. У вас уже есть возможность номер фукции задать в аргументе __swi(). В проекте, в котором описаны flash-функции:
Код
void BIOSFunc1Implementation(int param1, int param2)  __swi(0)  // нужный список параметров и возвращаемое значение
{

}
int  BIOSFunc2Implementation(void)  __swi(1)
{

}
.........
//и так все функции.

в проекте, из которого функции вызываются:
Код
extern void  BIOSFunc1(int, int)  __swi(0);
extern int  BIOSFunc2(void)  __swi(1);

/ * Task 1
void Func1 (void) __task {
........
int a;
while (1) {
  BIOSFunc1(100,200);
  os_dly_wait (1);
  a = BIOSFunc2();
};



У меня подобное вчера как раз и не получилось!
Формат талицы на асме из примера мой компилятор отказался понимать, а каков он должен быть я пока незнаю! Стал обходить другим путём - вышло то, что я описал.
os_tsk_create - "генерим" функцию появляется task
os_tsk_delete_self - удаляем task и функции нет.
Сегодня попробую испытать с вашим кодом - он намного красивей!
Paramon
Цитата(Paramon @ Mar 22 2007, 12:59) *
У меня подобное вчера как раз и не получилось!
Формат талицы на асме из примера мой компилятор отказался понимать, а каков он должен быть я пока незнаю! Стал обходить другим путём - вышло то, что я описал.
os_tsk_create - "генерим" функцию появляется task
os_tsk_delete_self - удаляем task и функции нет.
Сегодня попробую испытать с вашим кодом - он намного красивей!



Кажется получилось:

#include <ARTX.H>
OS_TID t_Func1; //
OS_TID t_Task2; //
OS_TID t_Task3;
//unsigned int counter;
void Func2 (int par) __swi(8);
void Func3 (void) __swi(9);
void Task2 (int par) __task;
void Task3 (void) __task;

// * Func 2
void Func2 (int par) __swi(8)
{
t_Task2 = os_tsk_create_ex(Task2,2,par);
}

// * Task 2
void Task2 (int par) __task
{
while (par<0xFFFFFFFF)
{
os_dly_wait (5);
par++;
};
os_tsk_delete_self();
}

// * Func 3
void Func3(void) __swi(9)
{
t_Task2 = os_tsk_create(Task3,2);
}
// * Task 3
void Task3 () __task
{
while(1)
{
os_itv_set(50);
os_itv_wait();
};
}
// * Func 1
void Func1 (void) __task {
t_Func1 = os_tsk_self ();
while (1) {
Func2(200);
os_dly_wait (1);
Func3();
os_dly_wait (1);
};
}
void init(void) __task
{
t_Func1=os_tsk_create(Func1,0);
os_itv_set(5);
os_itv_wait();
//
os_tsk_delete_self(); //
}
//
void main(void)
{
os_sys_init(init); //
}

Func2 и Func3 как и положено в асме:

49: Func2(200);
0x000805F8 20C8 MOV R0,#0xC8
0x000805FA DF08 SWI 0x08
50: os_dly_wait (1);
0x000805FC 2001 MOV R0,#0x01
0x000805FE F000 BL os_dly_wait(0x00080DC4) - Part #1
0x00080600 FBE1 BL os_dly_wait(0x00080DC4) - Part #2
51: Func3();
0x00080602 DF09 SWI 0x09
52: os_dly_wait (1);
0x00080604 2001 MOV R0,#0x01
0x00080606 F000 BL os_dly_wait(0x00080DC4) - Part #1
0x00080608 FBDD BL os_dly_wait(0x00080DC4) - Part #2

све TASKи вазываются и работают.
и с режимом ядра ничего ненадо делать!
SWI короткий!!!
передать параметр в ф-ю удалось! Вернуть некому, SWI давно завершён!
Наверное проще будет передавать
указатель!

Спасибо вам огромное!!!
С уважением PARAMON!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.