[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:
DrZlo13
2021-01-21 02:09:26 +10:00
committed by GitHub
parent 6c4983c6b6
commit 8f9b2513ff
169 changed files with 1009 additions and 4535 deletions

View File

@@ -1,4 +1,4 @@
#include "flipper_v2.h"
#include <furi.h>
void rgb_set(
bool r,

View File

@@ -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);
}

View File

@@ -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");

View File

@@ -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++;
}
}

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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);
}
}
}
*/

View File

@@ -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;

View File

@@ -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);