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

scmRtos для медных чайников

std::vector<int> my_vector;

my_vector тоже находится в пространстве имён std. Так?

Переменная my_vector - нет. Функция my_vector::size() - да.

 

Вот ещё ссылка в тему.

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


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

Т.е. подозреваете банальный (и подлый) memory overwrite при пересылке данных?
Так и оказалось.

При инициализации DMA указал количество элементов как sizeof(adc_buf), а adc_buf состоит из 12 элементов 2 байтовых.

В итоге sizeof(adc_buf) возвращало вдвое больше чем я хотел передать и данные писались поверх других переменных.

 

Уже не первый раз на этом попадаюсь

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


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

Опять туплю. На сей раз процессор STM32F103, компилятор GCC, версия scmRTOS 5, если это имеет значение.

Прерывание:

OS::channel<uint8_t, 32> UsartRxChannel;
....
extern "C" void USART1_IRQHandler(void)
{
  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  {
    uint8_t c;
    c = USART1->DR;
    if (UsartRxChannel.get_free_size()>0) UsartRxChannel.push(c);    
  }
}

Как только доходит первый раз до UsartRxChannel.push( c ) - все улетает неведомо куда и прерывания больше не случаются.

При использовании TEventFlag signal_isr() никаких странностей не наблюдается, но делать свой буфер, когда есть channel как-то не кошерно :) .

Не подскажете, что я делаю не так?

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


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

Не подскажете, что я делаю не так?

При использовании сервисов оси в прерываниях обязательно нужно объявлять в обработчике прерывания переменную типа OS::TISRW:

extern "C" void USART1_IRQHandler(void)
{
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        OS::TISRW ISR;
...

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

 

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


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

При использовании сервисов оси в прерываниях обязательно нужно объявлять в обработчике прерывания переменную типа OS::TISRW:

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

 

Спасибо огромное - похоже, у меня склероз крепчает - ведь в старых проектах у меня она везде есть!

 

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


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

Насколько я могу сейчас сообразить, это не должно приводить к зависанию. Просто перепланировка будет происходить по прерыванию системного таймера. Скорее всего тут ещё наложилось то, что вы не обрабатываете флаг переполнения UART. Если мне не изменяет память, он сбрасывается последовательным чтением регистра статуса и регистра данных. А в вашем обработчике при отсутствии флага RXNE чтение регистра данных не производится. Чтобы избежать таких ситуаций я делаю вот так:

{
    auto status = USART1->SR;
    auto data = USART1->DR;

    if (status & USART_FLAG_RXNE)
    {
        if (rxChannel_.get_free_size())
            rxChannel_.push(data);
    }
...

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


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

Насколько я могу сейчас сообразить, это не должно приводить к зависанию.

Что-то не выходит каменный цветок - вроде как заработало, через несколько десятков секунд опять виснет. Пока оставил следующее решение - работает без вопросов:

struct sFifo
{
 uint8_t buf[128];
 uint8_t tail;
 uint8_t head;
 uint8_t MsgSize;
};
sFifo usartRXfifo;
OS::TEventFlag GpsFlag;
extern "C" void USART1_IRQHandler(void)
{
 OS::TISRW ISR;
 auto status = USART1->SR;
 auto data = USART1->DR;
 if (status & USART_FLAG_RXNE)
 {
if((usartRXfifo.head-usartRXfifo.tail)!=128)
{
  usartRXfifo.buf[usartRXfifo.head & 0x7F]=data;
  usartRXfifo.head++;
}
   if (data=='\r')
   {
usartRXfifo.MsgSize = usartRXfifo.head-usartRXfifo.tail;
GpsFlag.signal_isr();
   }
 }
}

Может, с другими задачами чего поделить не может - в системе еще IMU крутится и данные в CAN выплевывает.

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


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

Вы тогда уж засуньте создание OS::TISRW в ту ветку, где взводится флажок GpsFlag. А то ваш нынешний код всё равно дёргает перепланировку на каждый принятый символ.

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


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

Что-то не выходит каменный цветок - вроде как заработало, через несколько десятков секунд опять виснет.

А уверены, что channel не переполняется? Если в нём нет места, то будет предпринята попытка встать на ожидание, что в прерывании приведёт к фатальным результатам.

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


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

А уверены, что channel не переполняется?

Он с большим запасом вроде как, и, кроме того, я проверяю перед записью, есть ли там место get_free_size. Короче, мистика какая-то.

 

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


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

Необходимо написать "мягкий" вариант критической секции, когда прерывания разрешены, но заблокирована работа планировщика, чтобы не было переключения процессов.

Вопрос. В какой п/программе Оси лучше сделать блокировку планировщика?

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

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


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

В какой п/программе Оси лучше сделать блокировку планировщика?
Начиная с версии 4 в ОС есть класс TKernelAgent. Он предназначен для написания расширений. Отнаследуйтесь от него и творите в наследнике что хотите. Когда напишете - расскажите, что у вас получилось. Помнится, такой вопрос уже обсуждался и никакого решения мы не нашли.

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


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

Опять туплю.

Пытаюсь заставить работать scmRTOS c STM32F103C8 (платка Blue Pill, операционная система должна работать поверх STM32duino)

В качестве системного таймера пытаюсь использовать TIMER3:

 

 

// If the macro value is 0 (the default), the port uses SysTick as a system
// timer. It initializes the timer and starts it. The user must make sure that
// the address of the timer interrupt handler (SysTick_Handler) is in the right
// place at the interrupt vector table.
// If the macro value is 1, then the user has to implement (see docs for details):
//     1. extern "C" void __init_system_timer();
//     2. void LOCK_SYSTEM_TIMER() / void UNLOCK_SYSTEM_TIMER();
//     3. In the interrupt handler of the custom timer, the user needs to call
//        OS::system_timer_isr()

#if SCMRTOS_USE_CUSTOM_TIMER == 1

static void TIM3_Event()
{
 OS::system_timer_isr();
}

extern "C" void __init_system_timer()
{
 RCC_BASE->APB1ENR |= RCC_APB1ENR_TIM3EN;      // TIM3
 // TIM3 master counter period 1 msec 48MHz main
 TIMER3->regs.gen->CR1 &= ~TIMER_CR1_CEN;   // disabled
 TIMER3->regs.gen->PSC = 480 - 1; //new clock = 100kHz
 TIMER3->regs.gen->ARR = 100 - 1;   //period = 16usec
 TIMER3->regs.gen->CR1   |= TIMER_CR1_DIR; //used as downcounter
 timer_attach_interrupt(TIMER3, TIMER_UPDATE_INTERRUPT, TIM3_Event);
 TIMER3->regs.gen->CR1 |= TIMER_CR1_CEN; // enable timer
 TIMER3->regs.gen->DIER  |= TIMER_DIER_UIE; //enable interrupt
}

INLINE void LOCK_SYSTEM_TIMER()
{
 TIMER3->regs.gen->CR1 &= ~TIMER_CR1_CEN; // disable timer
}

INLINE void UNLOCK_SYSTEM_TIMER()
{
 TIMER3->regs.gen->CR1 |= TIMER_CR1_CEN; // enable timer
}


#endif

 

после первого же вызова OS::sleep() прерывание больше не наблюдается.

Что я опять делаю не так?

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


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

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

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

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

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

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

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

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

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

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