Просмотр исходного кода

led blink example

* led blink example

* restore tests

* Update FURI_and_examples.md
coreglitch 5 лет назад
Родитель
Сommit
bee159f435

+ 0 - 81
applications/app_example/app_example.c

@@ -1,81 +0,0 @@
-#include <stdio.h>
-#include "flipper.h"
-#include "debug.h"
-
-void furi_widget(void* param);
-void furi_test_app(void* param);
-void furi_next_test_app(void* param);
-
-/*
-widget simply print ping message
-*/
-void furi_widget(void* param) {
-    FILE* debug_uart = get_debug();
-
-    fprintf(debug_uart, "start furi widget: %s\n", (char*)param);
-
-    while(1) {
-        fprintf(debug_uart, "furi widget\n");
-        delay(10);
-    }
-}
-
-/*
-it simply start, then start child widget, wait about 1 sec (with ping evey 200 ms),
-kill the widget, continue with 500 ms ping.
-*/
-void furi_test_app(void* param) {
-
-    uint8_t cnt = 0;
-
-    while(1) {
-        fprintf(debug_uart, "furi test app %d\n", cnt);
-        delay(10);
-
-        if(cnt == 2) {
-            fprintf(debug_uart, "go to next app\n");
-            furiac_switch(furi_next_test_app, "next_test", NULL);
-            fprintf(debug_uart, "unsuccessful switch\n");
-            while(1) {
-                delay(1000);
-            }
-        }
-
-        cnt++;
-    }
-}
-
-void furi_next_test_app(void* param) {
-    FILE* debug_uart = get_debug();
-
-    fprintf(debug_uart, "start next test app\n");
-
-    delay(10);
-
-    fprintf(debug_uart, "exit next app\n");
-    furiac_exit(NULL);
-
-    while(1) {
-        // this code must not be called
-        fprintf(debug_uart, "next app: something went wrong\n");
-        delay(10);
-    }
-}
-
-/*
-FILE* debug_uart = get_debug();
-
-fprintf(debug_uart, "hello Flipper!\n");
-
-GpioPin red_led = {LED_RED_GPIO_Port, LED_RED_Pin};
-
-app_gpio_init(red_led, GpioModeOutput);
-
-
-while(1) {
-    delay(100);
-    app_gpio_write(red_led, true);
-    delay(100);
-    app_gpio_write(red_led, false);
-}
-*/

+ 0 - 2
applications/app_example/app_example.h

@@ -1,2 +0,0 @@
-
-void furi_test_app(void*);

+ 16 - 0
applications/examples/blink.c

@@ -0,0 +1,16 @@
+#include "flipper.h"
+
+void application_blink(void* p) {
+    // create pin
+    GpioPin led = {.pin = GPIO_PIN_8, .port = GPIOA};
+    
+    // configure pin
+    pinMode(led, GpioModeOutput);
+
+    while(1) {
+        digitalWrite(led, HIGH);
+        delay(500);
+        digitalWrite(led, LOW);
+        delay(500);
+    }
+}

+ 13 - 2
applications/startup.h

@@ -1,13 +1,24 @@
 #pragma once
 
 #include "furi.h"
-#include "tests/test_index.h"
 
 typedef struct {
     FlipperApplication app;
     const char* name;
 } FlipperStartupApp;
 
+#ifdef TEST
+void flipper_test_app(void* p);
+#endif
+
+void application_blink(void* p);
+
 const FlipperStartupApp FLIPPER_STARTUP[] = {
-    {.app = flipper_test_app, .name = "test app"}
+    #ifdef TEST
+    {.app = flipper_test_app, .name = "test app"},
+    #endif
+
+    #ifdef EXAMPLE_BLINK
+    {.app = application_blink, .name = "blink"},
+    #endif
 };

+ 2 - 0
applications/tests/furiac_test.c

@@ -121,6 +121,8 @@ bool furi_ac_switch_exit(FILE* debug_uart) {
     
     delay(10); // wait while task do its work
 
+    seq.sequence[seq.count] = '\0';
+
     if(strcmp(seq.sequence, "ABA/") != 0) {
         fprintf(debug_uart, "wrong sequence: %s\n", seq.sequence);
         return false;

+ 0 - 2
applications/tests/test_index.h

@@ -1,2 +0,0 @@
-
-void flipper_test_app(void* p);

+ 27 - 4
target_lo/Inc/flipper_hal.h

@@ -17,7 +17,7 @@ typedef enum {
 } GpioMode;
 
 typedef struct {
-    uint32_t port;
+    const char* port;
     uint32_t pin;
     GpioMode mode;
 } GpioPin;
@@ -27,9 +27,9 @@ void app_gpio_init(GpioPin gpio, GpioMode mode);
 inline void app_gpio_write(GpioPin gpio, bool state) {
     if(gpio.pin != 0) {
         if(state) {
-            printf("[GPIO] %d:%d on\n", gpio.port, gpio.pin);
+            printf("[GPIO] %s%d on\n", gpio.port, gpio.pin);
         } else {
-            printf("[GPIO] %d:%d off\n", gpio.port, gpio.pin);
+            printf("[GPIO] %s%d off\n", gpio.port, gpio.pin);
         }
     } else {
         printf("[GPIO] no pin\n");
@@ -58,4 +58,27 @@ inline void app_tim_pulse(uint32_t width) {
 
 inline void app_tim_stop() {
     printf("[TIM] stop\n");
-}
+}
+
+#define GPIOA "PA"
+#define GPIOB "PB"
+#define GPIOC "PC"
+#define GPIOD "PD"
+#define GPIOE "PE"
+
+#define GPIO_PIN_0 0
+#define GPIO_PIN_1 1
+#define GPIO_PIN_2 2
+#define GPIO_PIN_3 3
+#define GPIO_PIN_4 4
+#define GPIO_PIN_5 5
+#define GPIO_PIN_6 6
+#define GPIO_PIN_7 7
+#define GPIO_PIN_8 8
+#define GPIO_PIN_9 9
+#define GPIO_PIN_10 10
+#define GPIO_PIN_11 11
+#define GPIO_PIN_12 12
+#define GPIO_PIN_13 13
+#define GPIO_PIN_14 14
+#define GPIO_PIN_15 15

+ 29 - 6
target_lo/Makefile

@@ -25,6 +25,8 @@ Src/main.c
 
 CPP_SOURCES = ../core/app.cpp
 
+# Core
+
 C_SOURCES += ../core/debug.c
 C_SOURCES += ../core/furi.c
 C_SOURCES += ../core/furi_ac.c
@@ -32,9 +34,28 @@ C_SOURCES += Src/flipper_hal.c
 C_SOURCES += Src/lo_os.c
 C_SOURCES += Src/lo_hal.c
 
+# C defines
+C_DEFS =  \
+-DUSE_HAL_DRIVER \
+-DSTM32L476xx \
+-DBUTON_INVERT=false \
+-DDEBUG_UART=huart1
+
+# System applications
+
+ifeq ($(TEST), 1)
 C_SOURCES += ../applications/tests/furiac_test.c
 C_SOURCES += ../applications/tests/furi_record_test.c
 C_SOURCES += ../applications/tests/test_index.c
+C_DEFS += -DTEST
+endif
+
+# User application
+
+ifeq ($(EXAMPLE_BLINK), 1)
+C_SOURCES += ../applications/examples/blink.c
+C_DEFS += -DEXAMPLE_BLINK
+endif
 
 #######################################
 # binaries
@@ -52,12 +73,6 @@ BIN = $(CP) -O binary -S
 # CFLAGS
 #######################################
 
-# C defines
-C_DEFS =  \
--DUSE_HAL_DRIVER \
--DSTM32L476xx \
--DBUTON_INVERT=false \
--DDEBUG_UART=huart1
 
 # C includes
 C_INCLUDES =  \
@@ -90,6 +105,14 @@ LDFLAGS = $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-
 # default action: build all
 all: $(BUILD_DIR)/$(TARGET)
 
+example_blink:
+	EXAMPLE_BLINK=1 make
+	$(BUILD_DIR)/$(TARGET)
+
+test:
+	TEST=1 make
+	$(BUILD_DIR)/$(TARGET)
+
 
 #######################################
 # build the application

+ 3 - 3
target_lo/Src/flipper_hal.c

@@ -13,15 +13,15 @@ void app_gpio_init(GpioPin gpio, GpioMode mode) {
 
         switch(mode) {
             case GpioModeInput:
-                printf("[GPIO] %d:%d input\n", gpio.port, gpio.pin);
+                printf("[GPIO] %s%d input\n", gpio.port, gpio.pin);
             break;
 
             case GpioModeOutput: 
-                printf("[GPIO] %d:%d push pull\n", gpio.port, gpio.pin);
+                printf("[GPIO] %s%d push pull\n", gpio.port, gpio.pin);
             break;
 
             case GpioModeOpenDrain:
-                printf("[GPIO] %d:%d open drain\n", gpio.port, gpio.pin);
+                printf("[GPIO] %s%d open drain\n", gpio.port, gpio.pin);
             break;
         }
 

+ 1 - 1
target_lo/Src/lo_os.c

@@ -6,7 +6,7 @@
 #include <signal.h>
 
 void osDelay(uint32_t ms) {
-    printf("[DELAY] %d ms\n", ms);
+    // printf("[DELAY] %d ms\n", ms);
     usleep(ms * 1000);
 }
 

+ 111 - 0
wiki/devlog/FURI_and_examples.md

@@ -0,0 +1,111 @@
+One of the most important component of Flipper Core is [FURI](FURI) (Flipper Universal Registry Implementation). It helps control the applications flow, make dynamic linking and interaction between applications.
+
+In fact, FURI is just wrapper around RTOS thread management and mutexes, and callback management.
+
+In this article we create few application, interact between apps, use OS functions and interact with HAL.
+
+# Simple Blink app
+
+First, let's create a simple led blinking application.
+
+## General agreements
+
+Flipper application is just a function:
+
+```C
+void application_name(void* p) {
+    // Setup
+
+    while(1) {
+        // Loop
+    }
+}
+```
+
+1. `void* p` is arbitrary pointer that may be used for pass parameters to application at launch (like argc/argv in POSIX).
+2. Application must never attempt to return or exit from their implementing function.
+3. Avoid long cycles without any "waits" or "blocking" like `delay` or `xQueueReceive`, otherwise your app will blocking overall Flipper work.
+4. Do not create static variables inside function or global variables. Use only local variables. We plan to add virual in-RAM filesystem to save any persistent data.  
+
+## Preparing for launch
+
+We will use integrated LED. Look at the schematic:
+
+![](https://github.com/Flipper-Zero/flipperzero-firmware-community/raw/master/wiki_static/application_examples/leds.png)
+![](https://github.com/Flipper-Zero/flipperzero-firmware-community/raw/master/wiki_static/application_examples/gpio_pa8.png)
+
+This led connect between power rail and GPIO PA8 and we should configure this pin as open drain to properly control led behaviour.
+
+You can find GPIO API in `target_*/flipper_hal.h`. Or if you prefer to use Arduino API, you can find bindings in `core/flipper.h`.
+
+For work with pin we should:
+
+1. Create `GpioPin` instance and specify pin and port.
+2. Configure mode of pin by `pinMode` function.
+3. Control state of pin by `digitalWrite` function.
+
+## Creating application
+
+1. Create new file (for example, `blink.c`) in `applications` folder.
+2. Create code like this:
+
+```C
+#include "flipper.h"
+
+void application_blink(void* p) {
+    // create pin
+    GpioPin led = {.pin = GPIO_PIN_8, .port = GPIOA};
+
+    // configure pin
+    pinMode(led, GpioModeOutput);
+
+    while(1) {
+        digitalWrite(led, HIGH);
+        delay(500);
+        digitalWrite(led, LOW);
+        delay(500);
+    }
+}
+```
+3. To start your application on Flipper startup, add it to autorun:
+    * in `applications/startup.h` add prototype of main application function:
+
+    ```C
+    void application_blink(void* p);
+    ```
+
+    * add entry to `FLIPPER_STARTUP` array (pointer to application function and application name):
+
+    ```C
+    const FlipperStartupApp FLIPPER_STARTUP[] = {
+        #ifdef TEST
+        {.app = flipper_test_app, .name = "test app"}
+        #endif
+
+        // user applications:
+
+        , {.app = application_blink, .name = "blink"}  
+    };
+    ```
+
+4. Add your application file to Makefile (for each target, `target_lo/Makefile` and `target_f1/Makefile`, we add one common makefile later):
+
+```
+# User application
+
+C_SOURCES += ../applications/blink.c
+```
+
+Build and run for linux (target_lo):
+
+`docker-compose exec dev make -C target_lo`
+
+Run:
+
+`docker-compose exec dev target_lo/build/target_lo`.
+
+Зырим как светодиод пытается мигать.
+
+![](https://github.com/Flipper-Zero/flipperzero-firmware-community/raw/master/wiki_static/application_examples/example_blink.gif)
+
+_You also run found source of this example in `applications/examples/blink.c` and run by `docker-compose exec dev make -C target_lo example_blink`_

+ 3 - 0
wiki_static/application_examples/example_blink.gif

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e386746c69e0685a45f8cd320239e825b23e17f07ab272a764cb08b54796a1e2
+size 411159

+ 3 - 0
wiki_static/application_examples/gpio_pa8.png

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:21d591754f159cc9c2e1870cf88fbae2bd69573c4a3b3721e9c2857d6265d44c
+size 17359

+ 3 - 0
wiki_static/application_examples/leds.png

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3d54ae19be7820c2db4f2d0177ecfee2e3dd16a387df49543876039dbfe92fa2
+size 14717