led blink example
* led blink example * restore tests * Update FURI_and_examples.md
This commit is contained in:
		
							parent
							
								
									2e023ffcda
								
							
						
					
					
						commit
						bee159f435
					
				| @ -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); |  | ||||||
| } |  | ||||||
| */ |  | ||||||
| @ -1,2 +0,0 @@ | |||||||
| 
 |  | ||||||
| void furi_test_app(void*); |  | ||||||
							
								
								
									
										16
									
								
								applications/examples/blink.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								applications/examples/blink.c
									
									
									
									
									
										Normal file
									
								
							| @ -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); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -1,13 +1,24 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "furi.h" | #include "furi.h" | ||||||
| #include "tests/test_index.h" |  | ||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     FlipperApplication app; |     FlipperApplication app; | ||||||
|     const char* name; |     const char* name; | ||||||
| } FlipperStartupApp; | } FlipperStartupApp; | ||||||
| 
 | 
 | ||||||
|  | #ifdef TEST | ||||||
|  | void flipper_test_app(void* p); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | void application_blink(void* p); | ||||||
|  | 
 | ||||||
| const FlipperStartupApp FLIPPER_STARTUP[] = { | 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 | ||||||
| }; | }; | ||||||
| @ -121,6 +121,8 @@ bool furi_ac_switch_exit(FILE* debug_uart) { | |||||||
|      |      | ||||||
|     delay(10); // wait while task do its work
 |     delay(10); // wait while task do its work
 | ||||||
| 
 | 
 | ||||||
|  |     seq.sequence[seq.count] = '\0'; | ||||||
|  | 
 | ||||||
|     if(strcmp(seq.sequence, "ABA/") != 0) { |     if(strcmp(seq.sequence, "ABA/") != 0) { | ||||||
|         fprintf(debug_uart, "wrong sequence: %s\n", seq.sequence); |         fprintf(debug_uart, "wrong sequence: %s\n", seq.sequence); | ||||||
|         return false; |         return false; | ||||||
|  | |||||||
| @ -1,2 +0,0 @@ | |||||||
| 
 |  | ||||||
| void flipper_test_app(void* p); |  | ||||||
| @ -17,7 +17,7 @@ typedef enum { | |||||||
| } GpioMode; | } GpioMode; | ||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     uint32_t port; |     const char* port; | ||||||
|     uint32_t pin; |     uint32_t pin; | ||||||
|     GpioMode mode; |     GpioMode mode; | ||||||
| } GpioPin; | } GpioPin; | ||||||
| @ -27,9 +27,9 @@ void app_gpio_init(GpioPin gpio, GpioMode mode); | |||||||
| inline void app_gpio_write(GpioPin gpio, bool state) { | inline void app_gpio_write(GpioPin gpio, bool state) { | ||||||
|     if(gpio.pin != 0) { |     if(gpio.pin != 0) { | ||||||
|         if(state) { |         if(state) { | ||||||
|             printf("[GPIO] %d:%d on\n", gpio.port, gpio.pin); |             printf("[GPIO] %s%d on\n", gpio.port, gpio.pin); | ||||||
|         } else { |         } else { | ||||||
|             printf("[GPIO] %d:%d off\n", gpio.port, gpio.pin); |             printf("[GPIO] %s%d off\n", gpio.port, gpio.pin); | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         printf("[GPIO] no pin\n"); |         printf("[GPIO] no pin\n"); | ||||||
| @ -58,4 +58,27 @@ inline void app_tim_pulse(uint32_t width) { | |||||||
| 
 | 
 | ||||||
| inline void app_tim_stop() { | inline void app_tim_stop() { | ||||||
|     printf("[TIM] stop\n"); |     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 | ||||||
|  | |||||||
| @ -25,6 +25,8 @@ Src/main.c | |||||||
| 
 | 
 | ||||||
| CPP_SOURCES = ../core/app.cpp | CPP_SOURCES = ../core/app.cpp | ||||||
| 
 | 
 | ||||||
|  | # Core
 | ||||||
|  | 
 | ||||||
| C_SOURCES += ../core/debug.c | C_SOURCES += ../core/debug.c | ||||||
| C_SOURCES += ../core/furi.c | C_SOURCES += ../core/furi.c | ||||||
| C_SOURCES += ../core/furi_ac.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_os.c | ||||||
| C_SOURCES += Src/lo_hal.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/furiac_test.c | ||||||
| C_SOURCES += ../applications/tests/furi_record_test.c | C_SOURCES += ../applications/tests/furi_record_test.c | ||||||
| C_SOURCES += ../applications/tests/test_index.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
 | # binaries
 | ||||||
| @ -52,12 +73,6 @@ BIN = $(CP) -O binary -S | |||||||
| # CFLAGS
 | # CFLAGS
 | ||||||
| #######################################
 | #######################################
 | ||||||
| 
 | 
 | ||||||
| # C defines
 |  | ||||||
| C_DEFS =  \
 |  | ||||||
| -DUSE_HAL_DRIVER \ |  | ||||||
| -DSTM32L476xx \ |  | ||||||
| -DBUTON_INVERT=false \
 |  | ||||||
| -DDEBUG_UART=huart1 |  | ||||||
| 
 | 
 | ||||||
| # C includes
 | # C includes
 | ||||||
| C_INCLUDES =  \
 | C_INCLUDES =  \
 | ||||||
| @ -90,6 +105,14 @@ LDFLAGS = $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc- | |||||||
| # default action: build all
 | # default action: build all
 | ||||||
| all: $(BUILD_DIR)/$(TARGET) | all: $(BUILD_DIR)/$(TARGET) | ||||||
| 
 | 
 | ||||||
|  | example_blink: | ||||||
|  | 	EXAMPLE_BLINK=1 make | ||||||
|  | 	$(BUILD_DIR)/$(TARGET) | ||||||
|  | 
 | ||||||
|  | test: | ||||||
|  | 	TEST=1 make | ||||||
|  | 	$(BUILD_DIR)/$(TARGET) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| #######################################
 | #######################################
 | ||||||
| # build the application
 | # build the application
 | ||||||
|  | |||||||
| @ -13,15 +13,15 @@ void app_gpio_init(GpioPin gpio, GpioMode mode) { | |||||||
| 
 | 
 | ||||||
|         switch(mode) { |         switch(mode) { | ||||||
|             case GpioModeInput: |             case GpioModeInput: | ||||||
|                 printf("[GPIO] %d:%d input\n", gpio.port, gpio.pin); |                 printf("[GPIO] %s%d input\n", gpio.port, gpio.pin); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|             case GpioModeOutput:  |             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; |             break; | ||||||
| 
 | 
 | ||||||
|             case GpioModeOpenDrain: |             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; |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ | |||||||
| #include <signal.h> | #include <signal.h> | ||||||
| 
 | 
 | ||||||
| void osDelay(uint32_t ms) { | void osDelay(uint32_t ms) { | ||||||
|     printf("[DELAY] %d ms\n", ms); |     // printf("[DELAY] %d ms\n", ms);
 | ||||||
|     usleep(ms * 1000); |     usleep(ms * 1000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										111
									
								
								wiki/devlog/FURI_and_examples.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								wiki/devlog/FURI_and_examples.md
									
									
									
									
									
										Normal file
									
								
							| @ -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: | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 
 | ||||||
|  | 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`. | ||||||
|  | 
 | ||||||
|  | Зырим как светодиод пытается мигать. | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | 
 | ||||||
|  | _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
									
								
								wiki_static/application_examples/example_blink.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								wiki_static/application_examples/example_blink.gif
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:e386746c69e0685a45f8cd320239e825b23e17f07ab272a764cb08b54796a1e2 | ||||||
|  | size 411159 | ||||||
							
								
								
									
										3
									
								
								wiki_static/application_examples/gpio_pa8.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								wiki_static/application_examples/gpio_pa8.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:21d591754f159cc9c2e1870cf88fbae2bd69573c4a3b3721e9c2857d6265d44c | ||||||
|  | size 17359 | ||||||
							
								
								
									
										3
									
								
								wiki_static/application_examples/leds.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								wiki_static/application_examples/leds.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:3d54ae19be7820c2db4f2d0177ecfee2e3dd16a387df49543876039dbfe92fa2 | ||||||
|  | size 14717 | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 coreglitch
						coreglitch