Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: scmRtos для медных чайников
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > scmRTOS
Страницы: 1, 2, 3
IgorKossak
Цитата(AHTOXA @ Jan 22 2013, 16:04) *
А, теперь всё понятно. Но давайте всё же для однозначности будем называть эту сборку "GCC ARM Embedded", как они сами её называют?
Согласен.
Цитата(AHTOXA @ Jan 22 2013, 16:04) *
Надо затестить её, и, если всё нормально, то использовать её как референсную. А то sourcery g++ lite теперь просто так не скачать, да и вообще будущее её неясно.
А тут всё же ARM участвует, солидноsm.gif

В этом случае я сплю спокойно. Потестил на нескольких проектах. Полёт нормальный. Использую как основной.
В сравнении Sourcery Lite порадовало, что у GCC ARM Embedded нет ограничений на аппаратную плавучку в библиотеках. Радуют также регулярные обновления и хорошая реакция разработчиков в их поддержке.
ReAl
Цитата(dezna @ Jan 22 2013, 06:58) *
я просил товарища собрать мне рабочий пример. он у себя проверил - работает. на моей железке тоже.
Ха, так я этот пример, оказывается, и собирал не KGP, а этим:
Цитата(AHTOXA @ Jan 22 2013, 10:20) *
есть Sourcery CodeBench Lite, бывшая sourcery g++ lite. (качать ARM EABI Release).

В makefile-то
Код
    TOOL    = arm-none-eabi-
#    TOOL    = arm-kgp-eabi-

Если точнее, то собиралось версией /opt/CodeSourcery/arm-2011.09/bin/
Ещё 2012.03 стоит дома, но дома я в /64 KGP использую.



Цитата(IgorKossak @ Jan 22 2013, 10:32) *
Для сборки под Cortex-Mx пользуюсь тулчейном от Linaro. Нареканий нет.
Хм. У меня даже в закладках лежит. Когда-то почему-то не пошло, видать.
«Бум пробовать»™
IgorKossak
Цитата(ReAl @ Jan 22 2013, 17:04) *
Хм. У меня даже в закладках лежит. Когда-то почему-то не пошло, видать.
«Бум пробовать»™

Были у них проблемы в линейке 4.6. с непомерным impure_data array. В линейке 4.7 этого не наблюдается.
ReAl
Цитата(IgorKossak @ Jan 22 2013, 17:44) *
Были у них проблемы в линейке 4.6. с непомерным impure_data array. В линейке 4.7 этого не наблюдается.
Возможно, не помню уже.

А LTO что - нет? Только что скачанное:
Цитата
arm-none-eabi-g++ (GNU Tools for ARM Embedded Processors) 4.7.3 20121207 (release) [ARM/embedded-4_7-branch revision 194305]
...
cc1plus: error: LTO support has not been enabled in this configuration
Или я что-то не так делаю?
AHTOXA
Цитата(ReAl @ Jan 22 2013, 21:04) *
Ха, так я этот пример, оказывается, и собирал не KGP, а этим:

В makefile-то
Код
    TOOL    = arm-none-eabi-
#    TOOL    = arm-kgp-eabi-

Ну да, всё же kgp не так широко известен, поэтому я в примерах делаю по умолчанию arm-none-eabi- (это может быть sourcery g++, yagarto, а теперь, возможно, и GCC ARM Embedded.)
IgorKossak
Цитата(ReAl @ Jan 22 2013, 17:49) *
А LTO что - нет? Только что скачанное:
Или я что-то не так делаю?

Нету, забыл сказать, потому что не использую.
У них в переписке кто-то поднимал этот вопрос. Поначалу отмахивались ссылаясь не отсутствие интереса пользователей к этому, но в конце обнадёжили. Подождём следующего апдейта (они раз в квартал случаются).
dezna
Цитата(AHTOXA @ Jan 22 2013, 12:20) *
ЗЫ. Если уж совсем не пойдёт, и вы боитесь самодельных сборок, то есть Sourcery CodeBench Lite, бывшая sourcery g++ lite. (качать ARM EABI Release).

вчера собрал arm-none-eabi 4.7.2. проект 1-EVENT собирается без шаманств с линкер скриптом и раьотает.
собрал свой рабочий проект - вылетел в HardFault.
поставил на закачку CodeBench Lite. посмотрим как он себя поведёт.
uriy
Вопрос больше касается С++. Делаю первый проект на scmRTOS и на С++ еще никогда не писал.
Накидал 3 процесса в одном мейн файле. Все работают как надо.
Начал раскидывать процесессы по отдельным файлам.
Я привык раскидывать процессы по своим c и h файлам.
Тут произошло что-то странное. Начал обрабатываться только один процесс и девайс как будто перезагружается раз в секунду.
Хотя у меня watchdog даже не задействован.

файл thread_lcd.cpp
Код
#include "thread_lcd.h"

template<> void TProc3::exec();
TProc3 Proc3;
//---------------------------------------------------------------------------
namespace OS {

template<> void TProc3::exec()
{
    uint8_t i;
    sleep(1000);
    lcd_clear();
    lcd_goto(1,0);
    for(;;)
    {
        lcd_goto(1,0);
        xprintf("hello %d", i++);
        sleep(1000);
    }
} // TProc3::exec()

} // namespace OS


файл thread_lcd.h
Код
#ifndef _THREAD_LCD_H_
#define _THREAD_LCD_H_
#include <scmRTOS.h>
#include "hardware/hardware.h"
typedef OS::process<OS::pr2, 120> TProc3;
#endif


Снова перетащил теже исходники в один файл и работает как надо.
dxp
QUOTE (uriy @ Dec 7 2015, 20:43) *
Вопрос больше касается С++. Делаю первый проект на scmRTOS и на С++ еще никогда не писал.

Тоже раскидываю процессы по своим файлам, это ничему не мешает. Единственное, что объявления типов процессов держу все вместе, чтобы контролировать их количество и параметры в одном месте (обычно это основной заголовочный файл проекта). А сами объекты процессов и их исполняемые функции - уже по месту.

Ещё. Код исполняемой функции процесса я не помещаю в пространство имён OS - ведь это уже код приложения, ему нечего делать в OS. Вообще, при написании прикладного кода ничего не нужно помещать в OS, это не "территория" проекта.
AHTOXA
Цитата(dxp @ Dec 10 2015, 10:30) *
Ещё. Код исполняемой функции процесса я не помещаю в пространство имён OS - ведь это уже код приложения, ему нечего делать в OS. Вообще, при написании прикладного кода ничего не нужно помещать в OS, это не "территория" проекта.

GCC на такое ругается:
Код
error: specialization of 'template  in different namespace [-fpermissive]
dxp
QUOTE (AHTOXA @ Dec 10 2015, 12:18) *
GCC на такое ругается:
CODE
error: specialization of 'template  in different namespace [-fpermissive]

А, это не тот ли самый косяк застарелый?

CODE
namespace OS
{
#ifndef __GNUC__  // avoid GCC bug ( http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15867 )
    template<> void TIdleProc::exec();
#endif

    TIdleProc IdleProc;
}
AHTOXA
Цитата(dxp @ Dec 10 2015, 14:59) *
А, это не тот ли самый косяк застарелый?

Не, то было другое. Там GCC давал предупреждение "redundant redeclaration".
А тут, как мне кажется, всё верно. Если прототип функции объявлен в пространстве имён OS, то и реализация должна быть там же. Иначе это будет реализация какой-то другой функции.

ЗЫ. Кстати, баг тот уже давно исправлен, можно вычистить этот кусочек.
Сергей Борщ
Цитата(AHTOXA @ Dec 10 2015, 14:32) *
Если прототип функции объявлен в пространстве имён OS, то и реализация должна быть там же.
Хм. В пространстве имен OS был объявлен OS::process, а TProc3 объявлен уже в глобальном пространстве имен. И специализацию exec мы пишем не для OS::process<тра-та-та>, а для TProc3, разве не так?
AHTOXA
Цитата(Сергей Борщ @ Dec 10 2015, 16:53) *
И специализацию exec мы пишем не для OS::process<тра-та-та>, а для TProc3, разве не так?

Так TProc3 - это просто typedef для OS::process<тра-та-та>. Алиас, так сказать.
По сути мы имеем
Код
namespace OS
{
    template <>
    void OS::process<OS::pr0, 3600>::exec()
    {
...
dxp
QUOTE (AHTOXA @ Dec 10 2015, 18:16) *
Так TProc3 - это просто typedef для OS::process<тра-та-та>. Алиас, так сказать.
По сути мы имеем
CODE
namespace OS
{
    template <>
    void OS::process<OS::pr0, 3600>::exec()
    {
...

OS::process<тра-та-та> в том случае - это уже инстанцирование шаблона, т.е. рожается конкретный тип из параметрического, и этот конкретный тип уже объявлен не в OS, а в глобальном. И это правильно. Иначе получалось бы, что все производные типы гвоздями были бы прибиты к пространству имён базового типа.
AHTOXA
Цитата(dxp @ Dec 10 2015, 20:23) *
OS::process<тра-та-та> в том случае - это уже инстанцирование шаблона, т.е. рожается конкретный тип из параметрического, и этот конкретный тип уже объявлен не в OS, а в глобальном.

GCC с тобой не согласенsm.gif
Цитата(dxp @ Dec 10 2015, 20:23) *
И это правильно. Иначе получалось бы, что все производные типы гвоздями были бы прибиты к пространству имён базового типа.

Ты не путай наследование и инстанцирование. Если бы мы написали
class SuperProcess : public OS::process<тра-та-та> - тогда да, это производный тип, и он уже не в пространстве имён OS. А в обсуждаемом случае мы всего лишь реализуем объявленную ранее функцию шаблона. И объявлена она в пространстве имён OS.
dxp
QUOTE (AHTOXA @ Dec 11 2015, 07:07) *
Ты не путай наследование и инстанцирование. Если бы мы написали
class SuperProcess : public OS::process<тра-та-та> - тогда да, это производный тип, и он уже не в пространстве имён OS. А в обсуждаемом случае мы всего лишь реализуем объявленную ранее функцию шаблона. И объявлена она в пространстве имён OS.

Я и не путаю. Это ты путаешь инстанцирование и псевдонимы (typedef). OS::process<тра-та-та> - это уже другой тип, чем OS::process. И его функция exec - это полная специализация этого нового типа. Обе эти новые сущности могут жить в любом пространстве имён, в т.ч. и в глобальном.
uriy
Между тем у меня появились некоторые подробности по поводу моей неудачной попытки разбить процессы по файлам.
Проблема вовсе не в С++. Что-то новое пугает и сразу валишь на это.

Я не уточнял что это контроллер STM8L152. C scmRTOS не пошло, решил запустить операционку OSA.
В обоих операционках три задачи: дисплей, rf модуль и пока просто мигание светодиодом.
И увидел ту же самую периодическую перезагрузку. Я был очень удивлен.
При включении добавил вывод на дисплей регистра источника сброса.
Причиной сброса оказался WWDG (window watchdog). Удивился еще больше. WWDG никогда не использую, даже не понимаю как его применить.
Ограничиваюсь обычным watchdog, но в этом проекте даже он еще не был задействован.
Причина проблем оказалась в связке ADC+DMA+TIM. DMA складывает три канала АЦП в буфер. В прерывании по завершении заполнения буфера проводит рассчет. Прерывание происходит пару раз в секунду. Запрет прерываний не устраняет проблему. Как-будто DMA пишет туда куда не надо.

Дальше сделал вывод на дисплей переменной равной нулю при старте с инкрементом раз в секунду. При отключенном ADC+DMA+TIM переменная обновляется на дисплее, rf модуль принимает валидные данные, светодиод мигает.
Включаю ADC+DMA+TIM. Переменная на дисплее по прежнему обновляется раз в секунду. Но она уже принимает случайные значения, обмен с rf модулем нарушен, а контроллер больше не перезагружается.
Во всех экспериментах в буфере АЦП всегда складывались ожидаемые значения.

В случае с scmRTOS похоже просто повезло что проблема не вылезла сразу когда все задачи были в одном файле.
Разбираться с этим пока не стал, пишу остальную часть кода.
AHTOXA
Цитата(dxp @ Dec 11 2015, 07:47) *
OS::process<тра-та-та> - это уже другой тип, чем OS::process. И его функция exec - это полная специализация этого нового типа. Обе эти новые сущности могут жить в любом пространстве имён, в т.ч. и в глобальном.

Начнём с того, что типа OS::process не существует. Существует шаблонный класс (class template) OS::process. При его инстанцировании с конкретными параметрами появляется тип OS::process<конкретные параметры>. Он точно также находится в пространстве имён OS. (Смотри на его имя). Для удобства мы дали этому типу псевдоним TProc3.
Думаю, что GCC делает правильно. Думаю также, что твой компилятор просто удовлетворяется префиксом OS:: в имени класса, и считает, что этого достаточно для того, чтобы реализация функции была в пространстве имён OS. Но наверняка по стандарту это не так (gcc довольно ревностно относится к соблюдению стандартов).
dxp
QUOTE (AHTOXA @ Dec 11 2015, 11:48) *
Начнём с того, что типа OS::process не существует. Существует шаблонный класс (class template) OS::process. При его инстанцировании с конкретными параметрами появляется тип OS::process<конкретные параметры>. Он точно также находится в пространстве имён OS. (Смотри на его имя). Для удобства мы дали этому типу псевдоним TProc3.

Как это не существует? Это параметризованный тип. И OS:: в OS::process - это просто квалификация пути к этому типу. А конкретный тип, который от него рожается путём подстановки параметра шаблона, уже возникает в том пространстве имён, в котором он объявлен.

По твоей логике получается, что в

std::vector<int> my_vector;

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

QUOTE (uriy @ Dec 11 2015, 11:26) *
Прерывание происходит пару раз в секунду. Запрет прерываний не устраняет проблему. Как-будто DMA пишет туда куда не надо.

Т.е. подозреваете банальный (и подлый) memory overwrite при пересылке данных?
AHTOXA
Цитата(dxp @ Dec 11 2015, 13:10) *
std::vector<int> my_vector;
my_vector тоже находится в пространстве имён std. Так?

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

Вот ещё ссылка в тему.
uriy
Цитата
Т.е. подозреваете банальный (и подлый) memory overwrite при пересылке данных?
Так и оказалось.
При инициализации DMA указал количество элементов как sizeof(adc_buf), а adc_buf состоит из 12 элементов 2 байтовых.
В итоге sizeof(adc_buf) возвращало вдвое больше чем я хотел передать и данные писались поверх других переменных.

Уже не первый раз на этом попадаюсь
varvar
Опять туплю. На сей раз процессор 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 как-то не кошерно sm.gif .
Не подскажете, что я делаю не так?
AHTOXA
Цитата(varvar @ Apr 16 2016, 22:36) *
Не подскажете, что я делаю не так?

При использовании сервисов оси в прерываниях обязательно нужно объявлять в обработчике прерывания переменную типа OS::TISRW:
Код
extern "C" void USART1_IRQHandler(void)
{
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        OS::TISRW ISR;
...

Она обеспечивает перепланировку при выходе из зоны видимости.
varvar
Цитата(AHTOXA @ Apr 16 2016, 21:48) *
При использовании сервисов оси в прерываниях обязательно нужно объявлять в обработчике прерывания переменную типа OS::TISRW:
Она обеспечивает перепланировку при выходе из зоны видимости.


Спасибо огромное - похоже, у меня склероз крепчает - ведь в старых проектах у меня она везде есть!
AHTOXA
Насколько я могу сейчас сообразить, это не должно приводить к зависанию. Просто перепланировка будет происходить по прерыванию системного таймера. Скорее всего тут ещё наложилось то, что вы не обрабатываете флаг переполнения UART. Если мне не изменяет память, он сбрасывается последовательным чтением регистра статуса и регистра данных. А в вашем обработчике при отсутствии флага RXNE чтение регистра данных не производится. Чтобы избежать таких ситуаций я делаю вот так:
Код
{
    auto status = USART1->SR;
    auto data = USART1->DR;

    if (status & USART_FLAG_RXNE)
    {
        if (rxChannel_.get_free_size())
            rxChannel_.push(data);
    }
...
varvar
Цитата(AHTOXA @ Apr 16 2016, 22:57) *
Насколько я могу сейчас сообразить, это не должно приводить к зависанию.

Что-то не выходит каменный цветок - вроде как заработало, через несколько десятков секунд опять виснет. Пока оставил следующее решение - работает без вопросов:
CODE
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 выплевывает.
AHTOXA
Вы тогда уж засуньте создание OS::TISRW в ту ветку, где взводится флажок GpsFlag. А то ваш нынешний код всё равно дёргает перепланировку на каждый принятый символ.
dxp
QUOTE (varvar @ Apr 17 2016, 15:12) *
Что-то не выходит каменный цветок - вроде как заработало, через несколько десятков секунд опять виснет.

А уверены, что channel не переполняется? Если в нём нет места, то будет предпринята попытка встать на ожидание, что в прерывании приведёт к фатальным результатам.
varvar
Цитата(dxp @ Apr 17 2016, 16:51) *
А уверены, что channel не переполняется?

Он с большим запасом вроде как, и, кроме того, я проверяю перед записью, есть ли там место get_free_size. Короче, мистика какая-то.
Anatoly74
Необходимо написать "мягкий" вариант критической секции, когда прерывания разрешены, но заблокирована работа планировщика, чтобы не было переключения процессов.
Вопрос. В какой п/программе Оси лучше сделать блокировку планировщика?
Сергей Борщ
QUOTE (Anatoly74 @ May 12 2016, 15:26) *
В какой п/программе Оси лучше сделать блокировку планировщика?
Начиная с версии 4 в ОС есть класс TKernelAgent. Он предназначен для написания расширений. Отнаследуйтесь от него и творите в наследнике что хотите. Когда напишете - расскажите, что у вас получилось. Помнится, такой вопрос уже обсуждался и никакого решения мы не нашли.
Anatoly74
Спасибо за наводку
varvar
Опять туплю.
Пытаюсь заставить работать scmRTOS c STM32F103C8 (платка Blue Pill, операционная система должна работать поверх STM32duino)
В качестве системного таймера пытаюсь использовать TIMER3:


CODE

// 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() прерывание больше не наблюдается.
Что я опять делаю не так?
AHTOXA
Прерывание вызывается?
А приоритет какой у него?
varvar
Цитата(AHTOXA @ Jun 10 2018, 13:18) *
Прерывание вызывается?
А приоритет какой у него?

Для проверки в прерывание могралку ставлю:
CODE
static void TIM3_Event()
{
static uint16_t counter=0;
counter++;
if(counter>100)
{
digitalWrite(PC13,!digitalRead(PC13));
counter=0;
}
OS::system_timer_isr();
}


Если процесс выглядит так:
CODE
namespace OS
{
template<> void TProc0::exec()
{
for (;;)
{
delay(100);
}
}
}

все моргает, стоит заменить на
CODE
namespace OS
{
template<> void TProc0::exec()
{
for (;;)
{
OS::sleep(100);
}
}
}

моргание прекращается.

Какой приоритет - это надо в ардуиновские исходники лезть смотреть, так что пока не знаю.
AHTOXA
Так у вас, получается, само прерывание затыкается?

Может, надо сбрасывать флаг прерывания в обработчике?

Ну и приоритет должен быть ниже всех остальных прерываний в системе (кроме PendSV).

varvar
Цитата(AHTOXA @ Jun 10 2018, 16:58) *
Так у вас, получается, само прерывание затыкается?

Может, надо сбрасывать флаг прерывания в обработчике?

Ну и приоритет должен быть ниже всех остальных прерываний в системе (кроме PendSV).

Да, затыкается прерывание. Но что его может затыкать?
Флаг поначалу сбрасывался, потом убрал - никак не влияет.
Если бы и влиял - влиял бы в обоих случаях.
А приоритет попробую порыть как в STM32duino изменить.
varvar
добавил в инициализацию

nvic_irq_set_priority(NVIC_TIMER3, (0xFEUL << (8-(CORE_PRIORITY_BITS))) & 0xFF);

хорошая новость - прерывания перестали затыкаться.
Плохая - система по-прежнему не работает, тут:
CODE
template<> void TProc0::exec()
{
for (;;)
{
digitalWrite(PC13,!digitalRead(PC13));
OS::sleep(100);
}
}

ничего не моргает.
Если sleep заменить ардуиновским delay, то светодиод моргает
AHTOXA
Во-первых, для надёжности лучше пишите в приоритет 0xFF, и без всяких сдвигов.

Во-вторых, убедитесь, что вызывается осёвый обработчик PendSV_Handler. А то кто его знает, что там в недрах mbed-а делается.

Кстати, вы OS:run() не забыли вызвать?
varvar
Цитата(AHTOXA @ Jun 11 2018, 00:34) *
Во-первых, для надёжности лучше пишите в приоритет 0xFF, и без всяких сдвигов.

Во-вторых, убедитесь, что вызывается осёвый обработчик PendSV_Handler. А то кто его знает, что там в недрах mbed-а делается.

Кстати, вы OS:run() не забыли вызвать?

OS:run() не забыл.
Приоритет, наверно, 0xFE? С 0xFF не работает - прерывние теряется.
PendSV_Handler не вызывается sad.gif
varvar
почему-то
CODE

nvic_set_vector_table((uint32_t)&PendSV_Handler, (uint32)VECT_TAB_ADDR+0x38);

не помогает - что я не так делаю?
varvar
Заработало!!! (с) Кот Матроскин

По крайней мере на первый взгляд, одна задача мигает светодиодом, вторая в USB что-то гонит.
Помогла замена

#pragma weak PendSVC_ISR = PendSV_Handler

в os_target.cpp на

#pragma weak __exc_pendsv = PendSV_Handler

Может я и не прав, и надо было по другому сделать - но таки моргает sm.gif

AHTOXA, спасибо огромное!
AHTOXA
Ну и отлично sm.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.