[FL-140] Core api dynamic records (#296)
* SYSTEM: tickless mode with deep sleep. * Move FreeRTOS ticks to lptim2 * API: move all sumbodules init routines to one place. Timebase: working lptim2 at tick source. * API Timebase: lp-timer routines, timer access safe zones prediction and synchronization. FreeRTOS: adjust configuration for tickless mode. * NFC: support for tickless mode. * API Timebase: improve tick error handling in IRQ. Apploader: use insomnia mode to run applications. * BLE: prevent sleep while core2 starting * HAL: nap while in insomnia mode * init records work * try to implement record delete * tests and flapp * flapp subsystem * new core functions to get app stat, simplify core code * fix thread termination * add strdup to core * fix tests * Refactoring: remove all unusued parts, update API usage, aggreagate API sources and headers, new record storage * Refactoring: update furi record api usage, cleanup code * Fix broken merge for freertos apps * Core, Target: fix compilation warnings * Drop firmware target local * HAL Timebase, Power, Clock: semaphore guarded access to clock and power modes, better sleep mode. * SD-Filesystem: wait for all deps to arrive before adding widget. Core, BLE: disable debug dump to serial. * delete old app example-ipc * delete old app fatfs list * fix strobe app, add input header * delete old display driver * comment old app qr-code * fix sd-card test, add forced widget update * remove unused new core test * increase heap to 128k * comment and assert old core tests * fix syntax Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
|
||||
void rgb_set(
|
||||
bool r,
|
||||
|
@@ -1,155 +0,0 @@
|
||||
#include "u8g2/u8g2.h"
|
||||
#include "fatfs/ff.h"
|
||||
#include "flipper_v2.h"
|
||||
#include <stdio.h>
|
||||
|
||||
extern uint8_t BSP_SD_Init();
|
||||
|
||||
// TODO currently we have small stack, so it will be static
|
||||
FuriRecordSubscriber* furi_log;
|
||||
#define STR_BUFFER_SIZE 128
|
||||
char str_buffer[STR_BUFFER_SIZE];
|
||||
uint8_t line_current = 0;
|
||||
uint16_t line_position = 0;
|
||||
|
||||
// TODO this should be in the target driver
|
||||
FATFS SD_FatFs;
|
||||
char SD_Path[4];
|
||||
|
||||
typedef enum {
|
||||
EventTypeStart,
|
||||
EventTypeKey,
|
||||
} AppEventType;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
InputEvent input;
|
||||
} value;
|
||||
AppEventType type;
|
||||
} AppEvent;
|
||||
|
||||
static void event_cb(const void* value, void* ctx) {
|
||||
QueueHandle_t event_queue = (QueueHandle_t)ctx;
|
||||
|
||||
AppEvent event;
|
||||
event.type = EventTypeKey;
|
||||
event.value.input = *(InputEvent*)value;
|
||||
xQueueSend(event_queue, (void*)&event, 0);
|
||||
}
|
||||
|
||||
void fatfs_list(void* p) {
|
||||
const uint8_t line_size = 10;
|
||||
const uint8_t lines_on_display = 6;
|
||||
|
||||
uint8_t bsp_result;
|
||||
FRESULT result;
|
||||
DIR dir;
|
||||
FILINFO fno;
|
||||
AppEvent event;
|
||||
|
||||
QueueHandle_t event_queue = xQueueCreate(2, sizeof(AppEvent));
|
||||
|
||||
furi_log = get_default_log();
|
||||
fuprintf(furi_log, "[fatfs_list] app start\n");
|
||||
fuprintf(furi_log, "[fatfs_list] wait for sd insert\n");
|
||||
|
||||
while(!hal_gpio_read_sd_detect()) {
|
||||
delay(100);
|
||||
}
|
||||
|
||||
fuprintf(furi_log, "[fatfs_list] sd inserted\n");
|
||||
|
||||
FuriRecordSubscriber* fb_record =
|
||||
furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL);
|
||||
if(fb_record == NULL) {
|
||||
fuprintf(furi_log, "[fatfs_list] cannot create fb record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
PubSub* event_record = furi_open("input_events");
|
||||
if(event_record == NULL) {
|
||||
fuprintf(furi_log, "[fatfs_list] cannot open input_events record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
PubSubItem* subscription = subscribe_pubsub(event_record, event_cb, event_queue);
|
||||
if(subscription == NULL) {
|
||||
fuprintf(furi_log, "[fatfs_list] cannot register input_events callback\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
bsp_result = BSP_SD_Init();
|
||||
|
||||
if(bsp_result != 0) {
|
||||
fuprintf(furi_log, "[fatfs_list] SD card init error\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
result = f_mount(&SD_FatFs, (TCHAR const*)SD_Path, 1);
|
||||
|
||||
if(result != FR_OK) {
|
||||
fuprintf(furi_log, "[fatfs_list] SD card mount error\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
// ok, now we can work with sd card
|
||||
|
||||
// send start event
|
||||
event.type = EventTypeStart;
|
||||
xQueueSend(event_queue, (void*)&event, 0);
|
||||
|
||||
while(1) {
|
||||
if(xQueueReceive(event_queue, (void*)&event, portMAX_DELAY)) {
|
||||
// process buttons event
|
||||
if(event.type == EventTypeKey) {
|
||||
// button pressed
|
||||
if(event.value.input.state == true) {
|
||||
if(event.value.input.input == InputUp && line_position > 0) {
|
||||
line_position--;
|
||||
}
|
||||
if(event.value.input.input == InputDown) {
|
||||
line_position++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
line_current = 1;
|
||||
|
||||
// open root dir
|
||||
result = f_opendir(&dir, "");
|
||||
|
||||
while(1) {
|
||||
// read a directory item
|
||||
result = f_readdir(&dir, &fno);
|
||||
|
||||
if(result != FR_OK) {
|
||||
// cannot read dir
|
||||
break;
|
||||
}
|
||||
|
||||
if(fno.fname[0] == 0) {
|
||||
// Break on end of dir
|
||||
break;
|
||||
}
|
||||
|
||||
// draw files on display
|
||||
if(line_current > line_position &&
|
||||
line_current <= (line_position + lines_on_display)) {
|
||||
if(fno.fattrib & AM_DIR) {
|
||||
snprintf(str_buffer, STR_BUFFER_SIZE, "DIR %s\n", fno.fname);
|
||||
} else {
|
||||
snprintf(str_buffer, STR_BUFFER_SIZE, "FIL %s\n", fno.fname);
|
||||
}
|
||||
fuprintf(furi_log, str_buffer);
|
||||
}
|
||||
|
||||
line_current++;
|
||||
}
|
||||
|
||||
result = f_closedir(&dir);
|
||||
|
||||
furi_commit(fb_record);
|
||||
}
|
||||
}
|
||||
|
||||
furiac_exit(NULL);
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
#include <stdio.h>
|
||||
#include <input/input.h>
|
||||
|
||||
typedef union {
|
||||
unsigned int packed;
|
||||
@@ -21,12 +22,10 @@ static void event_cb(const void* value, void* ctx) {
|
||||
|
||||
void application_input_dump(void* p) {
|
||||
// open record
|
||||
ValueManager* state_record = furi_open("input_state");
|
||||
furi_check(state_record);
|
||||
ValueManager* state_record = furi_record_open("input_state");
|
||||
subscribe_pubsub(&state_record->pubsub, state_cb, NULL);
|
||||
|
||||
PubSub* event_record = furi_open("input_events");
|
||||
furi_check(event_record);
|
||||
PubSub* event_record = furi_record_open("input_events");
|
||||
subscribe_pubsub(event_record, event_cb, NULL);
|
||||
|
||||
printf("Example app [input dump]\n");
|
||||
|
@@ -1,155 +0,0 @@
|
||||
#include "flipper.h"
|
||||
#include <string.h>
|
||||
|
||||
#define FB_WIDTH 10
|
||||
#define FB_HEIGHT 3
|
||||
#define FB_SIZE (FB_WIDTH * FB_HEIGHT)
|
||||
|
||||
// context structure used for pass some object from app thread to callback
|
||||
typedef struct {
|
||||
SemaphoreHandle_t events; // queue to pass events from callback to app thread
|
||||
FuriRecordSubscriber* log; // app logger
|
||||
} IpcCtx;
|
||||
|
||||
static void handle_fb_change(const void* fb, size_t fb_size, void* raw_ctx) {
|
||||
IpcCtx* ctx = (IpcCtx*)raw_ctx; // make right type
|
||||
|
||||
fuprintf(ctx->log, "[cb] framebuffer updated\n");
|
||||
|
||||
// send event to app thread
|
||||
xSemaphoreGive(ctx->events);
|
||||
|
||||
// Attention! Please, do not make blocking operation like IO and waits inside callback
|
||||
// Remember that callback execute in calling thread/context
|
||||
}
|
||||
|
||||
static void print_fb(char* fb, FuriRecordSubscriber* log) {
|
||||
if(fb == NULL) return;
|
||||
|
||||
/* draw framebuffer like this:
|
||||
+==========+
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
+==========+
|
||||
*/
|
||||
|
||||
char row_buffer[FB_WIDTH + 1];
|
||||
row_buffer[FB_WIDTH] = '\0';
|
||||
|
||||
// FB layout is hardcoded here
|
||||
fuprintf(log, "+==========+\n");
|
||||
for(uint8_t i = 0; i < FB_HEIGHT; i++) {
|
||||
strncpy(row_buffer, &fb[FB_WIDTH * i], FB_WIDTH);
|
||||
fuprintf(log, "|%s|\n", row_buffer);
|
||||
}
|
||||
fuprintf(log, "+==========+\n");
|
||||
}
|
||||
|
||||
void application_ipc_display(void* p) {
|
||||
// get logger
|
||||
FuriRecordSubscriber* log = get_default_log();
|
||||
|
||||
// create ASCII "framebuffer"
|
||||
// FB_WIDTH x FB_HEIGHT char buffer
|
||||
char _framebuffer[FB_SIZE];
|
||||
|
||||
// init framebuffer by spaces
|
||||
for(size_t i = 0; i < FB_SIZE; i++) {
|
||||
_framebuffer[i] = ' ';
|
||||
}
|
||||
|
||||
// create record
|
||||
if(!furi_create_deprecated("test_fb", (void*)_framebuffer, FB_SIZE)) {
|
||||
fuprintf(log, "[display] cannot create fb record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
StaticSemaphore_t event_descriptor;
|
||||
// create stack-based counting semaphore
|
||||
SemaphoreHandle_t events = xSemaphoreCreateCountingStatic(255, 0, &event_descriptor);
|
||||
|
||||
if(events == NULL) {
|
||||
fuprintf(log, "[display] cannot create event semaphore\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
// save log and event queue in context structure
|
||||
IpcCtx ctx = {.events = events, .log = log};
|
||||
|
||||
// subscribe to record. ctx will be passed to handle_fb_change
|
||||
FuriRecordSubscriber* fb_record =
|
||||
furi_open_deprecated("test_fb", false, false, handle_fb_change, NULL, &ctx);
|
||||
|
||||
if(fb_record == NULL) {
|
||||
fuprintf(log, "[display] cannot open fb record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
#ifdef HW_DISPLAY
|
||||
// on Flipper target -- open screen
|
||||
|
||||
// draw border
|
||||
|
||||
#else
|
||||
// on Local target -- print "blank screen"
|
||||
{
|
||||
void* fb = furi_take(fb_record);
|
||||
print_fb((char*)fb, log);
|
||||
furi_give(fb_record);
|
||||
}
|
||||
#endif
|
||||
|
||||
while(1) {
|
||||
// wait for event
|
||||
if(xSemaphoreTake(events, portMAX_DELAY) == pdTRUE) {
|
||||
fuprintf(log, "[display] get fb update\n\n");
|
||||
|
||||
#ifdef HW_DISPLAY
|
||||
// on Flipper target draw the screen
|
||||
#else
|
||||
// on local target just print
|
||||
{
|
||||
void* fb = furi_take(fb_record);
|
||||
print_fb((char*)fb, log);
|
||||
furi_give(fb_record);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Widget application
|
||||
void application_ipc_widget(void* p) {
|
||||
FuriRecordSubscriber* log = get_default_log();
|
||||
|
||||
// open record
|
||||
FuriRecordSubscriber* fb_record =
|
||||
furi_open_deprecated("test_fb", false, false, NULL, NULL, NULL);
|
||||
|
||||
if(fb_record == NULL) {
|
||||
fuprintf(log, "[widget] cannot create fb record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
uint8_t counter = 0;
|
||||
|
||||
while(1) {
|
||||
delay(120);
|
||||
|
||||
// write some ascii demo here: '#'' symbol run on overall screen
|
||||
char* fb = (char*)furi_take(fb_record);
|
||||
|
||||
if(fb == NULL) furiac_exit(NULL);
|
||||
|
||||
for(size_t i = 0; i < FB_SIZE; i++) {
|
||||
fb[i] = ' ';
|
||||
}
|
||||
|
||||
fb[counter % FB_SIZE] = '#';
|
||||
|
||||
furi_commit(fb_record);
|
||||
|
||||
counter++;
|
||||
}
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
#include <input.h>
|
||||
|
||||
static void event_cb(const void* value, void* ctx) {
|
||||
const InputEvent* event = value;
|
||||
@@ -38,8 +39,7 @@ void application_strobe(void* p) {
|
||||
ValueMutex delay_mutex;
|
||||
init_mutex(&delay_mutex, &delay_time_holder, sizeof(delay_time_holder));
|
||||
|
||||
PubSub* event_record = furi_open("input_events");
|
||||
furi_check(event_record);
|
||||
PubSub* event_record = furi_record_open("input_events");
|
||||
subscribe_pubsub(event_record, event_cb, &delay_mutex);
|
||||
|
||||
while(1) {
|
||||
|
@@ -1,32 +1,14 @@
|
||||
#include "u8g2/u8g2.h"
|
||||
#include "flipper.h"
|
||||
#include <furi.h>
|
||||
|
||||
void u8g2_example(void* p) {
|
||||
FuriRecordSubscriber* log = get_default_log();
|
||||
|
||||
// open record
|
||||
FuriRecordSubscriber* fb_record =
|
||||
furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL);
|
||||
u8g2_t* fb = furi_record_open("u8g2_fb");
|
||||
u8g2_SetFont(fb, u8g2_font_6x10_mf);
|
||||
u8g2_SetDrawColor(fb, 1);
|
||||
u8g2_SetFontMode(fb, 1);
|
||||
u8g2_DrawStr(fb, 2, 12, "hello world!");
|
||||
furi_record_close("u8g2_fb");
|
||||
|
||||
if(fb_record == NULL) {
|
||||
fuprintf(log, "[widget] cannot create fb record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
while(1) {
|
||||
u8g2_t* fb = furi_take(fb_record);
|
||||
if(fb != NULL) {
|
||||
u8g2_SetFont(fb, u8g2_font_6x10_mf);
|
||||
u8g2_SetDrawColor(fb, 1);
|
||||
u8g2_SetFontMode(fb, 1);
|
||||
u8g2_DrawStr(fb, 2, 12, "hello world!");
|
||||
}
|
||||
furi_commit(fb_record);
|
||||
|
||||
if(fb != NULL) {
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
delay(1);
|
||||
}
|
||||
furiac_exit(NULL);
|
||||
}
|
@@ -1,6 +1,9 @@
|
||||
#include "u8g2/u8g2.h"
|
||||
#include "qrcode/qrcode.h"
|
||||
#include "flipper.h"
|
||||
#include <furi.h>
|
||||
|
||||
/*
|
||||
TODO: rework with new app api
|
||||
|
||||
void u8g2_DrawPixelSize(u8g2_t* u8g2, uint8_t x, uint8_t y, uint8_t size) {
|
||||
for(uint8_t px = 0; px < size; px++) {
|
||||
@@ -11,8 +14,6 @@ void u8g2_DrawPixelSize(u8g2_t* u8g2, uint8_t x, uint8_t y, uint8_t size) {
|
||||
}
|
||||
|
||||
void u8g2_qrcode(void* p) {
|
||||
FuriRecordSubscriber* log = get_default_log();
|
||||
|
||||
// open record
|
||||
FuriRecordSubscriber* fb_record =
|
||||
furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL);
|
||||
@@ -36,7 +37,7 @@ void u8g2_qrcode(void* p) {
|
||||
qrcode_initText(&qrcode, qrcodeBytes, qr_version, qr_error_correction, "HELLO FLIPPER");
|
||||
|
||||
if(fb_record == NULL) {
|
||||
fuprintf(log, "[widget] cannot create fb record\n");
|
||||
printf("[widget] cannot create fb record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
@@ -69,4 +70,5 @@ void u8g2_qrcode(void* p) {
|
||||
|
||||
delay(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
@@ -1,7 +1,5 @@
|
||||
#include "flipper.h"
|
||||
#include <furi.h>
|
||||
#include <string.h>
|
||||
#include "log.h"
|
||||
#include "flipper_v2.h"
|
||||
|
||||
void application_uart_write(void* p) {
|
||||
// Red led for showing progress
|
||||
@@ -11,12 +9,9 @@ void application_uart_write(void* p) {
|
||||
|
||||
gpio_init(led_record, GpioModeOutputOpenDrain);
|
||||
|
||||
// get_default_log open "tty" record
|
||||
FuriRecordSubscriber* log = get_default_log();
|
||||
|
||||
// create buffer
|
||||
const char test_string[] = "test\n";
|
||||
furi_write(log, test_string, strlen(test_string));
|
||||
printf(test_string);
|
||||
|
||||
// for example, create counter and show its value
|
||||
uint8_t counter = 0;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
#include <input/input.h>
|
||||
|
||||
typedef struct {
|
||||
GpioPin* led;
|
||||
@@ -24,7 +25,7 @@ void application_vibro(void* p) {
|
||||
gpio_write(ctx.vibro, false);
|
||||
|
||||
// subscribe on buttons
|
||||
PubSub* event_record = furi_open("input_events");
|
||||
PubSub* event_record = furi_record_open("input_events");
|
||||
furi_check(event_record);
|
||||
subscribe_pubsub(event_record, button_handler, &ctx);
|
||||
|
||||
|
Reference in New Issue
Block a user