Jump to content

    

SMaster

Участник
  • Content Count

    21
  • Joined

  • Last visited

Community Reputation

0 Обычный

About SMaster

  • Rank
    Участник

Recent Profile Visitors

784 profile views
  1. FreeRTOS + ARM Cortex-M0 (BlueNRG1)

    В кейл инициализация происходит в функции __main (посмотрите ассемблеровский стартап-файлик), откуда в свою очередь вызывается функция main. Попробуйте запихать эту переменную в watch. А еще для более простой отладки я бы для начала выключил оптимизацию.
  2. Протестировал стрим буфер. Компилятор Keil, максимальная оптимизация по скорости, контроллер STM32F103C8T6. Измерил количество тиков на типовые операции и использование стека в байтах. Получились интересные результаты: Create / Send / Receive (тики между переходом управления планировщику и получением байта принимающей задачей) / Stack Стрим буфер = 200 / 572 / 548 / 136 Старая добрая очередь = 290 / 311 / 319 / 176 То есть выигрыш только в стеке? Я надеялся, что и скорость выше будет. Получается, что есть смысл использовать буферы только если прижимает по стеку, либо ради фишек буферов - Trigger Level для стрим буфера и возможность отправки данных разной длины для буфера сообщений. Код тестовой программы: Код#include "stm32f10x.h" #include "FreeRTOS.h" #include "stream_buffer.h" #include "task.h" #include "queue.h" StreamBufferHandle_t buf_tmp; QueueHandle_t        que_tmp; uint8_t i, j, k; void task_tmp1(void * param) {          while (1) {                  i++;         xStreamBufferSend(buf_tmp, &i, sizeof(uint8_t), portMAX_DELAY);         vTaskDelay(100);                  i++;         xQueueSend(que_tmp, &i, portMAX_DELAY);         vTaskDelay(100);              }      } void task_tmp2(void * param) {          while (1) {                  xStreamBufferReceive(buf_tmp, &j, sizeof(uint8_t), portMAX_DELAY);         __NOP();              }      } void task_tmp3(void * param) {          while (1) {                  xQueueReceive(que_tmp, &k, portMAX_DELAY);         __NOP();              }      } int main() {          xTaskCreate(task_tmp1, "tmp1", 128, NULL, 4, NULL);     xTaskCreate(task_tmp2, "tmp2", 128, NULL, 3, NULL);     xTaskCreate(task_tmp3, "tmp3", 128, NULL, 2, NULL);          buf_tmp = xStreamBufferCreate(100 * sizeof(uint8_t), sizeof(uint8_t));     que_tmp = xQueueCreate(100, sizeof(uint8_t));          vTaskStartScheduler();      }
  3. xTaskNotifyStateClear

    А как проверяете была остановлена задача или нет? Не по возвращаемому ли значению функции ulTaskNotifyTake()? Дело в том, что функция xTaskNotifyStateClear() очищает лишь флаг уведомления (значение ucNotifyState в TCB), но не отчищает 32-битное значение переменной уведомления (ulNotifiedValue). При этом xTaskNotifyGive(), которой вы скорее всего пользуетесь для передачи уведомления, выставляет флаг ucNotifyState и инкрементирует ulNotifiedValue, а функция ulTaskNotifyTake() ожидает флага в течение заданного времени, но возвращает не успешность ожидания флака, а значение переменной ulNotifiedValue. Если есть необходимость после сброса уведомления понять блокировалась ли задача (а она скорее всего блокировалась, раз мы непосредственно перед ожиданием уведомления сбросили флаг), то надо применить ulTaskNotifyTake(pdTRUE, 0), которая сбросит не только флаг, но и значение, либо при ожидании воспользоваться функцией xTaskNotifyWait(), например в виде xTaskNotifyWait(0, 0, NULL, portMAX_DELAY), которая вернет флаг pdTRUE = уведомление_произошло, pdFALSE = произошел_таймаут.
  4. Я вот жду релиза версии 9.0, в нем запилили возможность статически выделять память TCB/стек, QCB/очередь.
  5. Я думаю, что с этим у вас все правильно, но все же на всякий случай: все обработчики прерываний, вызывающие API-шные функции операционки, используют специализированные функции с окончанием FromISR()? Все такие функции имеют приоритет 11 и выше (численно)?
  6. М.б. поможет увеличение стека задачи?
  7. 1. Какой контроллер, на какой частоте работает, какой бодрейт у USARTа? Чтобы понимать сколько ресурсов требуется. 2. Какой длины очереди? Если бодрейт не более 115200, то очень странно, что контроллер не успевает отработать очередь. Для увеличения производительности можно попробовать применить т.н. уведомления, которые появились во FreeRTOS сравнительно недавно. http://www.freertos.org/RTOS_Task_Notifica...As_Mailbox.html Код будет приблизительно такой: CODEvoid USART2_IRQHandler(void) { char byte; volatile u32 status; portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; status = USART2->SR; /* Read one byte from the receive data register */ if (status & USART_FLAG_RXNE) { byte = USART_ReceiveData(USART2); xTaskNotifyFromISR(receive_task_handler, (uint32_t)byte, eSetValueWithOverwrite, &xHigherPriorityTaskWoken); // receive_task_handler - хэндлер задачи, принимающей данные } /* Write one byte to the transmit data register */ if (status & USART_FLAG_TXE) { /* Берем байт из очереди */ if (xQueueReceiveFromISR(qTxGsmQueue, &byte, &xHigherPriorityTaskWoken) == pdTRUE) { /* A character was retrieved from the queue so can be sent to the THR now. */ USART_SendData(USART2, byte); } else { USART_ITConfig(USART2, USART_IT_TXE, DISABLE); } } portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); } void receive_task(void * param) { uint32_t data; while (1) { xTaskNotifyWait(0, 0, &data, portMAX_DELAY); // Время ожидания бесконечность // Do something // ... } } И вообще, интересно взглянуть на вашу задачу, из которой вызывается gsm_get_str(). Как верно заметил den_po время ожидания элемента из очереди = 0. Какой-то не RTOSовский подход - функция будет вызываться вхолостую, вместо того, чтобы выполнение задачи блокировалось до появления данных на входе USART. В моем примере время ожидания бесконечно (при INCLUDE_vTaskSuspend равном 1). Отправку тоже можно упростить (в вычислительном плане), заюзав DMA. Судя по вызову USART_ITConfig, контроллер серии STM32 => DMA на борту имеется.
  8. mutex - есть ли очередь?

    Насколько я понимаю, xSemaphoreGive() в случае применения его к мутексу вызывает переключение контекста только в случае, если более высоприоритетная задача находится в ожидании этого мутекса. Функция xSemaphoreTake() также не вызывает переключения контекста, если мутекс не занят. Итого, при использовании его в подобной тестовой ситуации с одинаковым приоритетом задач без использования задержек и событий нужно как минимум воткнуть taskYIELD(). Думаю, что в реальной ситуации таких вопросов бы не возникло. Там скорее всего приоритет задач, использующих общий ресурс, разный. Либо есть задержки vTaskDelay(), либо работа с общим ресурсом происходит по событию. Если ответить на вопрос про очередь задач задач, обратившихся за мутексом, то очереди здесь нет, но мутекс "помнит", что его ожидает задача с более высоким приоритетом и в этом случае при отдаче переключает контекст, а там уже планировщик разруливает, что же делать дальше.
  9. STM32F103ZCT6, 21 канал АЦП + 4 канала PWM

    Цитата(_pv @ May 4 2015, 22:29) если речь про STM32F103ZCT6 в tqfp-144 корпусе, то там 3 АЦП и у мультиплексора 21 вход, как оно там потом по АЦП распределено не важно, оцифровать 21 канал можно. Только он стоит дороже STM32F303VC при том, что у f3 покруче ядро и периферия
  10. STM32F103ZCT6, 21 канал АЦП + 4 канала PWM

    Вам подойдет серия STM32F3. Рекомендую обратить внимание конкретно на STM32F303VC: 4 АЦП на 5 мегавыборок/с, 39 аналоговых каналов. И самое главное: копеешная отладочная плата STM32F3DISCOVERY.
  11. Вышла FreeRTOS V4.0.5 ... 8.2.3

    Кто-нибудь может объяснить нафига в 8.2.1 добавили thread local storage? Как они поясняют, так некоторые библиотечные фунции используют глобальную переменную err для оработки ошибок, но как это заюзать на практике - примеров нет... Хочется понять что за штука такая, может полезно будет. Direct task notifications, например, из релиза 8.2.0 я использую уже плотно, мне эта штука понравилась. Экономия памяти и времени.
  12. Есть ли какие подводные камни при переходе на эту версию компилятора с версии 5.11? Какие нужно отключать оптимизации для работы под jacOS?
  13. Цитата(demiurg_spb @ Nov 14 2008, 16:09) Откуда такие данные? (просто интересуюсь). Если система прекрасно работает с внутренними pullup'ами, то для чего городить огород? Согласен. Поэтому и хотел их подключить.
  14. Из даташита: ЦитатаNote that the internal pullups in the AVR pads can be enabled by setting the PORT bits corresponding to the SCL and SDA pins, as explained in the I/O Port section. The internal pull-ups can in some systems eliminate the need for external ones.
  15. Контроллер ATMega32, PUD = 0. КодPORTC = (1<<PC0) | (1<<PC1); DDRC  = (1<<DDC0) | (1<<DDC1); // Для проверки. Здесь резисторы включаются, на выводах 1 TWCR = 1<<TWEN; // Резисторы выключились :( По мануалу все должно работать. Есть соображения?