Перейти к содержанию
    

После чтения SPSR_c , устанавливаются биты #F_BIT | #I_BIT , после записывается в стек и в регистр CPSR_c

Режим не переключали, он сам переключается , в режим XXX (неопределенный а в эту обработку программа пришла из вектора 0х10 )?

    mrs    r14,       SPSR               @ Загрузить в LR_abt копию сохраненого статуса программы
    stmfd  r13!,     {r14}               @ Сохранить в стеке ABT регистр LR_abt
    orr    r14,       r14, #F_BIT        @ запрет прерываний, побитовое ИЛИ r14 = r14 | #F_BIT | #I_BIT
    orr    r14,       r14, #I_BIT
    msr    CPSR_c,    r14                @ запись в регистр статуса, переключение в режим XXX
    stmia  r0!,      {r13-r14}           @ Сохранить в regs_temp+56 регистры SP_XXX и LR_XXX
    orr    r0,       #F_BIT              
    orr    r0,       #I_BIT              
    orr    r0,       #ABT_MODE           
    msr    CPSR_c,    r0                 @ Записать в CPSR r0, переключение в режим ABT

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

После чтения SPSR_c , устанавливаются биты #F_BIT | #I_BIT , после записывается в стек и в регистр CPSR_c

Режим не переключали, он сам переключается , в режим XXX (неопределенный а в эту обработку программа пришла из вектора 0х10 )?

SPSR сохраняется на стеке до того, как устанавливаются биты F и I. Режим XXX не неопределенный, а тот, в котором случилось исключение. Т.е. получается так: XXX->ABT->XXX->ABT->XXX.

 

    orr    r0,       #F_BIT              
    orr    r0,       #I_BIT              
    orr    r0,       #ABT_MODE           
    msr    CPSR_c,    r0                 @ Записать в CPSR r0, переключение в режим ABT

Во-первых, Вы пропустили инициализацию R0, во-вторых, лучше бы найти "волшебное слово" для операции OR в ассемблере, чем плодить ненужные инструкции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вам, случайно не встречался пример обработки FIQ ? :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вам, случайно не встречался пример обработки FIQ ? :)

Что значит "случайно встречался"? :) Когда надо было - писал.

В общем случае ничем не отличается от IRQ, кроме наличия теневого банка старших регистров.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сделайте замечания что, тут я не правильно понял в irq обработчике, :)

Еще вопрос по fiq , теневой регистр, вроде не мало прочел, не где это не встречалось , это R8 -R14

что в них сохраняется, тоже что и RL ?

@----------------------------------------------------------------------------------------
IRQ_handler:
sub	  lr,		 lr, #4			@ LR_IRQ - 4
stmfd sp!,	   {r0, r3, lr}	   @ сохранить в стеке IRQ, регистры R0 R1 и LR
ldr	  r0, =	   AIC_BASE		  @ чтение из AIC_BASE и запись в регистр R0
ldr	  r1,		[r0, #AIC_IVR]	 @ чтение из r0 +  #AIC_IVR и запись в регистр R1 вектора прерываний
mrs	  r0,		 SPSR			  @ Запись в регистр R0 Сохраненого Статуса 	SPSR
stmdb sp!,	   {r0}			   @ сохранить в стеке регистр R0 (статус до прервания)
mrs	  r0,		 CPSR			  @ Запись в регистре R0, и возврат в режим который был до прерывания
orr	  r0,		 r0, #SYS_MODE	 @ Логическое ИЛИ регистра R0 с #SYS_MODE с сохранением в R0
msr	  CPSR,	   r0				@ переключение ядра, в Системный режим
stmdb sp!,	   {r2, r3, r4, r5, r6, r7, r8, r9, r10, fp, ip, lr}@ сохранить в стеке SyS регистры r2, r3, r4, r5, r6, r7, r8, r9, r10, fp, ip, lr
mov	  lr,		 pc				@ Копировать в LR регистр, регистр r14 + 0х04
bl	  r1							@ Переход на вектор программы обработки прерывания
ldmia sp!,	   {r2, r3, r4, r5, r6, r7, r8, r9, r10, fp, ip, lr}@ Прочитать из стека регистры r2, r3, r4, r5, r6, r7, r8, r9, r10, fp, ip, lr
mrs	  r0,		 CPSR			  @ сохранить в регистре R0 текущий статус
bic	  r0,		 r0, #SYS_MODE	 @ Логическая операция AND NOT регистра R0 и #SYS_MODE
orr	  r0,		 r0, #IRQ_MODE	 @ Логическое ИЛИ регистра R0  и  #IRQ_MODE
msr	  CPSR,	   r0				@ Запись в регистр CPSR регистр R0 и переключение ядра в IRQ_mode,
ldr	  r0, =	   AIC_BASE		  @ чтение из AIC_BASE и запись в регистр R0 (базовый адрес AIC)
str	  r0,		[r0, #AIC_EOICR]   @ сохранить R0 по адресу R0 + #AIC_EOICR  и  сброс прерывания
ldmia sp!,	   {r0}			   @ чтение из стека и запись в R0 (статус до прерывания)
msr	  SPSR,	   r0				@ запись в SPSR регистр R0 (возврат статуса до прерывания)
ldmia sp!,	   {r0, r3, pc}^	  @ запись в PC значения сохраненого, в момент возникновения прерывания и востановление регистров r0 r3, обновить CPSR
@----------------------------------------------------------------------------------------

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сделайте замечания что, тут я не правильно понял в irq обработчике, :)

Вроде все правильно поняли, только вот обработчик - дрянь :(

 

Еще вопрос по fiq , теневой регистр, вроде не мало прочел, не где это не встречалось , это R8 -R14

что в них сохраняется, тоже что и RL ?

Теневые регистры FIQ - R8-R12 (R13 и R14 и так у всех свои). В них ничего не сохраняется, они просто существуют только в режиме FIQ, из других режимов к ним доступа нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

>вот обработчик - дрянь

где бы посмотреть как он должен работать правильно, или что лучше изменить ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

где бы посмотреть как он должен работать правильно, или что лучше изменить ?

В приведенном вами коде выполняется несколько абсолютно бессмысленных действий:

1. Ручное чтение AIC_IVR

2. Переход в режим SYS с запрещенными прерываниями

3. Сохранение всех подряд регистров при вызове подпрограммы

 

Теперь как все это исправить:

 

1. Если уж у AIC есть механизм автовекторинга, то грех его не использовать:

    ldr    pc, RESET_ADDR
    ldr    pc, UNDEF_ADDR
    ldr    pc, SWI_ADDR
    ldr    pc, PREFETCH_ABORT_ADDR
    ldr    pc, DATA_ABORT_ADDR
    .word    0
    ldr     pc,[pc,#-0xF20]; IRQ
    ldr     pc,[pc,#-0xF20]; FIQ
RESET_ADDR:          .word    RESET_handler
UNDEF_ADDR:          .word    UNDEF_handler
SWI_ADDR:            .word    SWI_handler
PREFETCH_ABORT_ADDR: .word    PREFETCH_ABORT_handler
DATA_ABORT_ADDR:     .word    DATA_ABORT_handler

Т.е. сразу, первой же командой, переходим на адрес из AIC_IVR.

 

2. Если Вы не планируете использовать вложенные прерывания, то можно на этом остановитться, и оформлять обработчики стандартно:

RVCT: __irq void handler(void);
GCC: void handler(void) __attribute__ ((interrupt ("IRQ")));
и т.д.

 

2a. Если же нужны вложенные прерывание, то каждое из них снабжаем своей оберткой:

irq_wrapper
; Модифицируем и сохраняем LR
	sub		r14, r14, #0x04
	stmfd	sp!, {r14}

; Сохраняем SPSR и r0 на стеке IRQ
	mrs		r14, SPSR
	stmfd	sp!, {r0, r14}

; Включаем прерывания и переключаемся в режим SYS
	mrs		r14, CPSR
	bic		r14, r14, #I_BIT
	orr		r14, r14, #ARM_MODE_SVC
	msr		CPSR_c, r14

; Сохраняем только нужные регистры на стеке USER/SYS
	stmfd	sp!, {r1-r3, r12, r14}

; Вызываем C-обработчик
	bl		irq_handler

; Восстанавливаем регистры
	ldmfd	sp!, {r1-r3, r12, r14}

; Запрещаем прерывания, переключаемся в режим IRQ
	mrs		r0, CPSR
	bic		r0, r0, #ARM_MODE_SYS
	orr		r0, r0, #I_BIT :OR: ARM_MODE_IRQ
	msr		CPSR_c, r0

; Извещаем AIC об окончании обработки прерывания
	ldr		r0, =AT91C_BASE_AIC
	str		r0, [r0, #AIC_EOICR]

; Восстанавливаем SPSR_irq и r0 из стека IRQ
	ldmfd	sp!, {r0, r14}
	msr		SPSR_cxsf, r14

; Загружаем в PC модифицированный LR и переключаем режим
	ldmfd	sp!, {pc}^

В этом случае C-обработчик будет обычной процедурой:

void handler(void);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В инструкции msr SPSR_cxsf, r14 есть флаги или модификаторы, не знаю как правильно называются.

Флаг C разрешает модифицировать только биты 0 - 7,флаг X разрешает модифицировать только биты 8 - 15,s 16 - 23,f24-31.

когда они все установлены, разрешено модифицировать все биты статуса ядра, а зачем их устанавливать все?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

когда они все установлены, разрешено модифицировать все биты статуса ядра, а зачем их устанавливать все?

Ну, восстановить-то SPSR мы должны полностью.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А в чем будет разница, если не устанавливать cxsf ? :)

 msr SPSR ,  r14

Изменено пользователем sergey sva

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А в чем будет разница, если не устанавливать cxsf ? :)

 msr SPSR ,  r14

Во-первых, написать msr SPSR , r14 Вам нормальный ассемблер не позволит, заставив указать хотя бы одно поле. А если позволит, то сам сделает cxsf.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В приведенном вами коде выполняется несколько абсолютно бессмысленных действий:

1. Ручное чтение AIC_IVR

2. Переход в режим SYS с запрещенными прерываниями

 

По п.1. Ручное чтение AIC_IVR не такое уж зло. При этом достаточно написать один обработчик прерываний для всех функций прерываний, а не обрамлять каждую из них соответствуюшим кодом.

 

По п.2 Переход в режим SYS с запрещенными прерываниями. Так и вы тоже самое делаете в приведенном примере для вложенных прерываний.

 

Кстати, как то набрел на такой обработчик, который короче и быстрее, но требует 128 байт в irq стеке:

;16 instructions (16*8) = 128 bytes in irq_stack
;40 bus cycles
IRQ_Handler_Entry:
  sub         lr, lr, #4                    
  stmfd       sp!, {r4-r6, lr}             
  mrs         r4, SPSR                      
  ldr         r5, =AT91C_BASE_AIC           
  ldr         r6, [r5, #AIC_IVR]            
  str         r6, [r5, #AIC_IVR]            
  nop                                       
  msr         CPSR_c, #ARM_MODE_SYS         
  stmfd       sp!, {r0-r3, r12, lr}         
  mov         lr, pc                        
  bx          r6                            
  
  ldmia       sp!, {r0-r3, r12, lr}         
  msr         CPSR_c, #I_BIT | ARM_MODE_IRQ 
  str         r0, [r5, #AIC_EOICR]          
  msr         SPSR_cxsf, r4                 
  ldmia       sp!, {r4-r6, pc}^             
;; using more IRQ stack... the linker config file may
;; have to be fixed
;
    ENDP

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если не ошибаюсь, то в этом обработчике, переход на вектор прерывания будет с выключенными прерываниями,

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

А для чего это перезапись?

  ldr         r6, [r5, #AIC_IVR]            
  str         r6, [r5, #AIC_IVR]

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если не ошибаюсь, то в этом обработчике, переход на вектор прерывания будет с выключенными прерываниями,

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

А для чего это перезапись?

  ldr         r6, [r5, #AIC_IVR]            
  str         r6, [r5, #AIC_IVR]

 

Ошибаетесь. Переход на функцию обработки прерывания происходит при разрешенных прерываниях (мы же переключились в SYS режим).

 

При чтении по AT91C_BASE_AIC->AIC_IVR в r6 загружается адрес функции обработки прерывания. А запись туда же - сброс AIC'a, чтобы он мог обрабатывать последующие прерывания.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...