Главная » Микроконтроллеры
Призовой фонд
на сентябрь 2017 г.
1. 1000 руб
PCBWay
2. Осциллограф DSO138
Паяльник
3. Тестер компонентов MG328
Паяльник
4. 100 руб.
От пользователей

Распределение памяти между задачами

Существует и еще две важных причины, по которым ОСРВ, приведенная в листинге предыдущей главы, не сможет найти широкого применения. Во-первых, разные задачи могут использовать одни и те же регистры. А при переключении задач РОНы, как и SREG, нужно где-то сохранить. В принципе, этот вопрос можно решить: отвести для каждой задачи свою область памяти и переписывать туда их содержимое. Но такой обработчик потеряет “гибкость”, будет занимать много памяти и медленно выполнятся. Второй, и уже не разрешимой проблемой, окажется то, что в ходе выполнения задачи будет невозможно вызывать подпрограммы. Это легко можно увидеть на следующем примере. Допустим, в задаче 1 встретилась инструкция rcall, после чего адрес возврата из подпрограммы был сохранен в стеке. Через некоторое время возникает прерывание, в работу вмешивается ОСРВ и запускает задачу 2. Если теперь в задаче 2 встреться команда ret, то произойдет переход по последнему адресу, записанному в стеке, т.е. переход в некоторую точку задачи 1. Из всего вышесказанного можно сделать вывод, что для полноценного функционирования ОСРВ, помимо прочих ресурсов, каждая задача должна иметь еще и свой собственный стек для размещения своего контекста (регистров, адресов возврата и т.д.).

ОСРВ, приведенная в листинге ниже, подобно примеру в листинге предыдущей главы также управляет работой двух задач, но с некоторыми изменениями. В ней цикл задержки времени вынесен в отдельную подпрограмму pause, которая теперь может быть доступна для совместного использования. Кроме этого все переменные системы расположены в SRAM. Каждая задача имеет свое адресное пространство памяти данных размером MAMSPACE = 64 б. Задача 1 занимает диапазон адресов 0x060-0x09F, начиная с метки mem1; задача 2 - 0x0A0-0x09F-0x0DF, начиная с mem2.

Состояние памяти двух задач в ОСРВ
Рис.1 Состояние памяти двух задач в ОСРВ
а - во время выполнения задачи 1
б - при переключении контекстов задач
в - во время выполнения задачи 2

Состоянием памяти сразу после инициализации программы показано на рис.1а. В данный момент времени активна задача 1. Дно стека совпадает с самым верхним адресом ее адресного пространства(SP = 0x09F). На рис.1б показано, какие действия производит ОС для переключения контекста задачи 1 на контекст задачи 2, в случае если прерывание произошло, когда PC = 0x0280 и SP = 0x009D, т.е. в ходе выполнения подпрограммы задержки времени. Самое первое, что сделает ОС - это сохранит в стеке текущей задачи все РОНы и SREG. Указатель стека при этом переместится до уровня SP = 0x007A. На самом нижнем уровне будет находиться адрес возврата 0x0106, сохраненный при вызове подпрограммы pause. Следующие 2 байта – адрес возврата 0x0281 после выхода из прерывания. Далее 32 РОНа и SREG. Итого общий размер стека составит 37 б. На следующем шаге происходит сохранение SP задачи 1 в ячейках sp1h:sp1l и загрузка в SP из sp2h:sp2l нового значения указателя стека задачи 2. В ходе первого прерывания это значение после инициализации 0x0281. Теперь из стека восстанавливается контекст второй задачи (32 РОН и SREG) и после команды reti программа продолжает выполняться с метки task2 (PC = 0x0200), что является начальным адресом возврата в задачу 2(рис.2в). После того, как истечет время отведенное задаче 2, ОСРВ таким-же образом передаст управление задаче 1 (сохранит контекст задачи 1, сохранит SP задачи 1, загрузит SP задачи 2, восстановит контекст задачи 2) и т.д.

 .include "m8def.inc"
  
 .equ DELAY    = 100 ;задержка времени
 .equ MEMSPACE = 64  ;размер адресного пространства задачи

 .def temp     = R16 ;регистр для промежуточных операций
 .def mask     = R17 ;временный регистр
 .def cnt      = R18 ;счетчик циклов
 .def templ    = R19 ;регистры для промежуточных операций при
 .def temph    = R20;сохранении и восстановлении адреса возврата

      .dseg
	  .org  0x060 
   mem1:   .byte  MEMSPACE  ;адресное пространство задачи 1 
   mem2:   .byte  MEMSPACE  ;адресное пространство задачи 2  
   sp1h:   .byte  1 ;старший байт указателя стека задачи 1
   sp1l:   .byte  1 ;младший байт указателя стека задачи 1
   sp2h:   .byte  1 ;старший байт указателя стека задачи 2
   sp2l:   .byte  1 ;младший байт указателя стека задачи 1
   tsknum: .byte  1 ;ячейка хранения номера текущей задачи

      .cseg
      .org  0
     rjmp  initial 

      .org  0x0009
     rjmp  service_T0OVER

      .org  0x0020
initial: 
    clr   temp             ;чистка SRAM перед началом работы
	ldi   ZH,high(SRAM_START)
    ldi   ZL,low(SRAM_START)
	ldi   YH,high(SRAM_SIZE)
	ldi   YL,low(SRAM_SIZE)
mcl: st    Z+,temp
	sbiw  YH:YL,1
	brne  mcl
    sbi   DDRB,DDB0     ;установка линии 0 порта B на вывод 
    sbi   DDRB,DDB1     ;установка линии 1 порта B на вывод
    ldi   temp,(1 << CS02)|(1 << CS00)  ;включение таймера 0 с 
    out   TCCR0,temp                ;предделителем  F/1024
    ldi   temp,1 << TOIE0  ;разрешение прерывания по переполнению 
    out   TIMSK,temp     ;таймера 0 (период T = F/1024/256) 
     
    ldi   temp,low(task2)         ;загрузка начального адреса 
	sts   mem2+MEMSPACE-1,temp    ;возврата task2 = 0x0200 на 
	ldi   temp,high(task2)        ;дно стека 0x0DF задачи 2
	sts   mem2+MEMSPACE-2,temp
	ldi   temp,high(mem2+MEMSPACE-36) ;инициализация стека
	sts   sp2h,temp                   ;задачи 2 на SP = 0x0BD
	ldi   temp,low(mem2+MEMSPACE-35)
	sts   sp2l,temp
	ldi   temp,high(mem1+MEMSPACE-1)  ;инициализация стека	
    out   SPH,temp                    ;задачи 1 на SP = 0x09F 
	ldi   temp,low(mem1+MEMSPACE-1)
	out   SPL,temp
    ldi   temp,1     ;заносим номер текущей задачи
	sts   tsknum,temp
	sei              ;глобальное разрешение прерываний
	rjmp  task1      ;переходим к выполнению задачи 1

       .org  0x0100 
task1:                  ;    PC    SP          
     in    temp,PORTB  
     ldi   mask,1 << PB0
     eor   mask,temp   
     out   PORTB,mask
     ldi   cnt,DELAY     
     rcall pause         
     rjmp  task1        

       .org  0x0200
task2:
     in    temp,PORTB  ;0x0200 0x00DF <- Выход из прерывания 1
     ldi   mask,1 << PB1 
     eor   mask,temp
     out   PORTB,mask
     ldi   cnt,DELAY/2 
     rcall pause         
     rjmp  task2 
 
       .org  0x0280
pause:
    dec   cnt         ;0x0280 0x009D <- Прерывание 1
	brne  pause       
	ret
       
       .org  0x0300
service_T0OVER:
    push  R0         ;сохранение контекста текущей задачи
	push  R1
	push  R2
	push  R3
	push  R4 
    push  R5   
    .
	push  R26
	push  R27
	push  R28
	push  R29
	push  R30
	push  R31
    in    temp,SREG
	push  temp
    in    temph,SPH
	in    templ,SPL
	lds   temp,tsknum
	cpi   temp,1
	brne  sr1
	sts   sp1h,temph   ;если прерывание возникло при выполнении   
	sts   sp1l,templ   ;задачи 1, то сохраняем указатель стека 
	lds   temph,sp2h   ;задачи 1 в sp1h:sp1l и заносим во 
	lds   templ,sp2l   ;временные регистры temph:templ указатель 
	ldi   temp,2       ;стека задачи 2
	rjmp  sr2
sr1: sts   sp2h,temph   ;если прерывание возникло при выполнении   
	sts   sp2l,templ   ;задачи 2, то сохраняем указатель стека
	lds   temph,sp1h   ;задачи 2 в sp2h:sp2l и заносим во 
	lds   templ,sp1l   ;временные регистры temph:templ указатель
	ldi   temp,1       ;стека задачи 1
sr2: sts   tsknum,temp
    out   SPH,temph    ;загрузка в стек нового значения                 
	out   SPL,templ    ;из временных регистров temph:templ    
	pop   temp
	out   SREG,temp
	pop   R31
	pop   R30
	pop   R29
	pop   R28
	pop   R27
	pop   R26
    .
	pop   R5
	pop   R4
	pop   R3
	pop   R2
	pop   R1
	pop   R0          ;восстановление контекста следующей задачи
	reti

Выше показан наиболее общий случай, когда контекст каждой задачи сохраняется целиком. В нашем примере, конечно, нет необходимости заботится о сохранении всех 32 регистров. Для работы каждой задачи требуется только 3. Кроме того размер адресного пространства у каждой из задач тоже избыточен поскольку максимальная глубина стека не превысит 8 б.

Перейти к следующей части:

Теги:

Котов Игорь Юрьевич Опубликована: 2012 г. 0 0
Я собрал 0 0
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (0) | Я собрал (0) | Подписаться

Статью еще никто не комментировал. Вы можете стать первым.
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется электрическая мощность?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Программатор Pickit3
Программатор Pickit3
Конструктор - Гитарная педаль Remote Delay 2.5 DC-DC регулируемый преобразователь 1.5-37В 2А с индикатором
вверх