O objetivo deste BLOG é demonstrar como é possível utilizar o NuttX para programação do U-BLOX NINA W106. Foi utilizado o EVK U-BLOX NINA W106.
Adaptação e Tradução do Blog da embetronicx
Testado no Ubuntu 20
NuttX: O sistema operacional para a Internet das Coisas.
NuttX é um sistema operacional em tempo real (RTOS) com ênfase na conformidade de padrões e pequeno footprint. Escaláveis de ambientes microcontroladores de 8 bits a 64 bits, os principais padrões de governo em NuttX são os padrões Posix e ANSI. ApIs padrão adicionais do Unix e de outros RTOS comuns (como o VxWorks) são adotadas para funcionalidades não disponíveis sob esses padrões, ou para funcionalidades que não são apropriadas para ambientes profundamente incorporados (como fork()).
Apache NuttX é um esforço em incubação na Apache Software Foundation (ASF), patrocinada pela Incubadora. A incubação é necessária de todos os projetos recém-aceitos até que uma nova revisão indique que o processo de infraestrutura, comunicação e tomada de decisão se estabilizou de forma consistente com outros projetos ASF bem-sucedidos. Embora o status de incubação não seja necessariamente um reflexo da completude ou estabilidade do código, ele indica que o projeto ainda não foi totalmente endossado pela ASF.
NuttX é um sistema operacional incorporado em tempo real (RTOS). Seus objetivos são:
Rich Feature OS Set
O objetivo é fornecer implementações da maioria das interfaces padrão do SISTEMA OPERACIONAL POSIX para oferecer suporte a um ambiente de desenvolvimento rico e multi-threaded para processadores profundamente incorporados.
Não é um objetivo fornecer o nível de recursos do SO como os fornecidos pelo Linux. Para trabalhar com MCUs menores, a pequena footprint deve ser mais importante do que um conjunto de recursos extenso. Mas a conformidade padrão é mais importante do que uma pequena footprint. Certamente um RTOS menor poderia ser produzido ignorando padrões. Pense no NuttX é um pequeno trabalho linux com um conjunto de recursos muito reduzido.
Altamente escalável
Totalmente escalável de minúsculo (8 bits) a moderado incorporado (64 bits). A escalabilidade com conjunto de recursos ricos é realizada com: Muitos arquivos de origem minúsculos, link de bibliotecas estáticas, altamente configurável, uso de símbolos fracos quando disponíveis.
Conformidade de padrões
A NuttX se esforça para alcançar um alto grau de conformidade de padrões. As principais normas de governo são as normas POSIX e ANSI. ApIs padrão adicionais do Unix e de outros RTOS comuns são adotadas para funcionalidades não disponíveis sob esses padrões ou para funcionalidades que não são apropriadas para os RTOS profundamente incorporados (como fork()).
Devido a essa conformidade de padrões, o software desenvolvido sob outros OSs padrão (como o Linux) deve ser portado facilmente para NuttX.
Tempo Real Totalmente preventivo; prioridade fixa, round-robin, e agendamento "esporádico".
Licença Apache não restritiva totalmente aberta.
GNU Toolchains Compatíveis com as cadeias de ferramentas GNU baseadas no buildroot disponível para download para fornecer um ambiente completo de desenvolvimento para muitas arquiteturas.
Colocando Nuttx no U-BLOX NINA W106
O link abaixo, é roteiro Básico para que você possa preparar o ambiente para programar o U-BLOX NINA W106 com o NuttX
Dependências
$sudo apt install \
bison flex gettext texinfo libncurses5-dev libncursesw5-dev \
gperf automake libtool pkg-config build-essential gperf genromfs \
libgmp-dev libmpc-dev libmpfr-dev libisl-dev binutils-dev libelf-dev \
libexpat-dev gcc-multilib g++-multilib picocom u-boot-tools util-linux
Nota 1: O NuttX utiliza um sistema de build semelhante ao do Kernel do Linux (https://www.kernel.org/doc/html/latest/kbuild/index.html). Ele utiliza o kconfig-frontends como seu sistema de configuração. O repositório tools.git é utilizado para instalar este pacote. Porém se você estiver usando o Ubuntu 19.10 ou mais recente, estas distribuições já contém o pacote, mas de qualquer forma, instale.
$ sudo apt-get install kconfig-frontends
Nota 2: Outra dependência para o processo do NuttX com o ESP32 é o ESP-IDF (Espressif IoT Development Framework). Este framework é nativo do ESP e mantido pela Espressif. Ele compreende um conjunto de códigos como drivers, APIs, scripts, ferramental para compilar e fazer upload do firmware e o FreeRTOS customizado. Neste ponto, uma observação conceitual é muito importante, o NuttX não usa o FreeRTOS em nenhuma camada interna, apenas algumas ferramentas auxiliares que compõem o IDF serão utilizadas para geração do binário e gravação.
Download do NuttX
$ mkdir nuttx
$ cd nuttx
$ git clone https://github.com/apache/incubator-nuttx.git nuttx
$ git clone https://github.com/apache/incubator-nuttx-apps apps
O Ubuntu e o Debian ainda fornecem o Python 2.7 como o interpretador padrão, mas alguns
pacotes necessários podem estar faltando para distribuições mais recentes. Python 3 é
recomendado e pode ser instalado da seguinte maneira:
$ sudo apt-get install python3 python3-pip python3-setuptool
$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3
Instale agora o ESP-IDF (ESP32 TOOLS, LIBS, ETC) manualmente
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/linux-setup.html
(ESP-IDF) extrair
mkdir -p ~/esp
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git
osboxes@osboxes:~$ cd esp/
osboxes@osboxes:~/esp$ cd esp-idf/
osboxes@osboxes:~/esp/esp-idf$ ./install.sh
Detecting the Python interpreter
Checking "python" ...
/home/osboxes/esp/esp-idf/tools/detect_python.sh: line 16: python: command not found
Checking "python3" ...
Python 3.8.5
"python3" has been detected
Installing ESP-IDF tools
Installing tools: xtensa-esp32-elf, xtensa-esp32s2-elf, xtensa-esp32s3-elf, riscv32-esp-elf, esp32ulp-elf, esp32s2ulp-elf, openocd-esp32
Installing xtensa-esp32-elf@esp-2020r3-8.4.0
Downloading xtensa-esp32-elf-gcc8_4_0-esp-2020r3-linux-amd64.tar.gz to /home/osboxes/.espressif/dist/xtensa-esp32-elf-gcc8_4_0-esp-2020r3-linux-amd64.tar.gz.tmp
Done
Extracting /home/osboxes/.espressif/dist/xtensa-esp32-elf-gcc8_4_0-esp-2020r3-linux-amd64.tar.gz to /home/osboxes/.espressif/tools/xtensa-esp32-elf/esp-2020r3-8.4.0
Installing xtensa-esp32s2-elf@esp-2020r3-8.4.0
Downloading xtensa-esp32s2-elf-gcc8_4_0-esp-2020r3-linux-amd64.tar.gz to /home/osboxes/.espressif/dist/xtensa-esp32s2-elf-gcc8_4_0-esp-2020r3-linux-amd64.tar.gz.tmp
Done
.
.
.
$ cd nuttx
$ make -C tools/esp32/ ${HOME}/esp/esp-idf
Após a instalação do IDF, ou caso já possua o IDF instalado, execute o
seguinte comando para ativar o ambiente virtual que foi configurado na
instalação. Sempre que for realizar o build do NuttX, será necessário
ativar este ambiente.
$. ${HOME}/esp/esp-idf/export.sh
No presente momento, o NuttX utiliza 2 binários gerados através do
IDF: o bootloader e a tabela de partição. Ainda dentro do diretório
/nutxtx/nuttx/, faça o download destes binários pré configurados:
$ wget -O bootloader.bin https://github.com/saramonteiro/esp32_binaries_nuttx/blob/main/bootloader.bin?raw=true
$ wget -O partitions.bin https://github.com/saramonteiro/esp32_binaries_nuttx/blob/main/partitions.bin?raw=true
Mantenha-se no diretório do NuttX e execute o script de configuração para criar um arquivo de configuração para o
U-BLOX NINA W106.
$ make distclean
uttX has not been configured!
To configure the project:
tools/configure.sh <config>
For a list of available configurations:
tools/configure.sh -L
$ ./tools/configure.sh esp32-devkitc:nsh
Finalmente, faça o build e confirme em seguida que o firmware binário foi gerado:
$ make
osboxes@osboxes:~/nuttx/nuttx$ make
Create .version
Create version.h
LN: include/arch/board to /home/osboxes/nuttx/nuttx/boards/xtensa/esp32/esp32-devkitc/include
make[1]: Entering directory '/home/osboxes/nuttx/nuttx/libs/libxx'
make[1]: Leaving directory '/home/osboxes/nuttx/nuttx/libs/libxx'
make[1]: Nothing to be done for 'dirlinks'.
make[1]: Entering directory '/home/osboxes/nuttx/nuttx/boards'
make[1]: Entering directory '/home/osboxes/nuttx/nuttx/openamp'
make[1]: Nothing to be done for 'dirlinks'.
make[1]: Leaving directory '/home/osboxes/nuttx/nuttx/boards'
make[1]: Nothing to be done for 'dirlinks'.
make[2]: Entering directory '/home/osboxes/nuttx/apps/platform'
make[1]: Leaving directory '/home/osboxes/nuttx/nuttx/openamp'
make[1]: Entering directory '/home/osboxes/nuttx/apps'
LN: platform/board to /home/osboxes/nuttx/apps/platform/dummy
make[2]: Entering directory '/home/osboxes/nuttx/nuttx/boards/xtensa/esp32/common'
make[2]: Leaving directory '/home/osboxes/nuttx/apps/platform'
make[1]: Leaving directory '/home/osboxes/nuttx/apps'
make[1]: Entering directory '/home/osboxes/nuttx/nuttx/boards'
make[2]: Nothing to be done for 'context'.
make[1]: Nothing to be done for 'context'.
make[2]: Leaving directory '/home/osboxes/nuttx/nuttx/boards/xtensa/esp32/common'
make[1]: Leaving directory '/home/osboxes/nuttx/nuttx/boards'
make[1]: Entering directory '/home/osboxes/nuttx/nuttx/fs'
make[1]: Leaving directory '/home/osboxes/nuttx/nuttx/fs'
make[2]: Entering directory '/home/osboxes/nuttx/apps'
make[1]: Entering directory '/home/osboxes/nuttx/apps'
.
.
.
make[3]: Leaving directory '/home/osboxes/nuttx/apps/system/readline'
make[2]: Leaving directory '/home/osboxes/nuttx/apps'
IN: /home/osboxes/nuttx/apps/libapps.a -> staging/libapps.a
make[1]: Leaving directory '/home/osboxes/nuttx/apps'
make[1]: Leaving directory '/home/osboxes/nuttx/nuttx/fs'
make[1]: Entering directory '/home/osboxes/nuttx/nuttx/fs'
make[1]: 'libfs.a' is up to date.
make[1]: Leaving directory '/home/osboxes/nuttx/nuttx/binfmt'
make[1]: Entering directory '/home/osboxes/nuttx/nuttx/binfmt'
make[1]: 'libbinfmt.a' is up to date.
make[2]: 'libboard.a' is up to date.
make[1]: Entering directory '/home/osboxes/nuttx/nuttx/arch/xtensa/src'
make[2]: Entering directory '/home/osboxes/nuttx/nuttx/boards/xtensa/esp32/common'
CP: nuttx.hex
make[2]: Leaving directory '/home/osboxes/nuttx/nuttx/boards/xtensa/esp32/common'
LD: nuttx
make[1]: Leaving directory '/home/osboxes/nuttx/nuttx/arch/xtensa/src'
CP: nuttx.bin
osboxes@osboxes:~/nuttx/nuttx$
**Este binário não tem os cabeçalhos com as informações que o bootloader do ESP32 espera encontrar, então ele deve ser removido:
$ rm nuttx.bin
E um novo binário deverá ser gerado a partir do arquivo ELF chamado “nuttx”. Para isso, é necessário usar o script esptool.py para gerar este arquivo:
esptool.py --chip esp32 elf2image --flash_mode dio --flash_size 4MB -o ./nuttx.bin nuttx
Você pode configurar U-BLOX NINA W106 via
$ make menuconfig
.config - NuttX/x86_64 Configuration
────────────────────────────────────────────────────────────────────────────────────
┌───────────────────────── NuttX/x86_64 Configuration ──────────────────────────┐
│ Arrow keys navigate the menu. <Enter> selects submenus ---> (or empty │
│ submenus ----). Highlighted letters are hotkeys. Pressing <Y> includes, │
│ <N> excludes, <M> modularizes features. Press <Esc><Esc> to exit, <?> for │
│ Help, </> for Search. Legend: [*] built-in [ ] excluded <M> module < > │
│ ┌───────────────────────────────────────────────────────────────────────────┐ │
│ │ Build Setup ---> │ │
│ │ System Type ---> │ │
│ │ Board Selection ---> │ │
│ │ RTOS Features ---> │ │
│ │ Device Drivers ---> │ │
│ │ Networking Support ---> │ │
│ │ Crypto API ---> │ │
│ │ File Systems ---> │ │
│ │ Graphics Support ---> │ │
│ │ Memory Management ---> │ │
│ │ Audio Support ---> │ │
│ │ Video Support ---> │ │
│ │ Wireless Support ---> │ │
│ │ Binary Loader ---> │ │
│ │ Library Routines ---> │ │
│ │ Open Asymmetric Multi Processing ---> │ │
│ │ Application Configuration ---> │ │
│ └───────────────────────────────────────────────────────────────────────────┘ │
├───────────────────────────────────────────────────────────────────────────────┤
│ <Select> < Exit > < Help > < Save > < Load > │
└───────────────────────────────────────────────────────────────────────────────┘
make menuconfig customiza o que deseja adicionar/retirar na placa. Por exemplo, permite adicionar os drivers de um determinado periférico, adicionar mensagens de debug, etc.
Anote endereços de Gravação
Controlando LEDs
Vamos escrever um código para controlar os LEDs. Basicamente, o NuttX é um sistema operacional compatível com POSIX e gosta de usar a mesma convenção de nomenclatura de muitas das funções e arquivos que você encontraria em seu sistema UNIX / Linux padrão. E está operando como um sistema Linux. Em um sistema Linux, temos que escrever um driver de kernel para conversar com o hardware. Este driver do kernel residirá no espaço do kernel. E o aplicativo precisa estar lá para falar com o driver do kernel. Esse aplicativo residirá no espaço do usuário.
Portanto, vamos desenvolver um driver de LED e uma aplicação de LED. Se você já está familiarizado com o driver do kernel Linux e um aplicativo de espaço do usuário, prometo que será muito fácil entender o NuttX RTOS. Se você não estiver familiarizado também está bem. Você aproveita a chance e aprende o NuttX RTOS. Tenho certeza que você vai começar a adorar trabalhar com drivers do kernel Linux e também em um aplicativo.
Vamos começar. Estamos dividindo o tutorial em duas partes.
- Escrevendo um driver de LED
- Escrevendo um aplicativo
Escrevendo um driver de LED
No Linux / POSIX, todas as coisas são consideradas como um arquivo. Então, vamos criar um arquivo em /dev/. Em nosso exemplo, nosso driver criará o arquivo /dev/etx_led.
Primeiro, vamos ver o código abaixo.
esp32_etx_led.c
Eu adicionei este arquivo ao nuttx/boards/xtensa/esp32/common/src/
.
sp32_etx_led.h
/****************************************************************************
* boards/xtensa/esp32/common/src/esp32_etx_led.c
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
****************************************************************************/
/****************************************************************************
****************************************************************************/
#include <nuttx/config.h>
#include <arch/board/board.h>
#include "esp32-devkitc.h"
#include "esp32_etx_led.h"
#ifdef CONFIG_ESP32_ETX_LED
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* Character driver methods */
static int etx_led_open(FAR struct file *filep);
static int etx_led_close(FAR struct file *filep);
static ssize_t etx_led_write(FAR struct file *filep, FAR const char *buffer,
/****************************************************************************
****************************************************************************/
static const struct file_operations etx_led_fops =
etx_led_close, /* close */
etx_led_write, /* write */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
/****************************************************************************
****************************************************************************/
/****************************************************************************
* This function will be getting called when the application
* opens the "/dev/etx_led" file.
****************************************************************************/
static int etx_led_open(FAR struct file *filep)
/****************************************************************************
* This function will be getting called when the application
* closess the "/dev/etx_led" file.
****************************************************************************/
static int etx_led_close(FAR struct file *filep)
/****************************************************************************
* This function will be getting called when the application
* writes data the "/dev/etx_led" file.
****************************************************************************/
static ssize_t etx_led_write(FAR struct file *filep, FAR const char *buffer,
DEBUGASSERT(buffer != NULL);
//buffer[0] contains the value (ON/OFF)
//buffer[1] contains the GPIO Number
int32_t value = buffer[0];
int32_t gpio_pin = buffer[1];
if( gpio_pin < 0 || gpio_pin > ESP32_NGPIOS )
syslog(LOG_ERR, "Invalid GPIO Number - %d\n", gpio_pin);
// Configure the GPIO as Output
esp32_configgpio( gpio_pin, OUTPUT );
//syslog(LOG_ERR, "GPIO Number - %d\n", gpio_pin);
//syslog(LOG_ERR, "value - %d\n", value);
esp32_gpiowrite(gpio_pin, value);
/****************************************************************************
****************************************************************************/
/****************************************************************************
* Name: etx_led_driver_init
* Initialize the EmbeTronicX LED device Driver.
* This will create the device file as "/dev/etx_led"
* return negative number on failure.
****************************************************************************/
int etx_led_driver_init( void )
ret = register_driver("/dev/etx_led", &etx_led_fops, 0666, NULL);
_err("ERROR: register_driver failed : /dev/etx_led : %d\n", ret);
#endif /* CONFIG_ESP32_ETX_LED */
esp32_etx_led.h
Eu adicionei este arquivo ao caminho nuttx/boards/xtensa/esp32/common/include/
.
/****************************************************************************
* boards/xtensa/esp32/common/include/esp32_etx_led.h
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
****************************************************************************/
#ifndef __BOARDS_XTENSA_ESP32_COMMON_INCLUDE_ETX_LED_H
#define __BOARDS_XTENSA_ESP32_COMMON_INCLUDE_ETX_LED_H
/****************************************************************************
****************************************************************************/
#include <nuttx/config.h>
#define EXTERN extern "C"
/****************************************************************************
* Name: etx_led_driver_init
* Initialize the EmbeTronicX LED device Driver.
* This will create the device file as "/dev/etx_led"
* return negative number on failure.
****************************************************************************/
#ifdef CONFIG_ESP32_ETX_LED
int etx_led_driver_init( void );
#endif
#endif /* __BOARDS_XTENSA_ESP32_COMMON_INCLUDE_ETX_LED_H */
Explicação do código
Vou apenas explicar a você o código que foi fornecido acima.
Existe uma função chamada etx_led_driver_init(), que é um ponto de partida do driver e registra o driver e cria o arquivo do dispositivo chamado /dev/etx_led.
Existe uma estrutura chamada
struct file_operations etx_led_fops. Utilizando esta estrutura file_operations, estamos registrando nossos funções open(), close() e write().
open()
A função será chamada sempre que o aplicativo abrir o arquivo /dev/etx_led.
close()
A função será chamada sempre que o aplicativo fechar o arquivo /dev/etx_led
write()
A função é chamada quando o aplicativo grava algo no arquivo /dev/etx_led
Na função write(), estamos configurando o GPIO como uma saída usando o esp32_configgpio(). E defina o valor para esse GPIO usando o esp32_gpiowrite(). Portanto, sempre que um aplicativo quiser ligar ou desligar os LEDs, ele deve escrever o número GPIO e o valor neste driver.
Como já te disse, etx_led_driver_init() é o ponto de partida do driver. Mas alguém tem que ligar para isso. Estamos chamando essa função de esp32_bringup.c. Estou adicionando o código abaixo na função esp32_bringup() do nuttx/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c
#ifdef CONFIG_ESP32_ETX_GPIO
#include "esp32_etx_gpio.h"
#ifdef CONFIG_ESP32_ETX_GPIO
/* Register the EmbeTronicX GPIO Driver */
ret = etx_gpio_driver_init();
syslog(LOG_ERR, "ERROR: etx_gpio_driver_init() failed: %d\n", ret);
int esp32_bringup(void)
{
int ret;
#ifdef CONFIG_ESP32_ETX_GPIO
#include "esp32_etx_gpio.h"
#endif
#ifdef CONFIG_ESP32_ETX_GPIO
/* Register the EmbeTronicX GPIO Driver */
ret = etx_gpio_driver_init();
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: etx_gpio_driver_init() failed: %d\n", ret);
}
#endif
Makefile
Agora temos que construir este driver. Então, temos que adicionar as linhas abaixo dentro do nuttx/boards/xtensa/esp32/common/src/Make.defs
ifeq ($(CONFIG_ESP32_ETX_GPIO),y)
CSRCS += esp32_etx_gpio.c
# License for the specific language governing permissions and limitations
# under the License.
#
#############################################################################
ifeq ($(CONFIG_ESP32_ETX_GPIO),y)
CSRCS += esp32_etx_gpio.c
endif
ifeq ($(CONFIG_WATCHDOG),y)
CSRCS += esp32_board_wdt.c
endif
Kconfig
Até agora, estamos prontos com o driver LED. Mas se adicionarmos uma opção para habilitar / desabilitar este driver durante a compilação, seria muito bom. Então, para fazer isso, estou adicionando as linhas abaixo ao arquivo nuttx/boards/xtensa/esp32/common/Kconfig.
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
comment "Drivers added by EmbeTronicX (www.embetronicx.com)"
menu "EmbeTronicX Drivers"
config ESP32_ETX_LED
bool "EmbeTronicX LED driver"
default n
---help---
Enables the GPIOs to control the LEDs (ESP32).
This is added by the EmbeTroincX to demonstrate the
LED control using the ESP32 Dev board with NuttX.
This includes the EmbeTronicX LED driver which controls
the output.
endmenu # EmbeTronicX Drivers
Isso é tudo sobre o driver. Vamos escrever nosso aplicativo para acessar este driver. Você pode consultar este commit no GitHub para as alterações acima. Se você quiser o código-fonte completo, pegue o código do GitHub .
Escrevendo um aplicativo
No aplicativo, vou criar uma tarefa chamada ETX_LED usando a função task_create(). Nessa tarefa, estou escrevendo o número GPIO e seu valor para o driver /dev/etx_led. Olhe o código abaixo.
etx_led_app.c
Estou criando um novo diretório chamado etx_led
abaixo de apps/examples
.
/****************************************************************************
* examples/etx_led/etx_led_app.c
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
****************************************************************************/
/****************************************************************************
****************************************************************************/
#include <nuttx/config.h>
#ifdef CONFIG_EXAMPLES_ETX_LED
#define ETX_LED_DRIVER_PATH "/dev/etx_led" // LED Driver path
/****************************************************************************
****************************************************************************/
static struct gpio etx_gpio;
/****************************************************************************
****************************************************************************/
/****************************************************************************
****************************************************************************/
static int etx_led_task(int argc, char *argv[])
printf("ETX_LED: Task Starting\n");
int fd = open( ETX_LED_DRIVER_PATH, O_WRONLY);
printf("ETX_LED:ERROR - Failed to open %s: %d\n", ETX_LED_DRIVER_PATH, errno);
printf("ETX_LED: GPIO = %d Value %d\n", etx_gpio.gpio_num, etx_gpio.gpio_val);
ret = write( fd, (const void*)&etx_gpio, sizeof(etx_gpio) );
etx_gpio.gpio_val = !etx_gpio.gpio_val;
printf("ETX_LED: ERROR - Task finishing\n");
/****************************************************************************
****************************************************************************/
/****************************************************************************
****************************************************************************/
int main(int argc, FAR char *argv[])
printf("ETX_LED: Starting the Application\n");
printf("Usage : etx_led needs one argument which is GPIO number to toggle\n");
printf("Example : To toggle the GPIO 2, please enter \"etx_led 2\"\n");
etx_gpio.gpio_val = 1; //Initialy turn ON the LED
etx_gpio.gpio_num = atoi(argv[1]); //Get the GPIO Number from user
ret = task_create( "ETX_LED", // Task Name
CONFIG_EXAMPLES_ETX_LED_PRIORITY, // Task priority
CONFIG_EXAMPLES_ETX_LED_STACKSIZE, // Task Stack size
etx_led_task, // Task function
printf("ETX_LED: ERROR: Failed to start ETX LED task: %d\n", errcode);
#endif //#ifdef CONFIG_EXAMPLES_ETX_LED
Junto com etx_led_app.c, estou criando mais três arquivos chamados Makefile, Make.defs e Kconfig no diretório apps/examples/etx_led.
canard fboverlay igmp mld nxdemo pppd smps unionfs
osboxes@osboxes:~/nuttx/apps/examples$ mkdir etx_led
osboxes@osboxes:~/nuttx/apps/examples$ cd etx_led/
osboxes@osboxes:~/nuttx/apps/examples/etx_led$
osboxes@osboxes:~/nuttx/apps/examples/etx_led$ ls
etx_led_app.c
osboxes@osboxes:~/nuttx/apps/examples/etx_led$ nano Makefile
osboxes@osboxes:~/nuttx/apps/examples/etx_led$ nano Make.defs
osboxes@osboxes:~/nuttx/apps/examples/etx_led$ nano Kconfig
osboxes@osboxes:~/nuttx/apps/examples/etx_led$ ls -l
total 16
-rw-rw-r-- 1 osboxes osboxes 4023 Nov 30 09:49 etx_led_app.c
-rw-rw-r-- 1 osboxes osboxes 750 Nov 30 09:50 Kconfig
-rw-rw-r-- 1 osboxes osboxes 1062 Nov 30 09:50 Make.defs
-rw-rw-r-- 1 osboxes osboxes 1301 Nov 30 09:50 Makefile
osboxes@osboxes:~/nuttx/apps/examples/etx_led$
Se você quiser ver as mudanças em relação ao aplicativo, você pode olhar este commit . Você também pode obter o código completo do GitHub .
Construindo o driver e o aplicativo
Tudo indo bem. Vamos construir nosso aplicativo e o driver juntos. Eu criei o script de shell build.sh para combinar todas as etapas necessárias em um arquivo.
build.sh
Foi adicionado ao diretório o nuttx/ . Você pode obter o build.sh no
GitHub .
# A simple bash script to build the NuttX RTOS
. $HOME/esp/esp-idf/export.sh
echo "configuring ESP32 with NuttX RTOS"
./tools/configure.sh esp32-devkitc:nsh
make download ESPTOOL_PORT=/dev/ttyUSB0
O script acima tem um argumento. Se você passar 1, ele faz distclean e inicializa as configurações da placa . Se você passar diferente de 1, ele fará apenas o make menuconfig e make.
build.sh
osboxes@osboxes:~/nuttx/nuttx$ sudo chmod +x build.sh
osboxes@osboxes:~/nuttx/nuttx$ ./build.sh
Detecting the Python interpreter
Checking "python" ...
Python 3.8.10
"python" has been detected
Adding ESP-IDF tools to PATH...
Using Python interpreter in /home/osboxes/.espressif/python_env/idf4.4_py3.8_env/bin/python
Checking if Python packages are up to date...
Python requirements from /home/osboxes/esp/esp-idf/requirements.txt are satisfied.
Added the following directories to PATH:
.
.
.
Vamos fazer distclean e build. Execute o comando abaixo no diretório nuttx/nuttx.
Ao executar o comando acima, você deverá obter a janela menuconfig. Nesse menu, temos que habilitar o driver etx_led e o aplicativo etx_led_app .
Basta navegar para Seleção de placa -> Drivers EmbeTronicX -> e verificar o driver LED EmbeTroincX como na imagem abaixo.
Depois de habilitado isso, pressione Exit e vá para Home . Agora é hora de habilitar o aplicativo. Para fazer isso, navegue até Home ->Application Configuration -> Examples -> e verifique o exemplo do aplicativo EmbeTronicX LED como a imagem abaixo .
Isso é tudo. Salve e saia do menu e deixe-o fazer o Build.
AS: common/xtensa_vectors.S
AS: common/xtensa_window_vector.S
AS: common/xtensa_windowspill.S
AS: common/xtensa_int_handlers.S
AS: common/xtensa_user_handler.S
CC: chip/esp32_start.c
CC: chip/esp32_wdt.c
make[2]: Entering directory '/home/osboxes/nuttx/nuttx/boards/xtensa/esp32/common'
CC: board/esp32_boot.c
CC: board/esp32_bringup.c
CC: board/esp32_appinit.c
CC: src/esp32_etx_led.c
AR (create): libboard.a esp32_boot.o esp32_bringup.o esp32_appinit.o esp32_etx_led.o
make[2]: Leaving directory '/home/osboxes/nuttx/nuttx/boards/xtensa/esp32/common'
LD: nuttx
make[1]: Leaving directory '/home/osboxes/nuttx/nuttx/arch/xtensa/src'
CP: nuttx.hex
CP: nuttx.bin
MKIMAGE: ESP32 binary
esptool.py -c esp32 elf2image -fs 4MB -fm dio -ff 40m -o nuttx.bin nuttx
esptool.py v3.2-dev
Merged 1 ELF section
Generated: nuttx.bin (ESP32 compatible)
Assim que estiver tentando se conectar, segure o botão BOOT . Em seguida, ele começará a piscar.
Depois o build e gravação, você conecta o dispositivo usando o picocom usando o comando
picocom -b 115200 /dev/ttyUSB0
Agora você obterá o NuttShell (nsh) . Digite o comando help . Você obterá a saída como a imagem abaixo.
Nosso aplicativo etx_led foi adicionado em Builtin Apps . Vamos executar o aplicativo.
Exemplo de LED piscando ESP32 - Saída
app etx_led tem um argumento que é o número GPIO. Você pode fornecer qualquer número GPIO válido. Neste exemplo, estou fornecendo o número GPIO do LED integrado 2. Execute o comando abaixo.
etx_led 2
Se você não quiser usar o aplicativo, pode usar o comando printf abaixo . Mas certifique-se de ter habilitado o comando printf no menuconfig.
Para ligar o LED GPIO 2, tente inserir o comando abaixo em nsh .
printf \x0201 > /dev/etx_led
Aqui, 02 é o número GPIO e 01 é o valor a ser definido.
Para desligar o LED GPIO 2, tente inserir o comando abaixo em nsh.
printf \x0200 > /dev/etx_led
Aqui, 02 é o número GPIO e 00 é o valor a ser definido.
RODANDO EM BACKGROUND
nsh> etx_led 15 &
DÚVIDAS
suporte@smartcore.com.br
AGRADECIMENTOS
Alan Carvalho de Assis
Mestre em Engenharia Elétrica pela UFRGS; Formado em Computação
Sistemas de Informação pela UnilesteMG
REFERÊNCIAS
Sobre a SMARTCOREA SmartCore fornece módulos para comunicação wireless, biometria, conectividade, rastreamento e automação.
Nosso portfólio inclui modem 2G/3G/4G/NB-IoT/Cat.M, satelital, módulos WiFi, Bluetooth, GNSS / GPS, Sigfox, LoRa, leitor de cartão, leitor QR code, mecanismo de impressão, mini-board PC, antena, pigtail, LCD, bateria, repetidor GPS e sensores.