- GNU ARM Cross-toolchain – Compilação e OpenOCD
- GNU ARM Cross-toolchain – Configurando stack e heap
- GNU ARM Cross-toolchain – OpenOCD + GDB
- GNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery – Parte 1
- GNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery – Parte 2
- GNU ARM Cross-toolchain – Eclipse + FreeRTOS + GCC – Parte 1
- GNU ARM Cross-toolchain – Eclipse + FreeRTOS + GCC – Parte 2
A primeira parte deste artigo foi responsável por introduzir o sistema operacional de tempo-real FreeRTOS, caminhando um pouco pela sua estrutura de arquivos. Agora, nesta segunda parte, é abordada de forma prática os passos necessários para a migração da aplicação bare-metal para a sua versão baseada nesse sistema operacional. E agora, como começo a minha aplicação?
Pode-se utilizar (aliás, é aconselhado!) um dos projetos de demonstração oferecidos na pasta FreeRTOS/Demo, separados por arquitetura e compilador, como mostrado abaixo. Inicie usando uma aplicação de demonstração para garantir a sua correta compilação e, de forma incremental, substitua os arquivos do projeto exemplo por arquivos da aplicação final.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
Demo/ ├── ARM7_AT91FR40008_GCC ├── ARM7_AT91SAM7S64_IAR ├── ARM7_AT91SAM7X256_Eclipse ├── ARM7_LPC2106_GCC ├── ARM7_LPC2129_IAR ├── ARM7_LPC2129_Keil_RVDS ├── ARM7_LPC2138_Rowley ├── ARM7_LPC2368_Eclipse ├── ARM7_LPC2368_Rowley ├── ARM7_STR71x_IAR ├── ARM7_STR75x_GCC ├── ARM7_STR75x_IAR ├── ARM9_AT91SAM9XE_IAR ├── ARM9_STR91X_IAR ├── AVR32_UC3 ├── AVR_ATMega323_IAR ├── AVR_ATMega323_WinAVR ├── ColdFire_MCF51CN128_CodeWarrior ├── ColdFire_MCF52221_CodeWarrior ├── ColdFire_MCF52233_Eclipse ├── ColdFire_MCF52259_CodeWarrior ├── ColdFire_MCF5282_Eclipse ├── Common ├── CORTEX_A2F200_IAR_and_Keil ├── CORTEX_A2F200_SoftConsole ├── CORTEX_A9_RZ_R7S72100_IAR_DS-5 ├── CORTEX_A9_Zynq_ZC702 ├── CORTEX_AT91SAM3U256_IAR ├── CORTEX_ATSAM3S-EK2_Atmel_Studio ├── CORTEX_ATSAM3X_Atmel_Studio ├── CORTEX_CY8C5588_PSoC_Creator_GCC ├── CORTEX_CY8C5588_PSoC_Creator_Keil ├── CORTEX_CY8C5588_PSoC_Creator_RVDS ├── CORTEX_EFMG890F128_IAR ├── CORTEX_Kinetis_K60_Tower_IAR ├── CORTEX_LM3S102_GCC ├── CORTEX_LM3S102_Rowley ├── CORTEX_LM3S316_IAR ├── CORTEX_LM3S811_GCC ├── CORTEX_LM3S811_IAR ├── CORTEX_LM3S811_KEIL ├── CORTEX_LM3Sxxxx_Eclipse ├── CORTEX_LM3Sxxxx_IAR_Keil ├── CORTEX_LM3Sxxxx_Rowley ├── CORTEX_LPC1768_GCC_RedSuite ├── CORTEX_LPC1768_GCC_Rowley ├── CORTEX_LPC1768_IAR ├── CORTEX_M0+_Atmel_SAMD20_XPlained ├── CORTEX_M0_Infineon_XMC1000_IAR_Keil_GCC ├── CORTEX_M0_LPC1114_LPCXpresso ├── CORTEX_M0_STM32F0518_IAR ├── CORTEX_M4_ATSAM4E_Atmel_Studio ├── CORTEX_M4_ATSAM4L_Atmel_Studio ├── CORTEX_M4_ATSAM4S_Atmel_Studio ├── CORTEX_M4F_Infineon_XMC4000_GCC_Dave ├── CORTEX_M4F_Infineon_XMC4000_IAR ├── CORTEX_M4F_Infineon_XMC4000_Keil ├── CORTEX_M4F_Infineon_XMC4000_Tasking ├── CORTEX_M4F_Infineon_XMC4500_GCC_Atollic ├── CORTEX_M4F_M0_LPC43xx_Keil ├── CORTEX_M4F_STM32F407ZG-SK ├── CORTEX_MB9A310_IAR_Keil ├── CORTEX_MB9B500_IAR_Keil ├── CORTEX_MPU_LM3Sxxxx_Rowley ├── CORTEX_MPU_LPC1768_GCC_RedSuite ├── CORTEX_R4_RM48_TMS570_CCS5 ├── CORTEX_SmartFusion2_M2S050_SoftConsole ├── CORTEX_STM32F100_Atollic ├── CORTEX_STM32F103_GCC_Rowley ├── CORTEX_STM32F103_IAR ├── CORTEX_STM32F103_Keil ├── CORTEX_STM32F103_Primer_GCC ├── CORTEX_STM32F107_GCC_Rowley ├── CORTEX_STM32L152_Discovery_IAR ├── CORTEX_STM32L152_IAR ├── CORTUS_APS3_GCC ├── Cygnal ├── dsPIC_MPLAB ├── Flshlite ├── H8S ├── HCS12_CodeWarrior_banked ├── HCS12_CodeWarrior_small ├── HCS12_GCC_banked ├── lwIP_AVR32_UC3 ├── lwIP_Demo_Rowley_ARM7 ├── lwIP_MCF5235_GCC ├── MB91460_Softune ├── MB96340_Softune ├── MB96350_Softune_Dice_Kit ├── MCF5235_GCC ├── MicroBlaze ├── MicroBlaze_Spartan-6_EthernetLite ├── msp430_CrossWorks ├── msp430_GCC ├── msp430_IAR ├── MSP430X_MSP430F5438_CCS ├── MSP430X_MSP430F5438_IAR ├── NEC_78K0R_IAR ├── NEC_V850ES_IAR ├── NiosII_CycloneIII_DBC3C40_GCC ├── PC ├── PIC18_MPLAB ├── PIC18_WizC ├── PIC24_MPLAB ├── PIC32MX_MPLAB ├── PIC32MZ_MPLAB ├── PPC405_FPU_Xilinx_Virtex4_GCC ├── PPC405_Xilinx_Virtex4_GCC ├── PPC440_DP_FPU_Xilinx_Virtex5_GCC ├── PPC440_SP_FPU_Xilinx_Virtex5_GCC ├── PPC440_Xilinx_Virtex5_GCC ├── readme.txt ├── RL78_multiple_IAR ├── RL78_RL78G13_Promo_Board_IAR ├── RX100-RSK_GCC_e2studio ├── RX100-RSK_IAR ├── RX100-RSK_Renesas_e2studio ├── RX200_RX210-RSK_Renesas ├── RX600_RX62N-RDK_GNURX ├── RX600_RX62N-RDK_IAR ├── RX600_RX62N-RDK_Renesas ├── RX600_RX62N-RSK_GNURX ├── RX600_RX62N-RSK_IAR ├── RX600_RX62N-RSK_Renesas ├── RX600_RX630-RSK_Renesas ├── RX600_RX63N-RDK_Renesas ├── SuperH_SH7216_Renesas ├── TriCore_TC1782_TriBoard_GCC ├── uIP_Demo_IAR_ARM7 ├── uIP_Demo_Rowley_ARM7 ├── Unsupported_Demos ├── WIN32-MingW ├── WIN32-MSVC ├── WizNET_DEMO_GCC_ARM7 └── WizNET_DEMO_TERN_186 |
Para começar a trabalhar minimamente com o FreeRTOS, vamos entender como deve ser feita a migração da aplicação bare-metal que pisca leds no kit STM32F4Discovery, usada nos posts anteriores da série, para a sua versão baseada em RTOS. Esse processo já foi realizado e o novo projeto foi disponibilizado no GitHub. Execute o seguinte comando para obtê-lo:
Obs: Lembre-se que no primeiro post da série GNU ARM Cross-toolchain foi apresentada a organização do ambiente de desenvolvimento para os nossos projetos. Vale a pena seguir seus passos!
1 2 |
$ cd ~/work/projects $ git clone https://github.com/henriqueprossi/stm32f4-discovery-freertos.git |
O conteúdo da pasta stm32f4-discovery-freertos/hello_world, que contém os arquivos do projeto, é exibido abaixo:
1 2 3 4 5 6 |
hello_world/ ├── FreeRTOS ├── Libraries ├── makefile ├── project └── src |
Foram utilizados os mesmos arquivos da versão bare-metal do projeto. No entanto alguns pontos precisaram ser modificados, como é detalhado a seguir.
Anatomia de um projeto com FreeRTOS
Uma aplicação baseada no FreeRTOS é iniciada da mesma forma que uma aplicação bare-metal. Desde o reset até a chamada à função main(), o processo é o mesmo. Deve ser inicializado o ambiente de runtime da biblioteca C, configurada a pilha do sistema e inicializado o hardware utilizado. Em seguida deve ser criada pelo menos uma tarefa e ser chamada a função vTaskStartScheduler(), que entrega o controle da aplicação ao sistema operacional. Em seguida as tarefas são executadas de acordo com as suas prioridades.
Para que essa dinâmica seja possível na aplicação de pisca-leds, são necessárias as seguintes modificações:
- adicionar os arquivos-fonte do FreeRTOS ao projeto;
- informar os diretórios dos arquivos de cabeçalho do FreeRTOS;
- adicionar o arquivo FreeRTOSConfig.h ao projeto;
- configurar a tabela de vetores de exceções/interrupções;
- criar uma tarefa e inicializar o kernel.
Arquivos-fonte
O FreeRTOS, como explicado anteriormente, é composto por alguns arquivos que implementam o kernel e os serviços oferecidos pelo sistema operacional. Esses arquivos, listados abaixo, devem ser adicionados ao projeto, de forma que sejam compilados juntamente com todos os arquivos.
- FreeRTOS/Source/tasks.c;
- FreeRTOS/Source/queue.c;
- FreeRTOS/Source/list.c;
- FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c;
- FreeRTOS/Source/portable/MemMang/heap_2.c.
1 2 3 4 5 6 7 8 9 |
FREERTOS_DIR = $(PROJECT_DIR)/FreeRTOS/Source ... PROJ_C_SRC = $(PROJECT_DIR)/src/system_stm32f4xx.c \ ... $(FREERTOS_DIR)/list.c \ $(FREERTOS_DIR)/queue.c \ $(FREERTOS_DIR)/tasks.c \ $(FREERTOS_DIR)/portable/GCC/ARM_CM4F/port.c \ $(FREERTOS_DIR)/portable/MemMang/heap_2.c |
Caso seja necessário adicionar algum serviço do FreeRTOS à aplicação, seguem as opções oferecidas pelo sistema operacional e seus respectivos arquivos que devem ser adicionados ao projeto:
- Software timer: FreeRTOS/Source/timers.c;
- Event groups: FreeRTOS/Source/event_groups.c;
- Co-routines: FreeRTOS/Source/croutine.c.
Arquivos de cabeçalho
Alguns diretórios devem ser incluídos no caminho de procura de arquivos de cabeçalho do projeto. Dentre esses, pode-se citar:
- FreeRTOS/Source/include;
- FreeRTOS/Source/portable/GCC/ARM_CM4F.
1 2 3 4 |
PROJ_INC_DIR = $(PROJECT_DIR) \ ... $(FREERTOS_DIR)/include \ $(FREERTOS_DIR)/portable/GCC/ARM_CM4F |
Configuração do FreeRTOS – FreeRTOSConfig.h
Existe um arquivo de configuração do sistema operacional, chamado FreeRTOSConfig.h, que ajusta alguns parâmetros do kernel do FreeRTOS e habilita/desabilita alguns serviços, de acordo com a necessidade da aplicação que está sendo desenvolvida. É possível uma aplicação, por exemplo, fazer uso de event groups e possuir um tamanho de heap igual a 0x4000 bytes, ao passo que em outro projeto sejam utilizadas co-routines e faça uso de um heap de 0x2000 bytes. Também, como exemplo, nesse mesmo arquivo é habilitada ou desabilitada a preempção do scheduler. Como se trata de um arquivo específico da aplicação, ele deve estar localizado fora dos diretórios do sistema operacional. Sendo assim, tal caminho escolhido também deve ser adicionado ao projeto.
Tabela dos vetores de exceções/interrupções
Outro detalhe fundamental para o uso do FreeRTOS é a adaptação do vetor de exceções do microcontrolador. O core ARM Cortex-M3/4 contém, dentre muitos outros módulos, um controlador de exceções/interrupções chamado NVIC (Nested Vectored Interrupt Controller). Dentre as suas características, oferece tratamento de exceção/interrupção vetorizado. Isso significa que o processador busca o vetor correspondente à exceção ativa sem a necessidade de algum software calcular o endereço do handler da correspondente exceção. Ao contrário do que acontece com micro-processadores ARM clássicos, o NVIC obtém tal valor por meio de hardware, tendo como dados a posição inicial da tabela de vetores de exceções e o código da exceção. A localização da posição inicial dessa tabela, que é implementada como um array de words de 32 bits, é configurada por padrão no endereço 0x0 do mapa de memória do micro-processador, mas pode ser alterada em runtime. Dessa forma, a cada 4 bytes dentro dessa tabela de vetores é especificado o endereço de um handler para a respectiva exceção.
Algumas exceções do core ARM Cortex-M3/4 são tratadas pelo kernel do FreeRTOS, cujos handlers estão implementados na camada portable do sistema operacional. Veja a seguir quais são essas exceções.
SysTick timer
Todo RTOS faz uso de um timer periódico para gerenciamento do tick do scheduler. O core ARM Cortex-M3/4 oferece um timer dedicado para essa função, chamado de SysTick timer, não sendo necessário utilizar um periférico de timer genérico para essa função. É a partir da exceção causada pelo timeout desse timer que o kernel trata todo o gerenciamento de tempo do sistema, usando o tick do scheduler como parâmetro, e força a troca de contexto. Esse processo é iniciado gerando uma exceção de PendSV via software, como mostrado abaixo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
void xPortSysTickHandler( void ) { /* The SysTick runs at the lowest interrupt priority, so when this interrupt executes all interrupts must be unmasked. There is therefore no need to save and then restore the interrupt mask value as its value is already known. */ ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); { /* Increment the RTOS tick. */ if( xTaskIncrementTick() != pdFALSE ) { /* A context switch is required. Context switching is performed in the PendSV interrupt. Pend the PendSV interrupt. */ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } } portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 ); } |
PendSV
PendSV (Pended Service Call) é um tipo de exceção muito importante para suporte de operações de sistemas operacionais. Setando o bit 28, chamado de PENDSVSET, no registrador ICSR (Interrupt control and state register) do microcontrolador STM32F4xx, é indicado o estado pending da exceção PendSV para o NVIC. Assim que nenhuma exceção de maior prioridade que a PendSV estiver ativa, esta é atendida e seu handler é chamado, xPortPendSVHandler(), indicado na tabela de vetores do micro-processador. Veja abaixo o seu código:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
void xPortPendSVHandler( void ) { /* This is a naked function. */ __asm volatile ( " mrs r0, psp \n" " isb \n" " \n" " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ " ldr r2, [r3] \n" " \n" " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */ " it eq \n" " vstmdbeq r0!, {s16-s31} \n" " \n" " stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */ " \n" " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ " \n" " stmdb sp!, {r3} \n" " mov r0, %0 \n" " msr basepri, r0 \n" " bl vTaskSwitchContext \n" " mov r0, #0 \n" " msr basepri, r0 \n" " ldmia sp!, {r3} \n" " \n" " ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n" " \n" " ldmia r0!, {r4-r11, r14} \n" /* Pop the core registers. */ " \n" " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */ " it eq \n" " vldmiaeq r0!, {s16-s31} \n" " \n" " msr psp, r0 \n" " isb \n" " \n" #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */ #if WORKAROUND_PMU_CM001 == 1 " push { r14 } \n" " pop { pc } \n" #endif #endif " \n" " bx r14 \n" " \n" " .align 2 \n" "pxCurrentTCBConst: .word pxCurrentTCB \n" ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) ); } |
Essa exceção é responsável por realizar a troca de contexto do sistema, fazendo com que o scheduler substitua a tarefa sendo executada no momento pela tarefa de maior prioridade pronta para ser executada.
SVC
Assim como a exceção PendSV, a SVC (Supervisor Call) interpreta um papel fundamental nas implementações de sistemas operacionais. Essa exceção é causada pela instrução SVC, cujo handler é executado logo após esta chamada, a não ser que uma outra exceção de maior prioridade aconteça ao mesmo tempo.
Em muitos sistemas operacionais, o uso de Supervisor Call é utilizado como API para permitir que tarefas acessem recursos do sistema, fazendo uma ligação entre user space e kernel space. O FreeRTOS usa esse mecanismo, mas somente para executar a primeira tarefa do sistema, por meio da função prvPortStartFirstTask(), onde é feita a chamada SVC para o serviço número 0 (zero), como mostrado abaixo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
static void prvPortStartFirstTask( void ) { __asm volatile( " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ " ldr r0, [r0] \n" " ldr r0, [r0] \n" " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ " cpsie i \n" /* Globally enable interrupts. */ " dsb \n" " isb \n" " svc 0 \n" /* System call to start first task. */ " nop \n" ); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
void vPortSVCHandler( void ) { __asm volatile ( " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ " msr psp, r0 \n" /* Restore the task stack pointer. */ " isb \n" " mov r0, #0 \n" " msr basepri, r0 \n" " bx r14 \n" " \n" " .align 2 \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n" ); } |
Criação de uma tarefa e inicialização do kernel
Agora resta somente mais um passo! Precisa ser criada uma tarefa, por meio da API do FreeRTOS, usando a função xTaskCreate(), e inicializar o kernel com a chamada à função vTaskStartScheduler().
Na aplicação disponibilizada foi criada uma tarefa para executar exatamente a mesma função da aplicação bare-metal estudada até então: acender os leds da placa STM32F4Discovery de forma sequencial. Segue parte do código da aplicação:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
int main(void) { ... // The task for blinking the led's is created. It is called just after the scheduler is started. xTaskCreate( leds_blink_task , "leds_blink_task" , configMINIMAL_STACK_SIZE , NULL , tskIDLE_PRIORITY , NULL ); // It is started the scheduler. vTaskStartScheduler(); /* If all is well, the scheduler will now be running, and the following line will never be reached. * If the following line does execute, then there was insufficient FreeRTOS heap memory available * for the idle and/or timer tasks to be created. See the memory management section on the * FreeRTOS web site for more details. */ for (;;); return 0; } static void leds_blink_task(void * parameters) { for (;;) { GPIO_SetBits(GPIOD, LED4_PIN); // LED4 ON vTaskDelay(1000 / portTICK_RATE_MS); GPIO_SetBits(GPIOD, LED3_PIN); // LED3 ON vTaskDelay(1000 / portTICK_RATE_MS); GPIO_SetBits(GPIOD, LED5_PIN); // LED5 ON vTaskDelay(1000 / portTICK_RATE_MS); GPIO_SetBits(GPIOD, LED6_PIN); // LED6 ON vTaskDelay(1000 / portTICK_RATE_MS); GPIO_ResetBits(GPIOD, LED4_PIN | LED3_PIN | LED5_PIN | LED6_PIN); // All LEDs are OFF. vTaskDelay(1000 / portTICK_RATE_MS); } } |
Pronto! Agora a aplicação bare-metal está migrada para uma versão com o FreeRTOS. Vamos compilá-la e depurá-la com o que aprendemos até aqui? Conecte a sua placa STM32F4Discovery no seu PC com o cabo USB e execute os seguintes comandos para compilar a aplicação e iniciar o servidor GDB, o OpenOCD:
1 2 3 |
$ cd ~/work/projects/stm32f4-discovery-freertos/hello_world $ make $ openocd -s ~/work/tools/openocd/share/openocd/scripts -f board/stm32f4discovery.cfg |
As mensagens abaixo devem ser exibidas. Neste momento o OpenOCD já iniciou o seu servidor GDB e está aguardando comandos do aplicativo cliente.
1 2 3 4 5 6 7 8 9 10 |
Open On-Chip Debugger 0.8.0 (2014-08-23-18:03) Licensed under GNU GPL v2 For bug reports, read http://openocd.sourceforge.net/doc/doxygen/bugs.html srst_only separate srst_nogate srst_open_drain connect_deassert_srst Info : This adapter doesn't support configurable speed Info : STLINK v2 JTAG v14 API v2 SWIM v0 VID 0x0483 PID 0x3748 Info : using stlink api v2 Info : Target voltage: 2.905263 Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints |
O passo seguinte é, em outro prompt do shell, inicializar o cliente GDB, indicar a aplicação a ser depurada e executar comandos de gravação/depuração no prompt do cliente GDB, como mostrado abaixo:
1 2 3 4 5 6 7 8 9 10 11 |
$ arm-none-eabi-gdb build/hello_world.elf (gdb) target remote localhost:3333 (gdb) monitor reset init (gdb) monitor flash erase_sector 0 0 last (gdb) load (gdb) monitor soft_reset_halt (gdb) break main (gdb) continue (gdb) break leds_blink_task (gdb) continue (gdb) continue |
Como esperado, os leds acedem da mesma forma que aconteceu com a aplicação bare-metal. Verificamos que o breakpoint é ativado na primeira e nas seguintes execuções do loop da tarefa leds_blink_task. Agora é só criar mais tarefas para a brincadeira ficar mais divertida. Isso fica a gosto do cliente! E a função main(), não é mais executada? Não! Todo o controle de qual tarefa a ser executada está sob a responsabilidade do scheduler do FreeRTOS. Nos momentos em que não existem tarefas com alguma atividade a ser realizada, como acontece no momento em que a função vTaskDelay() é chamada, a tarefa Idle do RTOS é executada. Mas o que ganhamos com isso? Nos próximos posts explicaremos as diferenças e, principalmente, o que é oferecido de vantagem com essa nova implementação. Aguardem!
Boa tarde Henrique!!!!
Como fazer o upload para o microcontrolador?
Li todos os artigos, mas agora como faço o upload?
Ola, o upload é feito quando você digita: arm-none-eabi-gdb build/hello_world.elf, os outros comandos e depois o comando load
Olá Wellington,
Como o Vinicius disse, a gravação no microcontrolador acontece no comando load, que carrega o binário hello_world.elf na memória Flash.
Abraços,
Henrique
Opa! Consegui implementar muita coisa usando o FreeRTOS no projeto que estou desenvolvendo usando um uC Tiva TM4C123G. Demorei um pouco para entender como se configurar os parâmetros necessários no arquivo FreeRTOSConfig.h. O restante, saiu funcionando quase que direto. Estou usando semáforos, filas e, claro, tasks. O que achei mais legal é que me acelerou muito o desenvolvimento, principalmente pois eu nunca havia trabalhado com RTOSses e sei do trabalho que eu teria para fazer a mesma coisa usando uma abordagem bare metal. Acho que um trabalho futuro será determinar os valores das prioridades das tasks e determinar o quanto… Leia mais »
Muito legal Rafael! Pretendemos disponibilizar esse tipo de conteúdo no Embarcados. Vamos acelerar o processo! E muito obrigado pelos seus comentários! 🙂
Abraços!
Hoje me aconteceu uma coisa curiosa. Uma das interfaces que estou desenvolvendo aqui é uma comunicação RS-485 entre dois sistemas. Como estou em uma rede RS-485, tenho que controlar a direção do canal de comunicação através de um pino DE (Data Enable). Bom, esse controle eu deixei a cargo de um timer. Fiz algo assim (vou colar partes do código para dar uma idéia): http://pastebin.com/1aKLgvx6 Bom, na função RS485Open eu crio um timer e o utilizo assim que envio os dados pela porta serial, utilizando a função RS485Write. Assim que os dados são enviados, o timer é iniciado e deveria… Leia mais »
Olá Rafael, tudo bem? Desculpa pela demora na resposta…eu vi a sua pergunta esses dias rs Na sua chamada a xTimerCreate, xTimerPeriod = 2 / portTICK_RATE_MS ajusta o timer para um período de 2 ms, não 1 ms. E a prioridade do serviço de timer, dada pela constante configTIMER_TASK_PRIORITY, deve ser ajustada para que justamente o período de timeout do respectivo timer seja o mais próximo do ajustado. Provavelmente alguma tarefa de alta prioridade está “segurando” o processamento do escalonador, e a tarefa do timer não esteja sendo executada no seu devido tempo. Tente aumentar gradativamente a prioridade do timer… Leia mais »
Olá Henrique,
Agora estou com uma placa em mãos.
Passei por todos os post relacionados, e todos rodaram muito bem.
Como já onvi falarem (se não me engano, o próprio Sérgio Prado no blog), engenheiros de software, são pessoas extremamente ansiosas por botar a mão na massa.
Quando chegam os próximos posts?
Serão abordados mais detalhes sobre o FreeRTOS? As demais funcionalidades? Mais exemplos? Como canais de comunicação? Compartilhamento de recursos? Uso de interrupções?
E como sempre, excelente post.
Abraço.
Eduardo Scherrer
Olá Eduardo!
Agora não tem desculpa para não usar a placa!! 😉
Essa série não vai parar por aqui! Teremos um post de Eclipse, e em seguida posts teóricos e práticos sobre o FreeRTOS, tais como: sincronização entre tarefas, compartilhamento de recursos, redução do consumo de energia gerado, e outros. Vamos estudar a possibilidade de serem usados todos os canais de comunicação da placa. Pretendemos ter um post dessa série a cada uma ou duas semanas.
Muito obrigado pelos elogios e acompanhamento do site!! Fique ligado! 🙂
Abraços!
Boa noite Henrique,
Muito bom hein. Agora fiquei mais empolgado.
Eu cheguei a comprar a documentação para o uC da NXP. Mas só na teoria não vira, preciso de exemplos para firmar mais os conceitos.
Abraço e obrigado.
Eduardo Scherrer
Oi Eduardo, boa noite!
Tentaremos trabalhar com outros microcontroladores também, não sabemos se nessa série. Vamos ver como vai ficar! Mas com relação a FreeRTOS teremos mais conteúdo.
Eu que agradeço! Abraços
Esta semana eu comecei a trabalhar em um projeto utilizando microcontroladores da Texas (lm4f232h5qd). Como estou com liberdade de usar qualquer ferramenta, vou partir para o uso do FreeRTOS.
Acho que dará para brincar um pouco. =P
A Tivaware deve ajudar no desenvolvimento…deve ser bem legal trabalhar com esses microcontroladores. Mande notícias!! 🙂
Abraços!
Eu ainda estou aprendendo a trabalhar com a tiviaware. Já gostei pois é mais documentado do que a StdPeripheralLibrary da ST.
Vamo que vamo!
[…] GNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery – Parte 2 […]
[…] GNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery – Parte 2 […]
[…] GNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery – Parte 2 […]
[…] GNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery – Parte 2 […]
[…] o uso de um sistema operacional de tempo-real, RTOS, usando o FreeRTOS como alternativa. Na segunda parte serão apresentados os passos que devem ser seguidos para a migração da aplicação bare-metal […]
[…] GNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery – Parte 2 […]
[…] GNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery – Parte 2 […]