Jump to content
    

Есть ни что иное, как запрещение прерываний на время окончания записи в ЕЕПРОМ
Внимательно читайте даташит и включайте голову. Это запрещение прерываний на две команды запуска процесса записи, 4 такта.

В IAR EWAVR 5.50 в файле eeprom.s90 нет запрещений прерываний на время ожидания окончания записи в ЕЕПРОМ
В IAR EWAVR 5.50 есть ключевое слово __eeprom. eeprom.s90 пора забыть еще в версии 1.26. Ждать окончания записи можно и с разрешенными прерываниями.

Share this post


Link to post
Share on other sites

Внимательно читайте даташит и включайте голову. Это запрещение прерываний на две команды запуска процесса записи, 4 такта.

Про пример из даташита - согласен. В примере как раз прерывания отключаются на время запуска процесса записи в ЕЕПРОМ.

Но в файле eeprom.s90 как раз прерывания отключаются на время окончания записи в ЕЕПРОМ:

;----------------------------------------------------------

; ?eewait

;

; Wait for previous eeprom write operation to complete

;

; SIZE: 6 bytes

 

RSEG CODE:CODE:NOROOT(1)

?eewait:

CLI

SBIS EECR,EEWE ; Loop until previous write is completed

RET

OUT SREG,T0

RJMP ?eewait

В IAR EWAVR 5.50 есть ключевое слово __eeprom. eeprom.s90 пора забыть еще в версии 1.26.

Неправильно. Все переменные, которые объявлены ключевым словом __eeprom при компиляции для работы с областью памяти ЕЕПРОМ используют файл

eeprom.s90

Ждать окончания записи можно и с разрешенными прерываниями.

Если бы не наступал на эти грабли - не поднимал бы вопрос. Без запрещения прерываний на время окончания записи есть вероятность некорректной записи данных в область ЕЕПРОМ

Edited by quarter2

Share this post


Link to post
Share on other sites

Неправильно. Все переменные, которые объявлены ключевым словом __eeprom при компиляции для работы с областью памяти ЕЕПРОМ используют файл

eeprom.s90

Не совсем так - они используют функции из библиотеки. Возможно, источником при компиляции библиотеки является этот самый eeprom.s90. Если вы добавите этот файл в проект, то его функции заменять одноименные библиотечные. Давно не пользуюсь ИАРом для AVR, не могу посмотреть что он там берет из библиотеки. Посмотрел старый проект - использовался компилятор версии 2.28, прерывания мною не запрещались, прерывания шли довольно активно, сбоев при записи не было.

Без запрещения прерываний на время окончания записи есть вероятность некорректной записи данных в область ЕЕПРОМ
Прерывания тут не при чем - никогда не держу прерывания запрещенными во время записи и ни разу не нарывался на некорректную запись. Возможно вы используете (хотя бы и на чтение) __eprom-переменные в прерываниях, в этом случае - да, будут проблемы. Но это уже не проблема прерываний, а неверное архитектурное решение.

Share this post


Link to post
Share on other sites

Не совсем так - они используют функции из библиотеки. Возможно, источником при компиляции библиотеки является этот самый eeprom.s90. Если вы добавите этот файл в проект, то его функции заменять одноименные библиотечные.

На IAR EWAVR только что откомпилил простенькую программку с записью в ЕЕПРОМ, при это файл eeprom.s90 в проект не включал. В дебаг-режиме увидел, что линкер точно подставляет в выходной код строки из C:\Program Files\IAR Systems\Embedded Workbench 5.5\avr\src\lib\eeprom.s90

Возможно вы используете (хотя бы и на чтение) __eprom-переменные в прерываниях, в этом случае - да, будут проблемы. Но это уже не проблема прерываний, а неверное архитектурное решение.

Нет, в прерываниях __eprom-переменные не использую. При этом ЕЕПРОМ случайным образом, то пишется правильно, то с ошибками. Если включаю в проект файл eeprom.s90, в котором отключаются прерывания - данные в ЕЕПРОМ пишутся абсолютно правильно.

Share this post


Link to post
Share on other sites

Здравствуйте.

scmRTOS работает на ATxmega128A1 (спасибо ReAl за подсказки).

Пока в контексте сохраняются не все RAMP регистры (пока не нужны).

Возникли трудности с многоуровневым контроллером прерываний. Критические секции вставил и в SYS_TIMER_CRIT_SECT() и в обёртки TISRW/TISRW_SS. Уровни всех прерываний установлены LO, при установке уровня прерывания системного таймера MED через пару секунд все перестает работать.

У кого какие мысли по этому поводу?, как заставить ОСь работать с различными уровнями прерываний?

 

Share this post


Link to post
Share on other sites

Добавил сохранение в контекст RAMPD и RAMPX.

Проблему прерываний решил установкой уровня программного прерывания "HI".

Возможно, есть и другие решения …, предположительно два … )

Share this post


Link to post
Share on other sites

Возникли трудности с многоуровневым контроллером прерываний. Критические секции вставил и в SYS_TIMER_CRIT_SECT() и в обёртки TISRW/TISRW_SS. Уровни всех прерываний установлены LO, при установке уровня прерывания системного таймера MED через пару секунд все перестает работать.

У кого какие мысли по этому поводу?, как заставить ОСь работать с различными уровнями прерываний?

Надеюсь, доберусь до этого где-то в середине марта.

Раньше никак, хотя всё думал «ну вот в ближайшие выходные».

 

Share this post


Link to post
Share on other sites

Вопрос к разработчикам scmRTOS:

1. почему исходники не содержат __watchdog_reset() хотя бы через #define ?

каждый раз после апдейта приходится практически во всех файлах после while и for вставлять __watchdog_reset()

2. было бы неплохо внести дополнения в описание класса process:

template<TPriority pr, size_t stack_size, size_t rstack_size>

class process : public TBaseProcess

{

public:

INLINE_PROCESS_CTOR process();

 

int StackFree() {

word Free = 0;

for(;;) { // stack always has non-0xAB items.

if( Stack[Free] != 0xAB )

return Free;

++Free;

}

}

 

int StackUsed() { return stack_size - StackFree(); }

 

OS_PROCESS static void exec();

 

private:

stack_item_t Stack [stack_size/sizeof(stack_item_t)];

stack_item_t RStack[rstack_size/sizeof(stack_item_t)];

};

 

template<TPriority pr, uint16_t stack_size, uint16_t rstack_size>

process<pr, stack_size, rstack_size>::process() : TBaseProcess( &Stack[stack_size/sizeof(stack_item_t)]

, &RStack[rstack_size/sizeof(stack_item_t)]

, pr

, reinterpret_cast<void (*)()>(exec)

#if scmRTOS_DEBUG_ENABLE == 1

, Stack

, RStack

#endif

)

{

stack_item_t *pDst = Stack;

word Size = StackPointer - Stack;

while(Size)

{

*pDst++ = 0xAB;

--Size;

}

}

 

т.к. StackUsed() и StackFree() очень сильно помогают при отладке

Share this post


Link to post
Share on other sites

1. почему исходники не содержат __watchdog_reset() хотя бы через #define ?

каждый раз после апдейта приходится практически во всех файлах после while и for вставлять __watchdog_reset()

1. Назачем нужен WDT, который тупо сбрасывается во всех цилах?

2. Где в потрохах scmRTOS есть циклы, в которых управление задерживается на время, критичное с точки зрения успевания сбросить WDT ?

 

2. было бы неплохо внести дополнения в описание класса process:
Контроль стеков и профилировщик добавлены в ветке репозитория branches/pre-v400, которая в скором времени превратится в scmRTOS v4.00

 

Share this post


Link to post
Share on other sites

Здраствуйте.

Попробовал недавно scmRTOS - понравилось, но толку...для xmeg поддержки нет, а хотелось бы.

Появилось желание перенести версию 3.10 на хмегу. Но возникло столько вопросов и непонятных

моментов, что кажется хотелки так хотелками и остануться...

Попытаюсь здесь изложить моменты которые, как мне кажется нужно поменять в версии и

вызывающие у меня сомнения.

хотелось бы увидеть критику/советы как сделать лучше/как делать не надо, тд и тп.

 

Общие для разных схем переключения контекста моменты.

1. Функции SetDataSP/GetDataSP:

 

Заменить на (для начала сгодится, хотя лишний call/ret, но как лучше не нашёл):

GetDataSP:
    mov        R16, R28
    mov        R17, R29
    ret
SetDataSP:
    mov        R29,R17
    mov        R28,R16
    ret

 

и соотв.

 

extern "C" {
    TStackItem* GetDataSP();
};

extern "C" {
    void SetDataSP(TStackItem* sp);
};

 

2. Добавить в контекст RAMP_XYD. С этим понятно.

3. Были тут высказаны идеи о включении в контекст

регистра разрешённых прерываний, но мне кажется что это необязательно.

Или нет?

 

I. Схема переключения контекста по прерыванию.

 

1. Добавить запрет прерыванию после перехода на вектор ContextSwitcher_ISR,

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

была как можно короче?

 

     save_SREG
     cli; запрет прерываний
     save_SP
     save_regs
     save_SFRS
     
;cli; запрет прерываний или здесь правильней?
     mov   r16,r28                    ; load current stack pointer
     mov   r17,r29
                            ; as argument
     
     xcall OS_ContextSwitchHook          ;
     mov   r28,r16                    ; set next stack pointer
     mov   r29,r17                    ; from return value

 

2. Ещё совершенно непонятный для меня момент: каким уровнем лучше расположить

ContextSwitcher_ISR? Или не это непринципиально, а атомарность переключения?

 

С этой схемой как бы всё. Или нет? Тогда что я упустил?

 

II. Схема с прямой передачей управления.

 

1. Прерывания с TISRW_SS

 

Если я правильно понял, то в мегах выход из прерывания при переключении

реализуется таким путём:

 

переход на вектор прерывания->
функция прерывания->
вариант 1: перепланировка не нужна->reti
вариант 2: перепланировка нужна->OS_ContextSwitcher->ret

 

Если использовать прерывания, использующие сервисы ОС, только одного уровня,

то можно так:

 

OS_ContextSwitcher:

     save_SREG
     save_SP
     save_regs
     save_SFRS


     mov  r30,r16; Curr_SP_addr
     mov  r31,r17;
     std  Z+0,r28; save process's Stack Pointer
     std  Z+1,r29;
     

     

     mov  r28,r18; load next process Stack Pointer
     mov  r29,r19;
     
     lds  R16, 0x00A0; PMIC.STATUS 
     andi R16, 7
     BRNE Int_RestoreContext     
       
L_RestoreContext:

       
     restore_SFRS
     restore_regs
     restore_SP
     restore_SREG

     ret
     
Int_RestoreContext:
     restore_SFRS
     restore_regs
     restore_SP
     restore_SREG

     reti

 

Но решение какое-то ограниченное...

Попробовал изменить TISRW_SS

class TISRW_SS
   {
   public:

       INLINE  TISRW_SS(byte int_level)  {
#if scmRTOS_CONTEXT_SWITCH_SCHEME==0
		CurrentInterruptLevelMask=~int_level;
		CurrentInterruptLevelMask&=scmRTOS_INTERRUPT_LEVEL_MASK;
#endif
		ISR_Enter();
	}

       INLINE  ~TISRW_SS() { ISR_Exit();  }

   private:
#if scmRTOS_CONTEXT_SWITCH_SCHEME==0
	byte CurrentInterruptLevelMask;
#endif
       //-----------------------------------------------------
       INLINE void ISR_Enter() // volatile
       {
		TCritSect cs;
           if(Kernel.ISR_NestCount++ == 0)
           {
                SavedSP.DataSP   = GetDataSP();
                SavedSP.ReturnSP = GetReturnSP();
                SetISRStackPointers();
           }

#if scmRTOS_CONTEXT_SWITCH_SCHEME == 1
		DisableContextSwitch();
#endif
       }
       //-----------------------------------------------------
       INLINE void ISR_Exit()
       {
		TCritSect cs;
		if (--Kernel.ISR_NestCount==0) {
			SetReturnSP(SavedSP.ReturnSP);
			SetDataSP  (SavedSP.DataSP);
		}
#if scmRTOS_CONTEXT_SWITCH_SCHEME==0
		if (PMIC.STATUS&CurrentInterruptLevelMask) return ;
#endif
           Kernel.SchedISR();
       }
       //-----------------------------------------------------
   };

 

Но тоже какая-та ерунда: теперь получается что все прерывания

одного уровня должны либо использовать, либо не использовать TISRW_SS.

В общем тоже костыль получился, хотя и выглядит работающим (см. приложение).

 

В связи с этой проблемой вопрос: можно ли заставить IAR сделать функию

прерывания ещё и __monitor (возможно ли это в хмегах вообще - запретить прерывание более

высокого уровня след. командой после перехода с вектора прерывания и будет ли этот

запрет отрабатываться)? Этот вариант завтра попробую.

 

Спасибо.

xm.rar

Share this post


Link to post
Share on other sites

Ой-ой-ой... Мне самому xmega до сих пор как-то не нужна, вот я и тяну.

В очередной раз достал наверх макетку с atxmega128a1, помигал светодиодом, буду искать время на scmRTOS на ней.

Share this post


Link to post
Share on other sites

Ой-ой-ой...

Это вы о чём?

По поводу моей писанины или вообще?

 

Мне самому xmega до сих пор как-то не нужна, вот я и тяну.

Это понятно.

STM8 лучше xmeg-и?

 

В очередной раз достал наверх макетку с atxmega128a1, помигал светодиодом, буду искать время на scmRTOS на ней.

Ждём.

Share this post


Link to post
Share on other sites

Стмка на порядок дешевле. И там есть свои вкусности. Например можно подгружать с внешней памяти функции в оперативку и выполнять их.

Но у них есть большой минус связанный с ихним трехуровневым конвейером. Из за него нельзя делать софтварные задержки и будут проблемы с софтварным 1-wire.

Share this post


Link to post
Share on other sites

Стмка на порядок дешевле.

Реально на порядок? Посмотрю.

 

Например можно подгружать с внешней памяти функции в оперативку и выполнять их.

Жаль в АВР такого нет. Полезная возможность.

 

Но у них есть большой минус связанный с ихним трехуровневым конвейером. Из за него нельзя делать софтварные задержки и будут проблемы с софтварным 1-wire.

Зачем программно? Аппаратные ресурсы надо задействовать.

 

Share this post


Link to post
Share on other sites

stm8 настолько дешевые, что стоят почти как stm32. И тут стоит вопрос нахрена их брать?

В ST конечно умные дядьки сидят и они выпустили ультра дешевые stm8 с менее прочной флешпамять(100 гарантированных циклов записи), но полностью совместимый с полноценными микроконтроллерами. Т.е. проект разрабатываешь на нормальном камне а в серию идут дешевые мк.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...