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

Несколько вопросов начинающего

в коде подвоха не видно.

привидите пример создания этого семафора, ну и обратите на это внимание собственно :)

 

xSemaphoreHandle x_RTC_Second_Change;    //глобальная переменная
/*
.......
*/
vSemaphoreCreateBinary( x_RTC_Second_Change );  //в самом начале программы, до инициализации прерываний и создания задач

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


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

..vSemaphoreCreateBinary( x_RTC_Second_Change );...

 

вот тут есть инфа о различиях и правильном применении семафоров.

семафоры

обратите внимание на другие способы создания семафоров(и способы работы с ними - рисунки 30 и 31), например xSemaphoreCreateCounting

 

если интенсив у Вас большой - то возможно это Ваш случай.

 

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


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

вот тут есть инфа о различиях и правильном применении семафоров.

семафоры

обратите внимание на другие способы создания семафоров(и способы работы с ними - рисунки 30 и 31), например xSemaphoreCreateCounting

 

если интенсив у Вас большой - то возможно это Ваш случай.

Знаю про другие способы создания симафора. Но это не даёт ответа на вопрос, из-за чего именно происходит глюк. И увеличение частоты выдающего симафор прерывания в 1000 раз не учащает появление глюка.

 

Изучил глюк получше :

Во время глюка иногда попадаю в HardFault_Handler, иногда просто операционка начинает работать не так.

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

Глюк происходит, только если в задаче есть строчка xSemaphoreTake( x_RTC_Second_Change, portMAX_DELAY );

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

При этом переключаю я контекст taskYIELD() в конце прерывания или не переключаю ни на что не влияет.

post-24702-1389055133_thumb.jpg

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


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

///////прерывание RTC  ALARM  1 раз в секунду////////////////////////////////////////////////
void RTC_Alarm_IRQHandler(void)
{
     portBASE_TYPE pxHigherPriorityTaskWoken;
    
      EXTI->PR|=(1<<17);
      RTC->ISR&=~RTC_ISR_ALRAF;    //сбрасываем флаги прерывания
    
      xSemaphoreGiveFromISR(x_RTC_Second_Change,&pxHigherPriorityTaskWoken); 
      if(pxHigherPriorityTaskWoken==pdTRUE)
            taskYIELD(); //переключаем контекст
}

 

Какой камень? А вроде не правильное переключение контекста, у меня чото не задружило переключение taskYIELD() для NIOS и для STM32. Так

void USART1_IRQHandler(void)
{
    static uint8_t byte;
    [b]static [/b]portBASE_TYPE xHigherPriorityTaskWoken;
    xHigherPriorityTaskWoken = pdFALSE;
    if(USART1_SR_bit.RXNE == 1)
    { //
        byte = USART1_DR; 
        xQueueSendToBackFromISR(uart485Queue, &byte, &xHigherPriorityTaskWoken);
    }
    [b]portEND_SWITCHING_ISR(xHigherPriorityTaskWoken == pdTRUE);[/b]
}

лучше xHigherPriorityTaskWoken сделать статиком

ну и определи configASSERT, может косяк выскочит из-за конфига ртос

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


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

Какой камень? А вроде не правильное переключение контекста, у меня чото не задружило переключение taskYIELD() для NIOS и для STM32. Так

лучше xHigherPriorityTaskWoken сделать статиком

ну и определи configASSERT, может косяк выскочит из-за конфига ртос

 

STM32L151

Сделал xHigherPriorityTaskWoken статиком

Заменил taskYIELD(); на portYIELD_FROM_ISR(xHigherPriorityTaskWoken == pdTRUE); (это то же самое что у Вас portEND_SWITCHING_ISR )

Сделал через очередь xQueueSendFromISR

Ничего не изменилось.

 

Что такое configASSERT не понимаю. Объясните пожалуйста в двух словах. Прочитал про него на сайте Freertos, вижу как определён.

А что он делает-то и как его "определить" ?

#define configASSERT( ( x ) ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )

 

И ещё : где взять 100% правильный файл FreeRtosConfig.h для STM32L151 Keil FreeRTOS V7.6.0 ?

В разных примерах есть "вроде бы подходящие" файлы, и с ними до сих пор работало.

Ну а какой точно нужен ? Может в этом дело ?

 

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


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

Что такое configASSERT не понимаю. Объясните пожалуйста в двух словах. Прочитал про него на сайте Freertos, вижу как определён.

А что он делает-то и как его "определить" ?

#define configASSERT( ( x ) ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )

configASSERT - это проверка правильности настройки фрииртос. этот дефайн отнимает немного процесорного времени и нужен только для начального дебага(проверки) ртос. Когда гдето ртос начинает глючить, есть вероятность что не правильно что-то заданно.

например у меня было

#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )

создал задачу с приоритетом 5. вроде работало, но иногда сбоило. определил configASSERT в FreeRtosConfig.h

#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for(;; ); }

сразу при создании задачи застрял в одном месте ртос с коментами типа "попытка создать задачу с приоритетом >= 5". оказалось что configMAX_PRIORITIES должен быть на 1 выше самого высокого приоритета задачи.

 

Потом во фрииртос сложная замута с приоритетами задач и прерываний. В стм32 ещё приоритеты прерываний в обратном порядке. Чтобы ртос коректно крутилась нужно правильно назначить configKERNEL_INTERRUPT_PRIORITY и configMAX_SYSCALL_INTERRUPT_PRIORITY..... для stm32 это вообще квест.... попробую объяснить. В демках так

/* This is the raw value as per the Cortex-M3 NVIC.  Values can be 255
(lowest) to 0 (1?) (highest). */
#define configKERNEL_INTERRUPT_PRIORITY         255
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY     191 /* equivalent to 0xb0, or priority 11. */


/* This is the value being used as per the ST library which permits 16
priority values, 0 to 15.  This must correspond to the
configKERNEL_INTERRUPT_PRIORITY setting.  Here 15 corresponds to the lowest
NVIC value of 255. */
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY    15

configKERNEL_INTERRUPT_PRIORITY - с этим всё понятно. ядру низший приоритет.

#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xb0, or priority 11. */ - вот это загадка. 191 в хексе = 0xbf. для моего stm32 в назначении приоритета учавствует только старшая тетрада. поэтому bf equivalent to 0xb0. 0 отбрасываем.... приоритет 0хb, или 11.

Так вот.... если вы используете прерывания, пишете обработчики прерывания, и если в обработчике прерывания нет API, то прерывание может быть с любым приоритетом. А если из обработчика прерывания есть вызов API, то источник прерывания должен быть с приоритетом не выше configMAX_SYSCALL_INTERRUPT_PRIORITY, в моем случае не выше 11. Т.е. у вас приоритет для RTC_Alarm_IRQHandler должен быть равен или ниже configMAX_SYSCALL_INTERRUPT_PRIORITY.

0 - вроде как высший приоритет в стм32. т.е. если configMAX_SYSCALL_INTERRUPT_PRIORITY=191, то приоритет RTC_Alarm_IRQHandler должен быть от 15 до 11 включительно.

 

configASSERT также проверит приоритеты прерываний.

 

В моем компиляторе нет макросов __FILE__, __LINE__, да и выводить не куда. поэтому у меня вечный вайл for( ;; );

 

И ещё : где взять 100% правильный файл FreeRtosConfig.h для STM32L151 Keil FreeRTOS V7.6.0 ?
Ну так а чего там может быть правильно и неправильно. разберись с каждой строчкой и сделай свой. Не сложно вроде.

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


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

juvf, огромное спасибо, сделал приоритет прерывания от RTC 12 и проблема исчезла !!!

 

Что делает это configMAX_SYSCALL_INTERRUPT_PRIORITY так и не могу понять.

Как понимаю из документации, прерывания выше этого приоритета используются самой операционкой, поэтому они и должны быть выше всех остальных.

Но почему их так много, 11 ?

Ведь операционка использует всего 3 прерывания, вот эти

#define xPortSysTickHandler SysTick_Handler

#define xPortPendSVHandler PendSV_Handler

#define vPortSVCHandler SVC_Handler

 

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


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

juvf, огромное спасибо, сделал приоритет прерывания от RTC 12 и проблема исчезла !!!

 

Что делает это configMAX_SYSCALL_INTERRUPT_PRIORITY так и не могу понять.

Как понимаю из документации, прерывания выше этого приоритета используются самой операционкой, поэтому они и должны быть выше всех остальных.

Но почему их так много, 11 ?

Ведь операционка использует всего 3 прерывания, вот эти

#define xPortSysTickHandler SysTick_Handler

#define xPortPendSVHandler PendSV_Handler

#define vPortSVCHandler SVC_Handler

В СТМ какие прерывания более приоритетны? И 11 это не значит их количество, это приоритет прерывания.

http://microsin.net/programming/ARM/freertos-part3.html ищите пункт 3.5 и ниже.

так же читайте про приоритеты прерываний для вашего процессора.

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


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

В СТМ какие прерывания более приоритетны? И 11 это не значит их количество, это приоритет прерывания.

http://microsin.net/programming/ARM/freertos-part3.html ищите пункт 3.5 и ниже.

так же читайте про приоритеты прерываний для вашего процессора.

 

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

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

 

 

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


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

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

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

никто ничего не резервирует, просто приоритеты от 11 до 15 могут использовать функционал freertos, а которые выше приоритетом от 0 до 10 уже не могут и не могут быть прерваны тиком freertos.

 

ну и наверно в cortex m3 может быть много прерываний с одинаковым приоритетом, ведь векторов прерываний не 15.

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


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

На сколько я понял.... ос использует приоритеты ниже 11, т.е. 15-11. Да же не ос, а в обработчика прерываний есть апи ос.

Например сработал твой rtc, в обработчике вызвал функционал ртос. Сработал какой нить уарт с прерыванием 11.

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

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


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

Ещё один вопрос :

Почему в задачу vApplicationStackOverflowHook вместо указателя на название задачи стек которой переполнился передаётся 0 ?

Раньше работало, и я мог увидеть название задачи. Вопрос : что могло изменится ?

Заранее спасибо !

post-24702-1389603125_thumb.jpg

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


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

Ещё один вопрос :

Почему в задачу vApplicationStackOverflowHook вместо указателя на название задачи стек которой переполнился передаётся 0 ?

Раньше работало, и я мог увидеть название задачи. Вопрос : что могло изменится ?

Заранее спасибо !

Не знаю. Смотри указатель xTaskHandle xTask в vApplicationStackOverflowHook на какую задачу указывает. Как создавал задачу? прописал ли имена задач, задал ли xTaskHandle?

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


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

Не знаю. Смотри указатель xTaskHandle xTask в vApplicationStackOverflowHook на какую задачу указывает. Как создавал задачу? прописал ли имена задач, задал ли xTaskHandle?

Разобрался. Это Keil не хочет показывать значение локальной переменной, если она определена но не используется. Раньше этой проблемы с pcTaskName почему-то не было.

Сделал глобальную переменную, которой присваиваю pcTaskName.

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


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

Вопрос по организации алгоритма :

 

Допустим начала работать задача А(была создана, была разблокирована), и пока она работает должны заблокироваться задачи Б, С, Д. Когда задача А завершила работу, Б С Д должны разблокироваться. Как это принято делать так, что бы было наименее путано ? Сделать очередь из одного элемента, из которой задачи Б С Д читают этот элемент без удаления, а задача А его либо удаляет либо возвращает ?

Нет ли способа проверять внутри задачи Д чему равен хэндлер задачи А, так что бы когда он не NULL задача Д блокировалась бы, а когда снова стал NULL разблокировалась бы?

 

 

Спасибо.

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


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

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

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

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

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

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

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

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

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

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