|
Критическия секция, оцените и выскажите своё мнение |
|
|
|
Dec 12 2007, 12:13
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
sam7x + arm-elf-gcc Решил этот вопрос вынести в отдельную тему. По совету Сергея Борща переделал критические секция из FreeRTOS для себя. Так как переделовать пришлось код на асме, а в асме я позорно слаб, поэтому просьба покритиковать если что. На какие вещи опирался. Сделал дизасм своего проекта и увидел, что переменная переданная в функцию в конечном счёте оказывается в R0 до выполнения кода функции. Поэтому значение CSPR регистра я сохраняю и соответсвенно восстанавливаю по адресу хранящемуся в R0. И ещё меня смущает одна вещь, собрал проект с оптимизацией -Os. Естественно никакой передачи параметров в функцию нет, но указатель на переменную всё равно оказался в R0 Но в тоже время я вижу что SP и R0 имеют всегда одинаковое значение до начала выполнения тела функции. Верно ли моё наблюдение про R0. И если верно ли оно для оптимизированного кода. хидерник Код typedef uint32_t atomic_t;
void StartAtomic(atomic_t volatile *pAtomic);
void EndAtomic(atomic_t volatile *pAtomic);
#define ATOMIC_SECTION_ENTER {volatile atomic_t __atomic; StartAtomic(&__atomic); #define ATOMIC_SECTION_LEAVE EndAtomic(&__atomic);} сишник Код void StartAtomic(atomic_t volatile *pAtomic) { /* Disable interrupts as per portDISABLE_INTERRUPTS(); */ asm volatile ( "STMDB SP!, {R1} \n\t" /* Push R1. */ "MRS R1, CPSR \n\t" /* Get CPSR. */ "STR R1, [R0] \n\t" "ORR R1, R1, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "MSR CPSR, R1 \n\t" /* Write back modified value. */ "LDMIA SP!, {R1}" ); /* Pop R1. */ }
void EndAtomic(atomic_t volatile *pAtomic) { asm volatile ( "STMDB SP!, {R1} \n\t" /* Push R1. */ "LDR R1, [R0] \n\t" "MSR CPSR, R1 \n\t" /* Write back modified value. */ "LDMIA SP!, {R1}" ); /* Pop R1. */ } З.Ы. Работает уже почти час. Пока живёт.
Сообщение отредактировал xelax - Dec 12 2007, 12:15
|
|
|
|
|
 |
Ответов
|
Dec 12 2007, 12:39
|

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

|
А почему бы не попросить StartAtomic возвращать предыдущее значение CPSR вместо запоминания его? И при выходе передавать не адрес, а само значение. Согласно APCS ( ARM Procedure Call Standart), значение интегрального типа возвращается в R0. К тому же функция должна сохранять только R4-R11, а R1 можно не сохранять. Код typedef uint32_t atomic_t; atomic_t volatile void StartAtomic(); void EndAtomic(atomic_t volatile Atomic); #define ATOMIC_SECTION_ENTER {volatile atomic_t __atomic = StartAtomic(); #define ATOMIC_SECTION_LEAVE EndAtomic(__atomic);} сишник Код atomic_t volatile StartAtomic() { /* Disable interrupts as per portDISABLE_INTERRUPTS(); */ asm volatile ( "STMDB SP!, {R1} \n\t" /* Push R1. */ "MRS R0, CPSR \n\t" /* Get CPSR. */ "ORR R1, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "MSR CPSR, R1 \n\t" /* Write back modified value. */ "LDMIA SP!, {R1}" ); /* Pop R1. */ }
void EndAtomic(atomic_t volatile Atomic) { asm volatile ( "STMDB SP!, {R1} \n\t" /* Push R1. */ "MSR CPSR, R1 \n\t" /* Write back modified value. */ "LDMIA SP!, {R1}" ); /* Pop R1. */ } Только замечу, что этот код портит все остальные флаги в CPSR, может вылезти в любой момент. Надо бы в сохраненном значении маскировать все флаги. Подумать, чтобы при выходе одной командой AND включались только нужные прерывания.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 12 2007, 13:01
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
Цитата(Сергей Борщ @ Dec 12 2007, 15:39)  А почему бы не попросить StartAtomic возвращать предыдущее значение CPSR вместо запоминания его? И при выходе передавать не адрес, а само значение. Согласно APCS ( ARM Procedure Call Standart), значение интегрального типа возвращается в R0. К тому же функция должна сохранять только R4-R11, а R1 можно не сохранять. Не понял, зачем мне R4-R11 в стек сохранять, если я к ним не обращаюсь??? А по поводу возвращения из функции тоже не понятно. Что в return указывать? Цитата(Сергей Борщ @ Dec 12 2007, 15:39)  Только замечу, что этот код портит все остальные флаги в CPSR, может вылезти в любой момент. Надо бы в сохраненном значении маскировать все флаги. Подумать, чтобы при выходе одной командой AND включались только нужные прерывания. Согласен, надо исправить.
|
|
|
|
|
Dec 12 2007, 14:35
|

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

|
Цитата(xelax @ Dec 12 2007, 15:01)  Не понял, зачем мне R4-R11 в стек сохранять, если я к ним не обращаюсь??? Это я к тому, что R1 сохранять не нужно. Цитата(xelax @ Dec 12 2007, 15:01)  А по поводу возвращения из функции тоже не понятно. Что в return указывать? Хороший вопрос. Я не изучал еще его инлайн-ассемблер, не знаю как сказать, что результат в R0. Если бы это был WinAVR, я бы написал что-то вроде Код inline static atomic_t volatile StartAtomic() { register atomic_t result asm ("r0"); asm volatile ( "MRS R0, CPSR \n\t" /* Get CPSR. */ "ORR R1, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "MSR CPSR, R1 \n\t" /* Write back modified value. */ :"=r" (result) : :R1 ); return result; } Ха, а там есть где развернуться: ARM GCC Inline Assembler Cookbookтогда Код inline static atomic_t volatile StartAtomic() { asm volatile ( "MRS %0, CPSR \n\t" "ORR %1, %0, #0xC0 \n\t" "MSR CPSR, %1 \n\t" "ORR %0, %0, #0xFFFFFF3F \n\t" // mask all, but int bits :"=r" (result) : :"r" ); return result; } inline static void EndAtomic(atomic_t volatile Atomic) { asm volatile ( "MRS %1, CPSR \n\t" "AND %1, %1, %0 \n\t" "MSR CPSR, %1 \n\t" : :"=r" (Atomic) :"r" ); } Кажется так... По документику - только сейчас обратил внимание, что это стандарт на вызовы ARM<->THUMB (ATPCS). Для ARM<->ARM есть свой стандарт APCS, для THUMB<->THUMB - TPCS. Они описаны тут: ARM Software Development Toolkit. Reference Guide
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
Сообщений в этой теме
xelax Критическия секция Dec 12 2007, 12:13  xelax Цитата(xelax @ Dec 12 2007, 16:01) Не пон... Dec 12 2007, 14:32 xelax К стати при оптимизации -Os, в R1 не замечал, а во... Dec 12 2007, 15:20 Сергей Борщ Цитата(xelax @ Dec 12 2007, 17:20) К стат... Dec 12 2007, 16:12 Alex03 По поводу масок флагов вы перемудрили. В ARM всё у... Dec 13 2007, 06:51 Сергей Борщ Цитата(Alex03 @ Dec 13 2007, 08:51) По по... Dec 13 2007, 12:32
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|