[FL-781] FURI, CLI, stdlib: stdout hooks, integration between subsystems, uniform printf usage (#311)
* FURI stdglue: stdout hooks, local and global, ISR safe printf. Uniform newlines for terminal/debug output. Power: prevent sleep while core 2 has not started. * Furi record, stdglue: check mutex allocation * remove unused test * Furi stdglue: buferized output, dynamically allocated state. Furi record: dynamically allocated state. Input dump: proper line ending. Hal VCP: dynamically allocated state. * Interrupt manager: explicitly init list. * Makefile: cleanup rules, fix broken dfu upload. F4: add compiler stack protection options. * BLE: call debug uart callback on transmission complete * FreeRTOS: add configUSE_NEWLIB_REENTRANT * API HAL Timebase: fix issue with idle thread stack corruption caused by systick interrupt. BT: cleanup debug info output. FreeRTOS: disable reentry for newlib. * F4: update stack protection CFLAGS to match used compiller * F4: disable compiller stack protection because of incompatibility with current compiller * Makefile: return openocd logs to gdb * BLE: fixed pin, moar power, ble trace info. * Prevent sleep when connection is active * Makefile: return serial port to upload rule, add workaround for mac os * Furi: prevent usage of stack for cmsis functions. * F4: add missing includes, add debugger breakpoints * Applications: per app stack size. * Furi: honor kernel state in stdglue * FreeRTOS: remove unused hooks * Cleanup and format sources Co-authored-by: DrZlo13 <who.just.the.doctor@gmail.com>
This commit is contained in:
		
							parent
							
								
									fd5f694758
								
							
						
					
					
						commit
						584c0962d8
					
				| @ -60,7 +60,7 @@ static void handle_menu(void* _ctx) { | ||||
|     ctx->state->app_thread_attr.cb_mem = NULL; | ||||
|     ctx->state->app_thread_attr.cb_size = 0; | ||||
|     ctx->state->app_thread_attr.stack_mem = NULL; | ||||
|     ctx->state->app_thread_attr.stack_size = 1024; | ||||
|     ctx->state->app_thread_attr.stack_size = ctx->app->stack_size; | ||||
|     ctx->state->app_thread_attr.priority = osPriorityNormal; | ||||
|     ctx->state->app_thread_attr.tz_module = 0; | ||||
|     ctx->state->app_thread_attr.reserved = 0; | ||||
| @ -72,7 +72,7 @@ static void handle_cli(string_t args, void* _ctx) { | ||||
| 
 | ||||
|     if(ctx->app->app == NULL) return; | ||||
| 
 | ||||
|     cli_print("Starting furi application\r\n"); | ||||
|     printf("Starting furi application\r\n"); | ||||
| 
 | ||||
|     ctx->state->current_app = ctx->app; | ||||
|     ctx->state->app_thread_attr.name = ctx->app->name; | ||||
| @ -80,13 +80,13 @@ static void handle_cli(string_t args, void* _ctx) { | ||||
|     ctx->state->app_thread_attr.cb_mem = NULL; | ||||
|     ctx->state->app_thread_attr.cb_size = 0; | ||||
|     ctx->state->app_thread_attr.stack_mem = NULL; | ||||
|     ctx->state->app_thread_attr.stack_size = 1024; | ||||
|     ctx->state->app_thread_attr.stack_size = ctx->app->stack_size; | ||||
|     ctx->state->app_thread_attr.priority = osPriorityNormal; | ||||
|     ctx->state->app_thread_attr.tz_module = 0; | ||||
|     ctx->state->app_thread_attr.reserved = 0; | ||||
|     ctx->state->app_thread_id = osThreadNew(ctx->app->app, NULL, &ctx->state->app_thread_attr); | ||||
| 
 | ||||
|     cli_print("Press any key to kill application"); | ||||
|     printf("Press any key to kill application"); | ||||
| 
 | ||||
|     char c; | ||||
|     cli_read(&c, 1); | ||||
| @ -184,7 +184,7 @@ void app_loader(void* p) { | ||||
|             menu_item_add(menu, menu_plugins); | ||||
|         }); | ||||
| 
 | ||||
|     printf("[app loader] start\n"); | ||||
|     printf("[app loader] start\r\n"); | ||||
| 
 | ||||
|     osThreadSuspend(self_id); | ||||
| } | ||||
|  | ||||
| @ -38,114 +38,129 @@ void sd_filesystem(void* p); | ||||
| 
 | ||||
| const FuriApplication FLIPPER_SERVICES[] = { | ||||
| #ifdef APP_DISPLAY | ||||
|     {.app = display_u8g2, .name = "display_u8g2", .icon = A_Plugins_14}, | ||||
|     {.app = display_u8g2, .name = "display_u8g2", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_CLI | ||||
|     {.app = cli_task, .name = "cli_task", .icon = A_Plugins_14}, | ||||
|     {.app = cli_task, .name = "cli_task", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_EXAMPLE_BLINK | ||||
|     {.app = application_blink, .name = "blink", .icon = A_Plugins_14}, | ||||
|     {.app = application_blink, .name = "blink", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_INPUT | ||||
|     {.app = input_task, .name = "input_task", .icon = A_Plugins_14}, | ||||
|     {.app = input_task, .name = "input_task", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_EXAMPLE_INPUT_DUMP | ||||
|     {.app = application_input_dump, .name = "input dump", .icon = A_Plugins_14}, | ||||
|     {.app = application_input_dump, .name = "input dump", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_GUI | ||||
|     {.app = backlight_control, .name = "backlight_control", .icon = A_Plugins_14}, | ||||
|     {.app = gui_task, .name = "gui_task", .icon = A_Plugins_14}, | ||||
|     {.app = backlight_control, | ||||
|      .name = "backlight_control", | ||||
|      .stack_size = 1024, | ||||
|      .icon = A_Plugins_14}, | ||||
|     {.app = gui_task, .name = "gui_task", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_MENU | ||||
|     {.app = menu_task, .name = "menu_task", .icon = A_Plugins_14}, | ||||
|     {.app = app_loader, .name = "app_loader", .icon = A_Plugins_14}, | ||||
|     {.app = menu_task, .name = "menu_task", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
|     {.app = app_loader, .name = "app_loader", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_SD_FILESYSTEM | ||||
|     {.app = sd_filesystem, .name = "sd_filesystem", .icon = A_Plugins_14}, | ||||
|     {.app = sd_filesystem, .name = "sd_filesystem", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_DOLPHIN | ||||
|     {.app = dolphin_task, .name = "dolphin_task", .icon = A_Plugins_14}, | ||||
|     {.app = dolphin_task, .name = "dolphin_task", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_POWER | ||||
|     {.app = power_task, .name = "power_task", .icon = A_Plugins_14}, | ||||
|     {.app = power_task, .name = "power_task", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_BT | ||||
|     {.app = bt_task, .name = "bt_task", .icon = A_Plugins_14}, | ||||
|     {.app = bt_task, .name = "bt_task", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_CC1101 | ||||
|     {.app = cc1101_workaround, .name = "cc1101 workaround", .icon = A_Plugins_14}, | ||||
|     {.app = cc1101_workaround, | ||||
|      .name = "cc1101 workaround", | ||||
|      .stack_size = 1024, | ||||
|      .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_LF_RFID | ||||
|     {.app = lf_rfid_workaround, .name = "lf rfid workaround", .icon = A_Plugins_14}, | ||||
|     {.app = lf_rfid_workaround, | ||||
|      .name = "lf rfid workaround", | ||||
|      .stack_size = 1024, | ||||
|      .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_IRDA | ||||
|     {.app = irda, .name = "irda", .icon = A_Plugins_14}, | ||||
|     {.app = irda, .name = "irda", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_NFC | ||||
|     {.app = nfc_task, .name = "nfc_task", .icon = A_Plugins_14}, | ||||
|     {.app = nfc_task, .name = "nfc_task", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_TEST | ||||
|     {.app = flipper_test_app, .name = "test app", .icon = A_Plugins_14}, | ||||
|     {.app = flipper_test_app, .name = "test app", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_EXAMPLE_IPC | ||||
|     {.app = application_ipc_display, .name = "ipc display", .icon = A_Plugins_14}, | ||||
|     {.app = application_ipc_widget, .name = "ipc widget", .icon = A_Plugins_14}, | ||||
|     {.app = application_ipc_display, | ||||
|      .name = "ipc display", | ||||
|      .stack_size = 1024, | ||||
|      .icon = A_Plugins_14}, | ||||
|     {.app = application_ipc_widget, .name = "ipc widget", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_EXAMPLE_QRCODE | ||||
|     {.app = u8g2_qrcode, .name = "u8g2_qrcode", .icon = A_Plugins_14}, | ||||
|     {.app = u8g2_qrcode, .name = "u8g2_qrcode", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_EXAMPLE_FATFS | ||||
|     {.app = fatfs_list, .name = "fatfs_list", .icon = A_Plugins_14}, | ||||
|     {.app = fatfs_list, .name = "fatfs_list", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_EXAMPLE_DISPLAY | ||||
|     {.app = u8g2_example, .name = "u8g2_example", .icon = A_Plugins_14}, | ||||
|     {.app = u8g2_example, .name = "u8g2_example", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_SPEAKER_DEMO | ||||
|     {.app = coreglitch_demo_0, .name = "coreglitch_demo_0", .icon = A_Plugins_14}, | ||||
|     {.app = coreglitch_demo_0, | ||||
|      .name = "coreglitch_demo_0", | ||||
|      .stack_size = 1024, | ||||
|      .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_SD_TEST | ||||
|     {.app = sd_card_test, .name = "sd_card_test", .icon = A_Plugins_14}, | ||||
|     {.app = sd_card_test, .name = "sd_card_test", .stack_size = 4096, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_MUSIC_PLAYER | ||||
|     {.app = music_player, .name = "music player", .icon = A_Plugins_14}, | ||||
|     {.app = music_player, .name = "music player", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_IBUTTON | ||||
|     {.app = app_ibutton, .name = "ibutton", .icon = A_Plugins_14}, | ||||
|     {.app = app_ibutton, .name = "ibutton", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_GPIO_DEMO | ||||
|     {.app = app_gpio_test, .name = "gpio test", .icon = A_Plugins_14}, | ||||
|     {.app = app_gpio_test, .name = "gpio test", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_FLOOPPER_BLOOPPER | ||||
|     {.app = floopper_bloopper, .name = "Floopper Bloopper", .icon = A_Games_14}, | ||||
|     {.app = floopper_bloopper, .name = "Floopper Bloopper", .stack_size = 1024, .icon = A_Games_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_SDNFC | ||||
|     {.app = sdnfc, .name = "sdnfc", .icon = A_Plugins_14}, | ||||
|     {.app = sdnfc, .name = "sdnfc", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| @ -156,23 +171,23 @@ size_t FLIPPER_SERVICES_size() { | ||||
| // Main menu APP
 | ||||
| const FuriApplication FLIPPER_APPS[] = { | ||||
| #ifdef BUILD_CC1101 | ||||
|     {.app = cc1101_workaround, .name = "Sub-1 GHz", .icon = A_Sub1ghz_14}, | ||||
|     {.app = cc1101_workaround, .name = "Sub-1 GHz", .stack_size = 1024, .icon = A_Sub1ghz_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef BUILD_LF_RFID | ||||
|     {.app = lf_rfid_workaround, .name = "125 kHz RFID", .icon = A_125khz_14}, | ||||
|     {.app = lf_rfid_workaround, .name = "125 kHz RFID", .stack_size = 1024, .icon = A_125khz_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef BUILD_IRDA | ||||
|     {.app = irda, .name = "Infrared", .icon = A_Infrared_14}, | ||||
|     {.app = irda, .name = "Infrared", .stack_size = 1024, .icon = A_Infrared_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef BUILD_IBUTTON | ||||
|     {.app = app_ibutton, .name = "iButton", .icon = A_iButton_14}, | ||||
|     {.app = app_ibutton, .name = "iButton", .stack_size = 1024, .icon = A_iButton_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef BUILD_GPIO_DEMO | ||||
|     {.app = app_gpio_test, .name = "GPIO", .icon = A_GPIO_14}, | ||||
|     {.app = app_gpio_test, .name = "GPIO", .stack_size = 1024, .icon = A_GPIO_14}, | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| @ -183,35 +198,41 @@ size_t FLIPPER_APPS_size() { | ||||
| // Plugin menu
 | ||||
| const FuriApplication FLIPPER_PLUGINS[] = { | ||||
| #ifdef BUILD_EXAMPLE_BLINK | ||||
|     {.app = application_blink, .name = "blink", .icon = A_Plugins_14}, | ||||
|     {.app = application_blink, .name = "blink", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef BUILD_EXAMPLE_INPUT_DUMP | ||||
|     {.app = application_input_dump, .name = "input dump", .icon = A_Plugins_14}, | ||||
|     {.app = application_input_dump, .name = "input dump", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef BUILD_SPEAKER_DEMO | ||||
|     {.app = coreglitch_demo_0, .name = "coreglitch_demo_0", .icon = A_Plugins_14}, | ||||
|     {.app = coreglitch_demo_0, | ||||
|      .name = "coreglitch_demo_0", | ||||
|      .stack_size = 1024, | ||||
|      .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef BUILD_SD_TEST | ||||
|     {.app = sd_card_test, .name = "sd_card_test", .icon = A_Plugins_14}, | ||||
|     {.app = sd_card_test, .name = "sd_card_test", .stack_size = 4096, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef BUILD_VIBRO_DEMO | ||||
|     {.app = application_vibro, .name = "application_vibro", .icon = A_Plugins_14}, | ||||
|     {.app = application_vibro, | ||||
|      .name = "application_vibro", | ||||
|      .stack_size = 1024, | ||||
|      .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef BUILD_MUSIC_PLAYER | ||||
|     {.app = music_player, .name = "music player", .icon = A_Plugins_14}, | ||||
|     {.app = music_player, .name = "music player", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef BUILD_FLOOPPER_BLOOPPER | ||||
|     {.app = floopper_bloopper, .name = "Floopper Bloopper", .icon = A_Games_14}, | ||||
|     {.app = floopper_bloopper, .name = "Floopper Bloopper", .stack_size = 1024, .icon = A_Games_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef BUILD_SDNFC | ||||
|     {.app = sdnfc, .name = "sdnfc", .icon = A_Plugins_14}, | ||||
|     {.app = sdnfc, .name = "sdnfc", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -8,6 +8,7 @@ typedef void (*FlipperApplication)(void*); | ||||
| typedef struct { | ||||
|     const FlipperApplication app; | ||||
|     const char* name; | ||||
|     const size_t stack_size; | ||||
|     const IconName icon; | ||||
| } FuriApplication; | ||||
| 
 | ||||
|  | ||||
| @ -33,7 +33,7 @@ void bt_cli_info(string_t args, void* context) { | ||||
|     string_t buffer; | ||||
|     string_init(buffer); | ||||
|     api_hal_bt_dump_state(buffer); | ||||
|     cli_print(string_get_cstr(buffer)); | ||||
|     printf(string_get_cstr(buffer)); | ||||
|     string_clear(buffer); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -3,8 +3,6 @@ | ||||
| #include <gui/gui.h> | ||||
| #include <input/input.h> | ||||
| 
 | ||||
| extern "C" void cli_print(const char* str); | ||||
| 
 | ||||
| #define RSSI_DELAY 5000 //rssi delay in micro second
 | ||||
| #define CHAN_SPA 0.05 // channel spacing
 | ||||
| 
 | ||||
| @ -81,9 +79,9 @@ int16_t rx_rssi(CC1101* cc1101, const FreqConfig* config) { | ||||
|     /*
 | ||||
|     char buf[256]; | ||||
|     sprintf(buf, "status: %d -> %d, rssi: %d\n", rx_status, cc1101->SpiReadStatus(CC1101_MARCSTATE), rssi_dBm); | ||||
|     cli_print(buf); | ||||
|     printf(buf); | ||||
|     sprintf(buf, "begin: %d, end: %d\n", begin_size, end_size); | ||||
|     cli_print(buf); | ||||
|     printf(buf); | ||||
|     */ | ||||
| 
 | ||||
|     // uint8_t rx_data[64];
 | ||||
| @ -101,7 +99,7 @@ int16_t rx_rssi(CC1101* cc1101, const FreqConfig* config) { | ||||
|             } | ||||
|             printf(" "); | ||||
|         } | ||||
|         printf("\n"); | ||||
|         printf("\r\n"); | ||||
|         * | ||||
| 
 | ||||
|         for(uint8_t i = 0; i < fifo_length; i++) { | ||||
| @ -111,7 +109,7 @@ int16_t rx_rssi(CC1101* cc1101, const FreqConfig* config) { | ||||
|             } | ||||
|         } | ||||
|     } else { | ||||
|         cli_print("fifo size over\n"); | ||||
|         printf("fifo size over\r\n"); | ||||
|     } | ||||
|     */ | ||||
| 
 | ||||
| @ -158,12 +156,12 @@ void flp_config(CC1101* cc1101) { | ||||
| 
 | ||||
|     // bandwidth 50-100 kHz
 | ||||
|     if(!cc1101->setRxBandwidth(75.0)) { | ||||
|         printf("wrong rx bw\n"); | ||||
|         printf("wrong rx bw\r\n"); | ||||
|     } | ||||
| 
 | ||||
|     // datarate ~30 kbps
 | ||||
|     if(!cc1101->setBitRate(100.)) { | ||||
|         printf("wrong bitrate\n"); | ||||
|         printf("wrong bitrate\r\n"); | ||||
|     } | ||||
| 
 | ||||
|     // mod
 | ||||
| @ -361,7 +359,7 @@ extern "C" void cc1101_workaround(void* p) { | ||||
| 
 | ||||
|     ValueMutex state_mutex; | ||||
|     if(!init_mutex(&state_mutex, &_state, sizeof(State))) { | ||||
|         printf("[cc1101] cannot create mutex\n"); | ||||
|         printf("[cc1101] cannot create mutex\r\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
| 
 | ||||
| @ -373,7 +371,7 @@ extern "C" void cc1101_workaround(void* p) { | ||||
|     // Open GUI and register widget
 | ||||
|     Gui* gui = (Gui*)furi_record_open("gui"); | ||||
|     if(gui == NULL) { | ||||
|         printf("[cc1101] gui is not available\n"); | ||||
|         printf("[cc1101] gui is not available\r\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
|     gui_add_widget(gui, widget, GuiLayerFullscreen); | ||||
| @ -381,7 +379,7 @@ extern "C" void cc1101_workaround(void* p) { | ||||
|     gpio_init(&debug_0, GpioModeOutputPushPull); | ||||
|     gpio_write((GpioPin*)&debug_0, false); | ||||
| 
 | ||||
|     printf("[cc1101] creating device\n"); | ||||
|     printf("[cc1101] creating device\r\n"); | ||||
|     GpioPin cs_pin = {CC1101_CS_GPIO_Port, CC1101_CS_Pin}; | ||||
| 
 | ||||
|     gpio_init(&cc1101_g0_gpio, GpioModeInput); | ||||
| @ -389,13 +387,13 @@ extern "C" void cc1101_workaround(void* p) { | ||||
|     // TODO open record
 | ||||
|     GpioPin* cs_pin_record = &cs_pin; | ||||
|     CC1101 cc1101(cs_pin_record); | ||||
|     printf("[cc1101] init device\n"); | ||||
|     printf("[cc1101] init device\r\n"); | ||||
| 
 | ||||
|     uint8_t address = cc1101.Init(); | ||||
|     if(address > 0) { | ||||
|         printf("[cc1101] init done: %d\n", address); | ||||
|         printf("[cc1101] init done: %d\r\n", address); | ||||
|     } else { | ||||
|         printf("[cc1101] init fail\n"); | ||||
|         printf("[cc1101] init fail\r\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
| 
 | ||||
| @ -406,7 +404,7 @@ extern "C" void cc1101_workaround(void* p) { | ||||
|     // setup_freq(&cc1101, &FREQ_LIST[4]);
 | ||||
|     // enable_cc1101_irq();
 | ||||
| 
 | ||||
|     printf("init ok\n"); | ||||
|     printf("init ok\r\n"); | ||||
| 
 | ||||
|     // TODO open record
 | ||||
|     GpioPin* led_record = (GpioPin*)&led_gpio[1]; | ||||
| @ -428,12 +426,12 @@ extern "C" void cc1101_workaround(void* p) { | ||||
|         if(event_status == osOK) { | ||||
|             if(event.type == EventTypeKey) { | ||||
|                 if(event.value.input.state && event.value.input.input == InputBack) { | ||||
|                     printf("[cc1101] bye!\n"); | ||||
|                     cli_print("[cc1101] bye!\n"); | ||||
|                     printf("[cc1101] bye!\r\n"); | ||||
| 
 | ||||
|                     cc1101.SpiStrobe(CC1101_SIDLE); | ||||
|                     cc1101.SpiStrobe(CC1101_SPWD); | ||||
|                     cli_print("[cc1101] go to power down\n"); | ||||
| 
 | ||||
|                     printf("[cc1101] go to power down\r\n"); | ||||
| 
 | ||||
|                     // TODO remove all widgets create by app
 | ||||
|                     widget_enabled_set(widget, false); | ||||
|  | ||||
| @ -227,14 +227,14 @@ bool CC1101::SpiSetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t lsb | ||||
| ****************************************************************/ | ||||
| uint8_t CC1101::Init(void) { | ||||
| #ifdef CC1101_DEBUG | ||||
|     printf("Init SPI...\n"); | ||||
|     printf("Init SPI...\r\n"); | ||||
| #endif | ||||
|     SpiInit(); //spi initialization
 | ||||
|     gpio_write(ss_pin, true); | ||||
| // gpio_write(SCK_PIN, true);
 | ||||
| // gpio_write(MOSI_PIN, false);
 | ||||
| #ifdef CC1101_DEBUG | ||||
|     printf("Reset CC1101...\n"); | ||||
|     printf("Reset CC1101...\r\n"); | ||||
| #endif | ||||
|     Reset(); // CC1101 reset
 | ||||
| 
 | ||||
| @ -256,7 +256,7 @@ uint8_t CC1101::Init(void) { | ||||
|     // RegConfigSettings(); //CC1101 register config
 | ||||
| 
 | ||||
| #ifdef CC1101_DEBUG | ||||
|     printf("Done!\n"); | ||||
|     printf("Done!\r\n"); | ||||
| #endif | ||||
| 
 | ||||
|     return version; | ||||
| @ -308,7 +308,7 @@ void CC1101::SetMod(uint8_t mode) { | ||||
|     } | ||||
|     } | ||||
| 
 | ||||
|     printf("\n"); | ||||
|     printf("\r\n"); | ||||
| #endif | ||||
| } | ||||
| /****************************************************************
 | ||||
| @ -394,7 +394,7 @@ void CC1101::SetReceive(void) { | ||||
|     SpiStrobe(CC1101_SRX); | ||||
|     while(SpiReadStatus(CC1101_MARCSTATE) ^ CC1101_STATUS_RX) { | ||||
|         // delay(1);
 | ||||
|         // printf("wait status\n");
 | ||||
|         // printf("wait status\r\n");
 | ||||
|     } | ||||
| } | ||||
| /****************************************************************
 | ||||
|  | ||||
| @ -27,32 +27,42 @@ void cli_putc(char c) { | ||||
|     api_hal_vcp_tx((uint8_t*)&c, 1); | ||||
| } | ||||
| 
 | ||||
| char cli_getc(Cli* cli) { | ||||
|     furi_assert(cli); | ||||
|     char c; | ||||
|     if(api_hal_vcp_rx((uint8_t*)&c, 1) == 0) { | ||||
|         cli_reset_state(cli); | ||||
|     } | ||||
|     return c; | ||||
| } | ||||
| 
 | ||||
| void cli_stdout_callback(void* _cookie, const char* data, size_t size) { | ||||
|     api_hal_vcp_tx((const uint8_t*)data, size); | ||||
| } | ||||
| 
 | ||||
| void cli_read(char* buffer, size_t size) { | ||||
|     api_hal_vcp_rx((uint8_t*)buffer, size); | ||||
| } | ||||
| 
 | ||||
| void cli_print(const char* str) { | ||||
|     api_hal_vcp_tx((uint8_t*)str, strlen(str)); | ||||
| } | ||||
| 
 | ||||
| void cli_print_version() { | ||||
|     cli_print("Build date:" BUILD_DATE ". " | ||||
|     printf("Build date:" BUILD_DATE ". " | ||||
|            "Git Commit:" GIT_COMMIT ". " | ||||
|            "Git Branch:" GIT_BRANCH ". " | ||||
|            "Commit Number:" GIT_BRANCH_NUM "."); | ||||
| } | ||||
| 
 | ||||
| void cli_motd() { | ||||
|     cli_print("Flipper cli.\r\n"); | ||||
|     printf("Flipper cli.\r\n"); | ||||
|     cli_print_version(); | ||||
| } | ||||
| 
 | ||||
| void cli_nl() { | ||||
|     cli_print("\r\n"); | ||||
|     printf("\r\n"); | ||||
| } | ||||
| 
 | ||||
| void cli_prompt() { | ||||
|     cli_print("\r\n>: "); | ||||
|     printf("\r\n>: "); | ||||
|     fflush(stdout); | ||||
| } | ||||
| 
 | ||||
| void cli_backspace(Cli* cli) { | ||||
| @ -100,8 +110,8 @@ void cli_enter(Cli* cli) { | ||||
|         cli_prompt(); | ||||
|     } else { | ||||
|         cli_nl(); | ||||
|         cli_print("Command not found: "); | ||||
|         cli_print(string_get_cstr(command)); | ||||
|         printf("Command not found: "); | ||||
|         printf(string_get_cstr(command)); | ||||
|         cli_prompt(); | ||||
|         cli_putc(CliSymbolAsciiBell); | ||||
|     } | ||||
| @ -112,14 +122,9 @@ void cli_enter(Cli* cli) { | ||||
| } | ||||
| 
 | ||||
| void cli_process_input(Cli* cli) { | ||||
|     char c; | ||||
|     char c = cli_getc(cli); | ||||
|     size_t r; | ||||
| 
 | ||||
|     r = api_hal_vcp_rx((uint8_t*)&c, 1); | ||||
|     if(r == 0) { | ||||
|         cli_reset_state(cli); | ||||
|     } | ||||
| 
 | ||||
|     if(c == CliSymbolAsciiTab) { | ||||
|         cli_putc(CliSymbolAsciiBell); | ||||
|     } else if(c == CliSymbolAsciiSOH) { | ||||
| @ -175,6 +180,7 @@ void cli_task(void* p) { | ||||
| 
 | ||||
|     furi_record_create("cli", cli); | ||||
| 
 | ||||
|     furi_stdglue_set_thread_stdout_callback(cli_stdout_callback); | ||||
|     while(1) { | ||||
|         cli_process_input(cli); | ||||
|     } | ||||
|  | ||||
| @ -34,12 +34,6 @@ void cli_add_command(Cli* cli, const char* name, CliCallback callback, void* con | ||||
|  */ | ||||
| void cli_read(char* buffer, size_t size); | ||||
| 
 | ||||
| /* Print to terminal
 | ||||
|  * Do it only from inside of callback. | ||||
|  * @param buffer - pointer to null terminated string to print. | ||||
|  */ | ||||
| void cli_print(const char* buffer); | ||||
| 
 | ||||
| /* New line 
 | ||||
|  * Send new ine sequence | ||||
|  */ | ||||
|  | ||||
| @ -5,22 +5,22 @@ | ||||
| void cli_command_help(string_t args, void* context) { | ||||
|     (void)args; | ||||
|     Cli* cli = context; | ||||
|     cli_print("Commands we have:"); | ||||
|     printf("Commands we have:"); | ||||
| 
 | ||||
|     furi_check(osMutexAcquire(cli->mutex, osWaitForever) == osOK); | ||||
|     CliCommandDict_it_t it; | ||||
|     for(CliCommandDict_it(it, cli->commands); !CliCommandDict_end_p(it); CliCommandDict_next(it)) { | ||||
|         CliCommandDict_itref_t* ref = CliCommandDict_ref(it); | ||||
|         cli_print(" "); | ||||
|         cli_print(string_get_cstr(ref->key)); | ||||
|         printf(" "); | ||||
|         printf(string_get_cstr(ref->key)); | ||||
|     }; | ||||
|     furi_check(osMutexRelease(cli->mutex) == osOK); | ||||
| 
 | ||||
|     if(string_size(args) > 0) { | ||||
|         cli_nl(); | ||||
|         cli_print("Also I have no clue what '"); | ||||
|         cli_print(string_get_cstr(args)); | ||||
|         cli_print("' is."); | ||||
|         printf("Also I have no clue what '"); | ||||
|         printf(string_get_cstr(args)); | ||||
|         printf("' is."); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -43,7 +43,7 @@ void cli_command_uuid(string_t args, void* context) { | ||||
|         uint8_t uid_byte = uid[i]; | ||||
|         string_cat_printf(byte_str, "%02X", uid_byte); | ||||
|     } | ||||
|     cli_print(string_get_cstr(byte_str)); | ||||
|     printf(string_get_cstr(byte_str)); | ||||
| } | ||||
| 
 | ||||
| void cli_command_date(string_t args, void* context) { | ||||
| @ -61,11 +61,19 @@ void cli_command_date(string_t args, void* context) { | ||||
|     string_cat_printf(datetime_str, "%.2d:%.2d:%.2d ", time.Hours, time.Minutes, time.Seconds); | ||||
|     string_cat_printf(datetime_str, "%.2d-%.2d-%.2d", date.Month, date.Date, 2000 + date.Year); | ||||
| 
 | ||||
|     cli_print(string_get_cstr(datetime_str)); | ||||
|     printf(string_get_cstr(datetime_str)); | ||||
| 
 | ||||
|     string_clear(datetime_str); | ||||
| } | ||||
| 
 | ||||
| void cli_command_log(string_t args, void* context) { | ||||
|     Cli* cli = context; | ||||
|     furi_stdglue_set_global_stdout_callback(cli_stdout_callback); | ||||
|     printf("Press any key to stop...\r\n"); | ||||
|     cli_getc(cli); | ||||
|     furi_stdglue_set_global_stdout_callback(NULL); | ||||
| } | ||||
| 
 | ||||
| void cli_commands_init(Cli* cli) { | ||||
|     cli_add_command(cli, "help", cli_command_help, cli); | ||||
|     cli_add_command(cli, "?", cli_command_help, cli); | ||||
| @ -73,4 +81,5 @@ void cli_commands_init(Cli* cli) { | ||||
|     cli_add_command(cli, "!", cli_command_version, cli); | ||||
|     cli_add_command(cli, "uid", cli_command_uuid, cli); | ||||
|     cli_add_command(cli, "date", cli_command_date, cli); | ||||
|     cli_add_command(cli, "log", cli_command_log, cli); | ||||
| } | ||||
|  | ||||
| @ -38,4 +38,6 @@ Cli* cli_alloc(); | ||||
| void cli_free(Cli* cli); | ||||
| void cli_reset_state(Cli* cli); | ||||
| void cli_print_version(); | ||||
| char cli_getc(Cli* cli); | ||||
| void cli_putc(char c); | ||||
| void cli_stdout_callback(void* _cookie, const char* data, size_t size); | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
| extern TIM_HandleTypeDef SPEAKER_TIM; | ||||
| 
 | ||||
| void coreglitch_demo_0(void* p) { | ||||
|     printf("coreglitch demo!\n"); | ||||
|     printf("coreglitch demo!\r\n"); | ||||
| 
 | ||||
|     float notes[] = { | ||||
|         0.0, | ||||
|  | ||||
| @ -11,13 +11,13 @@ static void state_cb(const void* value, void* ctx) { | ||||
|     InputDump dump = {.packed = 0}; | ||||
|     dump.state = *(InputState*)value; | ||||
| 
 | ||||
|     printf("state: %02x\n", dump.packed); | ||||
|     printf("state: %02x\r\n", dump.packed); | ||||
| } | ||||
| 
 | ||||
| static void event_cb(const void* value, void* ctx) { | ||||
|     const InputEvent* event = value; | ||||
| 
 | ||||
|     printf("event: %02x %s\n", event->input, event->state ? "pressed" : "released"); | ||||
|     printf("event: %02x %s\r\n", event->input, event->state ? "pressed" : "released"); | ||||
| } | ||||
| 
 | ||||
| void application_input_dump(void* p) { | ||||
| @ -28,7 +28,7 @@ void application_input_dump(void* p) { | ||||
|     PubSub* event_record = furi_record_open("input_events"); | ||||
|     subscribe_pubsub(event_record, event_cb, NULL); | ||||
| 
 | ||||
|     printf("Example app [input dump]\n"); | ||||
|     printf("Example app [input dump]\r\n"); | ||||
| 
 | ||||
|     for(;;) { | ||||
|         delay(100); | ||||
|  | ||||
| @ -37,7 +37,7 @@ void u8g2_qrcode(void* p) { | ||||
|     qrcode_initText(&qrcode, qrcodeBytes, qr_version, qr_error_correction, "HELLO FLIPPER"); | ||||
| 
 | ||||
|     if(fb_record == NULL) { | ||||
|         printf("[widget] cannot create fb record\n"); | ||||
|         printf("[widget] cannot create fb record\r\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| Subproject commit 621044255a8be4d2c3f342e2b22178a342ccbfe8 | ||||
| Subproject commit 7ba50ef912566c78d2ddd37ab5912a8cada5c35d | ||||
| @ -66,7 +66,7 @@ void app_gpio_test(void* p) { | ||||
| 
 | ||||
|     ValueMutex state_mutex; | ||||
|     if(!init_mutex(&state_mutex, &_state, sizeof(State))) { | ||||
|         printf("[gpio-tester] cannot create mutex\n"); | ||||
|         printf("[gpio-tester] cannot create mutex\r\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
| 
 | ||||
| @ -94,7 +94,7 @@ void app_gpio_test(void* p) { | ||||
|         if(event_status == osOK) { | ||||
|             if(event.type == EventTypeKey) { | ||||
|                 if(event.value.input.state && event.value.input.input == InputBack) { | ||||
|                     printf("[gpio-tester] bye!\n"); | ||||
|                     printf("[gpio-tester] bye!\r\n"); | ||||
|                     // TODO remove all widgets create by app
 | ||||
|                     widget_enabled_set(widget, false); | ||||
|                     furiac_exit(NULL); | ||||
|  | ||||
| @ -76,7 +76,7 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ | ||||
| 
 | ||||
|     case U8X8_MSG_BYTE_INIT: | ||||
| #ifdef DEBUG | ||||
|         printf("[u8g2] init\n"); | ||||
|         printf("[u8g2] init\r\n"); | ||||
| #endif | ||||
| 
 | ||||
|         // TODO change it to FuriRecord pin
 | ||||
| @ -85,7 +85,7 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ | ||||
| 
 | ||||
|     case U8X8_MSG_BYTE_START_TRANSFER: | ||||
| #ifdef DEBUG | ||||
|         printf("[u8g2] start\n"); | ||||
|         printf("[u8g2] start\r\n"); | ||||
| #endif | ||||
| 
 | ||||
|         // TODO: SPI manager
 | ||||
| @ -98,7 +98,7 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ | ||||
| 
 | ||||
|     case U8X8_MSG_BYTE_END_TRANSFER: | ||||
| #ifdef DEBUG | ||||
|         printf("[u8g2] end\n"); | ||||
|         printf("[u8g2] end\r\n"); | ||||
| #endif | ||||
| 
 | ||||
|         asm("nop"); | ||||
|  | ||||
| @ -25,15 +25,15 @@ void input_task(void* p) { | ||||
|     uint8_t debounce_counters[INPUT_COUNT]; | ||||
| 
 | ||||
|     if(!init_managed(&input_state_record, &input_state, sizeof(input_state))) { | ||||
|         printf("[input_task] cannot initialize ValueManager for input_state\n"); | ||||
|         printf("[input_task] cannot initialize ValueManager for input_state\r\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
|     if(!init_pubsub(&input_events_record)) { | ||||
|         printf("[input_task] cannot initialize PubSub for input_events\n"); | ||||
|         printf("[input_task] cannot initialize PubSub for input_events\r\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
|     if(!init_event(&event)) { | ||||
|         printf("[input_task] cannot initialize Event\n"); | ||||
|         printf("[input_task] cannot initialize Event\r\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -263,7 +263,7 @@ void irda(void* p) { | ||||
| 
 | ||||
|     ValueMutex state_mutex; | ||||
|     if(!init_mutex(&state_mutex, &_state, sizeof(State))) { | ||||
|         printf("cannot create mutex\n"); | ||||
|         printf("cannot create mutex\r\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -48,7 +48,7 @@ void prepare_data(uint32_t ID, uint32_t VENDOR, uint8_t* data) { | ||||
|     for(uint8_t i = 0; i < 64; i++) { | ||||
|         printf("%d ", data[i]); | ||||
|     } | ||||
|     printf("\n"); | ||||
|     printf("\r\n"); | ||||
|     */ | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -106,7 +106,7 @@ static bool even_check(uint8_t* buf) { | ||||
|                 buf[line * (ROW_SIZE + 1) + ROW_SIZE]); | ||||
|             return false; | ||||
|         } | ||||
|         printf("\n"); | ||||
|         printf("\r\n"); | ||||
|     } | ||||
| 
 | ||||
|     for(uint8_t col = 0; col < ROW_SIZE; col++) { | ||||
| @ -138,7 +138,7 @@ static void extract_data(uint8_t* buf, uint8_t* customer, uint32_t* em_data) { | ||||
|             offset++; | ||||
|         } | ||||
|     } | ||||
|     printf("\n"); | ||||
|     printf("\r\n"); | ||||
| 
 | ||||
|     *customer = data; | ||||
| 
 | ||||
| @ -155,7 +155,7 @@ static void extract_data(uint8_t* buf, uint8_t* customer, uint32_t* em_data) { | ||||
|             offset++; | ||||
|         } | ||||
|     } | ||||
|     printf("\n"); | ||||
|     printf("\r\n"); | ||||
| 
 | ||||
|     *em_data = data; | ||||
| } | ||||
| @ -194,7 +194,7 @@ void lf_rfid_workaround(void* p) { | ||||
| 
 | ||||
|     ValueMutex state_mutex; | ||||
|     if(!init_mutex(&state_mutex, &_state, sizeof(State))) { | ||||
|         printf("cannot create mutex\n"); | ||||
|         printf("cannot create mutex\r\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -33,7 +33,7 @@ ValueMutex* menu_init() { | ||||
| 
 | ||||
|     ValueMutex* menu_mutex = furi_alloc(sizeof(ValueMutex)); | ||||
|     if(menu_mutex == NULL || !init_mutex(menu_mutex, menu, sizeof(Menu))) { | ||||
|         printf("[menu_task] cannot create menu mutex\n"); | ||||
|         printf("[menu_task] cannot create menu mutex\r\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -369,7 +369,7 @@ void music_player(void* p) { | ||||
| 
 | ||||
|     ValueMutex state_mutex; | ||||
|     if(!init_mutex(&state_mutex, &_state, sizeof(State))) { | ||||
|         printf("cannot create mutex\n"); | ||||
|         printf("cannot create mutex\r\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
| 
 | ||||
| @ -393,7 +393,7 @@ void music_player(void* p) { | ||||
|     osThreadId_t player = osThreadNew(music_player_thread, &context, &player_attr); | ||||
| 
 | ||||
|     if(player == NULL) { | ||||
|         printf("cannot create player thread\n"); | ||||
|         printf("cannot create player thread\r\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -142,19 +142,19 @@ void power_free(Power* power) { | ||||
| } | ||||
| 
 | ||||
| void power_cli_poweroff(string_t args, void* context) { | ||||
|     cli_print("Poweroff in 3 seconds"); | ||||
|     printf("Poweroff in 3 seconds"); | ||||
|     osDelay(3000); | ||||
|     api_hal_power_off(); | ||||
| } | ||||
| 
 | ||||
| void power_cli_reset(string_t args, void* context) { | ||||
|     cli_print("NVIC System Reset in 3 seconds"); | ||||
|     printf("NVIC System Reset in 3 seconds"); | ||||
|     osDelay(3000); | ||||
|     NVIC_SystemReset(); | ||||
| } | ||||
| 
 | ||||
| void power_cli_dfu(string_t args, void* context) { | ||||
|     cli_print("NVIC System Reset to DFU mode in 3 seconds"); | ||||
|     printf("NVIC System Reset to DFU mode in 3 seconds"); | ||||
|     api_hal_boot_set_mode(ApiHalBootModeDFU); | ||||
|     osDelay(3000); | ||||
|     NVIC_SystemReset(); | ||||
| @ -164,7 +164,7 @@ void power_cli_test(string_t args, void* context) { | ||||
|     string_t buffer; | ||||
|     string_init(buffer); | ||||
|     api_hal_power_dump_state(buffer); | ||||
|     cli_print(string_get_cstr(buffer)); | ||||
|     printf(string_get_cstr(buffer)); | ||||
|     string_clear(buffer); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -610,99 +610,99 @@ void SdTest::cli_read_benchmark(string_t args, void* _ctx) { | ||||
|     const uint8_t str_buffer_size = 64; | ||||
|     char str_buffer[str_buffer_size]; | ||||
| 
 | ||||
|     cli_print("preparing benchmark data\r\n"); | ||||
|     printf("preparing benchmark data\r\n"); | ||||
|     bool data_prepared = _this->prepare_benchmark_data(); | ||||
|     if(data_prepared) { | ||||
|         cli_print("benchmark data prepared\r\n"); | ||||
|         printf("benchmark data prepared\r\n"); | ||||
|     } else { | ||||
|         cli_print("error: cannot allocate buffer for benchmark data\r\n"); | ||||
|         printf("error: cannot allocate buffer for benchmark data\r\n"); | ||||
|     } | ||||
| 
 | ||||
|     // prepare data for read test
 | ||||
|     cli_print("prepare data for read speed test, procedure can be lengthy, please wait\r\n"); | ||||
|     printf("prepare data for read speed test, procedure can be lengthy, please wait\r\n"); | ||||
| 
 | ||||
|     if(!_this->fs_api->file.open(&file, "read.test", FSAM_WRITE, FSOM_OPEN_ALWAYS)) { | ||||
|         cli_print("error: cannot open file in prepare read\r\n"); | ||||
|         printf("error: cannot open file in prepare read\r\n"); | ||||
|     } | ||||
| 
 | ||||
|     for(size_t i = 0; i < benchmark_data_size / b4096_size; i++) { | ||||
|         bytes_written = _this->fs_api->file.write(&file, benchmark_data, b4096_size); | ||||
|         if(bytes_written != b4096_size || file.error_id != FSE_OK) { | ||||
|             cli_print("error: cannot write to file in prepare read\r\n"); | ||||
|             printf("error: cannot write to file in prepare read\r\n"); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if(!_this->fs_api->file.close(&file)) { | ||||
|         cli_print("error: cannot close file in prepare read\r\n"); | ||||
|         printf("error: cannot close file in prepare read\r\n"); | ||||
|     } | ||||
| 
 | ||||
|     // test start
 | ||||
|     cli_print("read speed test, procedure can be lengthy, please wait\r\n"); | ||||
|     printf("read speed test, procedure can be lengthy, please wait\r\n"); | ||||
| 
 | ||||
|     // open file
 | ||||
|     if(!_this->fs_api->file.open(&file, "read.test", FSAM_READ, FSOM_OPEN_EXISTING)) { | ||||
|         cli_print("error: cannot open file in read benchmark\r\n"); | ||||
|         printf("error: cannot open file in read benchmark\r\n"); | ||||
|     } | ||||
| 
 | ||||
|     // 1b test
 | ||||
|     benchmark_bps = | ||||
|         _this->read_benchmark_internal(b1_size, benchmark_data_size / b1_size, &file, true); | ||||
|     if(benchmark_bps == BENCHMARK_ERROR) { | ||||
|         cli_print("error: in 1-byte read test\r\n"); | ||||
|         printf("error: in 1-byte read test\r\n"); | ||||
|     } else { | ||||
|         snprintf(str_buffer, str_buffer_size, "1-byte: %lu bytes per second\r\n", benchmark_bps); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
|     } | ||||
| 
 | ||||
|     // 8b test
 | ||||
|     benchmark_bps = | ||||
|         _this->read_benchmark_internal(b8_size, benchmark_data_size / b8_size, &file, true); | ||||
|     if(benchmark_bps == BENCHMARK_ERROR) { | ||||
|         cli_print("error: in 8-byte read test\r\n"); | ||||
|         printf("error: in 8-byte read test\r\n"); | ||||
|     } else { | ||||
|         snprintf(str_buffer, str_buffer_size, "8-byte: %lu bytes per second\r\n", benchmark_bps); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
|     } | ||||
| 
 | ||||
|     // 32b test
 | ||||
|     benchmark_bps = | ||||
|         _this->read_benchmark_internal(b32_size, benchmark_data_size / b32_size, &file, true); | ||||
|     if(benchmark_bps == BENCHMARK_ERROR) { | ||||
|         cli_print("error: in 32-byte read test\r\n"); | ||||
|         printf("error: in 32-byte read test\r\n"); | ||||
|     } else { | ||||
|         snprintf(str_buffer, str_buffer_size, "32-byte: %lu bytes per second\r\n", benchmark_bps); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
|     } | ||||
| 
 | ||||
|     // 256b test
 | ||||
|     benchmark_bps = | ||||
|         _this->read_benchmark_internal(b256_size, benchmark_data_size / b256_size, &file, true); | ||||
|     if(benchmark_bps == BENCHMARK_ERROR) { | ||||
|         cli_print("error: in 256-byte read test\r\n"); | ||||
|         printf("error: in 256-byte read test\r\n"); | ||||
|     } else { | ||||
|         snprintf(str_buffer, str_buffer_size, "256-byte: %lu bytes per second\r\n", benchmark_bps); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
|     } | ||||
| 
 | ||||
|     // 4096b test
 | ||||
|     benchmark_bps = | ||||
|         _this->read_benchmark_internal(b4096_size, benchmark_data_size / b4096_size, &file, true); | ||||
|     if(benchmark_bps == BENCHMARK_ERROR) { | ||||
|         cli_print("error: in 4096-byte read test\r\n"); | ||||
|         printf("error: in 4096-byte read test\r\n"); | ||||
|     } else { | ||||
|         snprintf( | ||||
|             str_buffer, str_buffer_size, "4096-byte: %lu bytes per second\r\n", benchmark_bps); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
|     } | ||||
| 
 | ||||
|     // close file
 | ||||
|     if(!_this->fs_api->file.close(&file)) { | ||||
|         cli_print("error: cannot close file\r\n"); | ||||
|         printf("error: cannot close file\r\n"); | ||||
|     } | ||||
| 
 | ||||
|     _this->free_benchmark_data(); | ||||
| 
 | ||||
|     cli_print("test completed\r\n"); | ||||
|     printf("test completed\r\n"); | ||||
| } | ||||
| 
 | ||||
| void SdTest::cli_write_benchmark(string_t args, void* _ctx) { | ||||
| @ -721,68 +721,68 @@ void SdTest::cli_write_benchmark(string_t args, void* _ctx) { | ||||
|     const uint8_t str_buffer_size = 64; | ||||
|     char str_buffer[str_buffer_size]; | ||||
| 
 | ||||
|     cli_print("preparing benchmark data\r\n"); | ||||
|     printf("preparing benchmark data\r\n"); | ||||
|     bool data_prepared = _this->prepare_benchmark_data(); | ||||
|     if(data_prepared) { | ||||
|         cli_print("benchmark data prepared\r\n"); | ||||
|         printf("benchmark data prepared\r\n"); | ||||
|     } else { | ||||
|         cli_print("error: cannot allocate buffer for benchmark data\r\n"); | ||||
|         printf("error: cannot allocate buffer for benchmark data\r\n"); | ||||
|     } | ||||
| 
 | ||||
|     cli_print("write speed test, procedure can be lengthy, please wait\r\n"); | ||||
|     printf("write speed test, procedure can be lengthy, please wait\r\n"); | ||||
| 
 | ||||
|     // 1b test
 | ||||
|     benchmark_bps = _this->write_benchmark_internal(b1_size, benchmark_data_size / b1_size, true); | ||||
|     if(benchmark_bps == BENCHMARK_ERROR) { | ||||
|         cli_print("error: in 1-byte write test\r\n"); | ||||
|         printf("error: in 1-byte write test\r\n"); | ||||
|     } else { | ||||
|         snprintf(str_buffer, str_buffer_size, "1-byte: %lu bytes per second\r\n", benchmark_bps); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
|     } | ||||
| 
 | ||||
|     // 8b test
 | ||||
|     benchmark_bps = _this->write_benchmark_internal(b8_size, benchmark_data_size / b8_size, true); | ||||
|     if(benchmark_bps == BENCHMARK_ERROR) { | ||||
|         cli_print("error: in 8-byte write test\r\n"); | ||||
|         printf("error: in 8-byte write test\r\n"); | ||||
|     } else { | ||||
|         snprintf(str_buffer, str_buffer_size, "8-byte: %lu bytes per second\r\n", benchmark_bps); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
|     } | ||||
| 
 | ||||
|     // 32b test
 | ||||
|     benchmark_bps = | ||||
|         _this->write_benchmark_internal(b32_size, benchmark_data_size / b32_size, true); | ||||
|     if(benchmark_bps == BENCHMARK_ERROR) { | ||||
|         cli_print("error: in 32-byte write test\r\n"); | ||||
|         printf("error: in 32-byte write test\r\n"); | ||||
|     } else { | ||||
|         snprintf(str_buffer, str_buffer_size, "32-byte: %lu bytes per second\r\n", benchmark_bps); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
|     } | ||||
| 
 | ||||
|     // 256b test
 | ||||
|     benchmark_bps = | ||||
|         _this->write_benchmark_internal(b256_size, benchmark_data_size / b256_size, true); | ||||
|     if(benchmark_bps == BENCHMARK_ERROR) { | ||||
|         cli_print("error: in 256-byte write test\r\n"); | ||||
|         printf("error: in 256-byte write test\r\n"); | ||||
|     } else { | ||||
|         snprintf(str_buffer, str_buffer_size, "256-byte: %lu bytes per second\r\n", benchmark_bps); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
|     } | ||||
| 
 | ||||
|     // 4096b test
 | ||||
|     benchmark_bps = | ||||
|         _this->write_benchmark_internal(b4096_size, benchmark_data_size / b4096_size, true); | ||||
|     if(benchmark_bps == BENCHMARK_ERROR) { | ||||
|         cli_print("error: in 4096-byte write test\r\n"); | ||||
|         printf("error: in 4096-byte write test\r\n"); | ||||
|     } else { | ||||
|         snprintf( | ||||
|             str_buffer, str_buffer_size, "4096-byte: %lu bytes per second\r\n", benchmark_bps); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
|     } | ||||
| 
 | ||||
|     _this->free_benchmark_data(); | ||||
| 
 | ||||
|     cli_print("test completed\r\n"); | ||||
|     printf("test completed\r\n"); | ||||
| } | ||||
| 
 | ||||
| // wait for button press
 | ||||
| @ -873,7 +873,7 @@ template <class T> void SdTest::set_error(std::initializer_list<T> list) { | ||||
| template <class T> void SdTest::set_text(std::initializer_list<T> list) { | ||||
|     uint8_t line_position = 0; | ||||
|     acquire_state(); | ||||
|     printf("------------------------\n"); | ||||
|     printf("------------------------\r\n"); | ||||
| 
 | ||||
|     // set line strings from args
 | ||||
|     for(auto element : list) { | ||||
| @ -886,10 +886,10 @@ template <class T> void SdTest::set_text(std::initializer_list<T> list) { | ||||
|     // set empty lines
 | ||||
|     for(; line_position < state.lines_count; line_position++) { | ||||
|         state.line[line_position] = ""; | ||||
|         printf("\n"); | ||||
|         printf("\r\n"); | ||||
|     } | ||||
| 
 | ||||
|     printf("------------------------\n"); | ||||
|     printf("------------------------\r\n"); | ||||
|     release_state(); | ||||
|     update_gui(); | ||||
| } | ||||
|  | ||||
| @ -174,7 +174,7 @@ void app_sd_info_callback(void* context) { | ||||
|         if(str_buffer[i] == NULL) { | ||||
|             memory_error = true; | ||||
|         } else { | ||||
|             snprintf(str_buffer[i], str_buffer_size, ""); | ||||
|             str_buffer[i][0] = 0; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -365,25 +365,25 @@ void app_sd_eject_callback(void* context) { | ||||
| static void cli_sd_status(string_t args, void* _ctx) { | ||||
|     SdApp* sd_app = (SdApp*)_ctx; | ||||
| 
 | ||||
|     cli_print("SD status: "); | ||||
|     cli_print(fs_error_get_internal_desc(sd_app->info.status)); | ||||
|     cli_print("\r\n"); | ||||
|     printf("SD status: "); | ||||
|     printf(fs_error_get_internal_desc(sd_app->info.status)); | ||||
|     printf("\r\n"); | ||||
| } | ||||
| 
 | ||||
| static void cli_sd_format(string_t args, void* _ctx) { | ||||
|     SdApp* sd_app = (SdApp*)_ctx; | ||||
| 
 | ||||
|     cli_print("formatting SD card, please wait\r\n"); | ||||
|     printf("formatting SD card, please wait\r\n"); | ||||
| 
 | ||||
|     // format card
 | ||||
|     app_sd_format_internal(sd_app); | ||||
| 
 | ||||
|     if(sd_app->info.status != SD_OK) { | ||||
|         cli_print("SD card format error: "); | ||||
|         cli_print(fs_error_get_internal_desc(sd_app->info.status)); | ||||
|         cli_print("\r\n"); | ||||
|         printf("SD card format error: "); | ||||
|         printf(fs_error_get_internal_desc(sd_app->info.status)); | ||||
|         printf("\r\n"); | ||||
|     } else { | ||||
|         cli_print("SD card formatted\r\n"); | ||||
|         printf("SD card formatted\r\n"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -437,42 +437,42 @@ static void cli_sd_info(string_t args, void* _ctx) { | ||||
|         } | ||||
| 
 | ||||
|         snprintf(str_buffer, str_buffer_size, "Label: %s\r\n", volume_label); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
| 
 | ||||
|         snprintf(str_buffer, str_buffer_size, "%s, S/N: %lu\r\n", fs_type, serial_num); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
| 
 | ||||
|         snprintf(str_buffer, str_buffer_size, "Cluster: %d sectors\r\n", fs->csize); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
| 
 | ||||
|         snprintf(str_buffer, str_buffer_size, "Sector: %d bytes\r\n", sector_size); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
| 
 | ||||
|         snprintf( | ||||
|             str_buffer, str_buffer_size, "%lu KB total\r\n", total_sectors / 1024 * sector_size); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
| 
 | ||||
|         snprintf( | ||||
|             str_buffer, str_buffer_size, "%lu KB free\r\n", free_sectors / 1024 * sector_size); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
|     } else { | ||||
|         cli_print("SD status error: "); | ||||
|         printf("SD status error: "); | ||||
|         snprintf( | ||||
|             str_buffer, | ||||
|             str_buffer_size, | ||||
|             "%s\r\n", | ||||
|             fs_error_get_internal_desc(_fs_status(&sd_app->info))); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
| 
 | ||||
|         cli_print("Label error: "); | ||||
|         printf("Label error: "); | ||||
|         snprintf( | ||||
|             str_buffer, str_buffer_size, "%s\r\n", fs_error_get_internal_desc(get_label_result)); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
| 
 | ||||
|         cli_print("Get free error: "); | ||||
|         printf("Get free error: "); | ||||
|         snprintf( | ||||
|             str_buffer, str_buffer_size, "%s\r\n", fs_error_get_internal_desc(get_free_result)); | ||||
|         cli_print(str_buffer); | ||||
|         printf(str_buffer); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -511,7 +511,7 @@ void sd_filesystem(void* p) { | ||||
|     with_value_mutex( | ||||
|         menu_vm, (Menu * menu) { menu_item_add(menu, menu_item); }); | ||||
| 
 | ||||
|     printf("[sd_filesystem] start\n"); | ||||
|     printf("[sd_filesystem] start\r\n"); | ||||
| 
 | ||||
|     // add api record
 | ||||
|     furi_record_create("sdcard", fs_api); | ||||
| @ -522,7 +522,7 @@ void sd_filesystem(void* p) { | ||||
|     while(true) { | ||||
|         if(sd_was_present) { | ||||
|             if(hal_gpio_read_sd_detect()) { | ||||
|                 printf("[sd_filesystem] card detected\n"); | ||||
|                 printf("[sd_filesystem] card detected\r\n"); | ||||
| 
 | ||||
|                 uint8_t bsp_result = BSP_SD_Init(); | ||||
| 
 | ||||
| @ -530,13 +530,13 @@ void sd_filesystem(void* p) { | ||||
|                     sd_app->info.status = SD_LOW_LEVEL_ERR; | ||||
|                     printf("[sd_filesystem] bsp error: %x\n", bsp_result); | ||||
|                 } else { | ||||
|                     printf("[sd_filesystem] bsp ok\n"); | ||||
|                     printf("[sd_filesystem] bsp ok\r\n"); | ||||
|                     sd_app->info.status = f_mount(&sd_app->info.fat_fs, sd_app->info.path, 1); | ||||
| 
 | ||||
|                     if(sd_app->info.status != SD_OK) { | ||||
|                         printf("[sd_filesystem] mount error: %d\n", sd_app->info.status); | ||||
|                     } else { | ||||
|                         printf("[sd_filesystem] mount ok\n"); | ||||
|                         printf("[sd_filesystem] mount ok\r\n"); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
| @ -545,7 +545,7 @@ void sd_filesystem(void* p) { | ||||
|             } | ||||
|         } else { | ||||
|             if(!hal_gpio_read_sd_detect()) { | ||||
|                 printf("[sd_filesystem] card removed\n"); | ||||
|                 printf("[sd_filesystem] card removed\r\n"); | ||||
| 
 | ||||
|                 widget_enabled_set(sd_app->icon.widget, false); | ||||
|                 app_sd_unmount_card(sd_app); | ||||
|  | ||||
| @ -44,7 +44,7 @@ void template_app(void* p) { | ||||
|     /* init state here */ | ||||
|     ValueMutex state_mutex; | ||||
|     if(!init_mutex(&state_mutex, &_state, sizeof(State))) { | ||||
|         printf("cannot create mutex\n"); | ||||
|         printf("cannot create mutex\r\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
| 
 | ||||
| @ -56,7 +56,7 @@ void template_app(void* p) { | ||||
|     // Open GUI and register widget | ||||
|     Gui* gui = furi_record_open("gui"); | ||||
|     if(gui == NULL) { | ||||
|         printf("gui is not available\n"); | ||||
|         printf("gui is not available\r\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
|     gui_add_widget(gui, widget, /* specify UI layer */); | ||||
|  | ||||
| @ -59,7 +59,7 @@ typedef struct { | ||||
| void furi_concurent_app(void* p) { | ||||
|     ValueMutex* mutex = (ValueMutex*)p; | ||||
|     if(mutex == NULL) { | ||||
|         printf("cannot open mutex\n"); | ||||
|         printf("cannot open mutex\r\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
| 
 | ||||
| @ -67,7 +67,7 @@ void furi_concurent_app(void* p) { | ||||
|         ConcurrentValue* value = (ConcurrentValue*)acquire_mutex_block(mutex); | ||||
| 
 | ||||
|         if(value == NULL) { | ||||
|             printf("cannot take record\n"); | ||||
|             printf("cannot take record\r\n"); | ||||
|             release_mutex(mutex, value); | ||||
|             furiac_exit(NULL); | ||||
|         } | ||||
| @ -103,7 +103,7 @@ void test_furi_concurrent_access() { | ||||
| 
 | ||||
|         if(value == NULL) { | ||||
|             release_mutex(&mutex, value); | ||||
|             mu_fail("cannot take record\n"); | ||||
|             mu_fail("cannot take record\r\n"); | ||||
|         } | ||||
| 
 | ||||
|         // emulate read-modify-write broken by context switching
 | ||||
|  | ||||
| @ -31,19 +31,19 @@ bool test_furi_ac_create_kill() { | ||||
| 
 | ||||
|     FuriApp* widget = furiac_start(create_kill_app, "create_kill_app", (void*)&counter); | ||||
|     if(widget == NULL) { | ||||
|         printf("create widget fail\n"); | ||||
|         printf("create widget fail\r\n"); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     delay(10); | ||||
| 
 | ||||
|     if(!furiac_kill(widget)) { | ||||
|         printf("kill widget fail\n"); | ||||
|         printf("kill widget fail\r\n"); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     if(value_a == counter) { | ||||
|         printf("counter unchanged\n"); | ||||
|         printf("counter unchanged\r\n"); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -5,7 +5,7 @@ FW_ADDRESS		= 0x08008000 | ||||
| OS_OFFSET		= 0x00008000 | ||||
| FLASH_ADDRESS	= 0x08000000 | ||||
| 
 | ||||
| OPENOCD_OPTS	= -f interface/stlink.cfg -c "transport select hla_swd" -f ../debug/stm32wbx.cfg -c "init" | ||||
| OPENOCD_OPTS	= -f interface/stlink.cfg -c "transport select hla_swd" -f ../debug/stm32wbx.cfg -c "stm32wbx.cpu configure -rtos auto" -c "init" | ||||
| BOOT_CFLAGS		= -DBOOT_ADDRESS=$(BOOT_ADDRESS) -DFW_ADDRESS=$(FW_ADDRESS) -DOS_OFFSET=$(OS_OFFSET) | ||||
| MCU_FLAGS		= -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard | ||||
| 
 | ||||
|  | ||||
| @ -17,20 +17,22 @@ void furi_init() { | ||||
| 
 | ||||
| int systemd() { | ||||
|     furi_init(); | ||||
| 
 | ||||
|     printf("[systemd] furi initialized\r\n"); | ||||
|     // FURI startup
 | ||||
|     for(size_t i = 0; i < FLIPPER_SERVICES_size(); i++) { | ||||
|         printf("[systemd] starting service %s\r\n", FLIPPER_SERVICES[i].name); | ||||
|         osThreadAttr_t* attr = furi_alloc(sizeof(osThreadAttr_t)); | ||||
|         attr->name = FLIPPER_SERVICES[i].name; | ||||
|         attr->stack_size = 1024; | ||||
|         attr->stack_size = FLIPPER_SERVICES[i].stack_size; | ||||
|         osThreadNew(FLIPPER_SERVICES[i].app, NULL, attr); | ||||
|     } | ||||
|     printf("[systemd] all services started\r\n"); | ||||
| 
 | ||||
|     while(1) { | ||||
|         osThreadSuspend(osThreadGetId()); | ||||
|     } | ||||
| 
 | ||||
|     printf("\n=== Bye from Flipper Zero! ===\n\n"); | ||||
|     printf("[systemd] === Bye from Flipper Zero! ===\r\n"); | ||||
| 
 | ||||
|     return (int)exitcode; | ||||
| } | ||||
| @ -5,10 +5,7 @@ bool init_pubsub(PubSub* pubsub) { | ||||
|     // mutex without name,
 | ||||
|     // no attributes (unfortunatly robust mutex is not supported by FreeRTOS),
 | ||||
|     // with dynamic memory allocation
 | ||||
|     const osMutexAttr_t value_mutex_attr = { | ||||
|         .name = NULL, .attr_bits = 0, .cb_mem = NULL, .cb_size = 0U}; | ||||
| 
 | ||||
|     pubsub->mutex = osMutexNew(&value_mutex_attr); | ||||
|     pubsub->mutex = osMutexNew(NULL); | ||||
|     if(pubsub->mutex == NULL) return false; | ||||
| 
 | ||||
|     // construct list
 | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| #include "record.h" | ||||
| #include "check.h" | ||||
| #include "memmgr.h" | ||||
| 
 | ||||
| #include <cmsis_os2.h> | ||||
| #include <m-string.h> | ||||
| @ -22,34 +23,38 @@ typedef struct { | ||||
|     FuriRecordDict_t records; | ||||
| } FuriRecordData; | ||||
| 
 | ||||
| FuriRecordData furi_record_data; | ||||
| static FuriRecordData* furi_record_data = NULL; | ||||
| 
 | ||||
| void furi_record_init() { | ||||
|     furi_record_data.records_mutex = osMutexNew(NULL); | ||||
|     FuriRecordDict_init(furi_record_data.records); | ||||
|     furi_record_data = furi_alloc(sizeof(FuriRecordData)); | ||||
|     furi_record_data->records_mutex = osMutexNew(NULL); | ||||
|     furi_check(furi_record_data->records_mutex); | ||||
|     FuriRecordDict_init(furi_record_data->records); | ||||
| } | ||||
| 
 | ||||
| FuriRecord* furi_record_get_or_create(string_t name_str) { | ||||
|     FuriRecord* record = FuriRecordDict_get(furi_record_data.records, name_str); | ||||
|     assert(furi_record_data); | ||||
|     FuriRecord* record = FuriRecordDict_get(furi_record_data->records, name_str); | ||||
|     if(!record) { | ||||
|         FuriRecord new_record; | ||||
|         new_record.data = NULL; | ||||
|         new_record.owner = NULL; | ||||
|         osThreadIdSet_init(new_record.holders); | ||||
|         FuriRecordDict_set_at(furi_record_data.records, name_str, new_record); | ||||
|         record = FuriRecordDict_get(furi_record_data.records, name_str); | ||||
|         FuriRecordDict_set_at(furi_record_data->records, name_str, new_record); | ||||
|         record = FuriRecordDict_get(furi_record_data->records, name_str); | ||||
|     } | ||||
|     return record; | ||||
| } | ||||
| 
 | ||||
| void furi_record_create(const char* name, void* data) { | ||||
|     assert(furi_record_data); | ||||
|     osThreadId_t thread_id = osThreadGetId(); | ||||
| 
 | ||||
|     string_t name_str; | ||||
|     string_init_set_str(name_str, name); | ||||
| 
 | ||||
|     // Acquire mutex
 | ||||
|     furi_check(osMutexAcquire(furi_record_data.records_mutex, osWaitForever) == osOK); | ||||
|     furi_check(osMutexAcquire(furi_record_data->records_mutex, osWaitForever) == osOK); | ||||
|     FuriRecord* record = furi_record_get_or_create(name_str); | ||||
|     record->data = data; | ||||
|     record->owner = thread_id; | ||||
| @ -60,31 +65,34 @@ void furi_record_create(const char* name, void* data) { | ||||
|         osThreadFlagsSet((osThreadId_t)*osThreadIdSet_ref(it), FURI_RECORD_FLAG_UPDATED); | ||||
|     } | ||||
|     // Release mutex
 | ||||
|     furi_check(osMutexRelease(furi_record_data.records_mutex) == osOK); | ||||
|     furi_check(osMutexRelease(furi_record_data->records_mutex) == osOK); | ||||
| 
 | ||||
|     string_clear(name_str); | ||||
| } | ||||
| 
 | ||||
| bool furi_record_destroy(const char* name) { | ||||
|     assert(furi_record_data); | ||||
|     osThreadId_t thread_id = osThreadGetId(); | ||||
| 
 | ||||
|     string_t name_str; | ||||
|     string_init_set_str(name_str, name); | ||||
| 
 | ||||
|     bool destroyed = false; | ||||
|     furi_check(osMutexAcquire(furi_record_data.records_mutex, osWaitForever) == osOK); | ||||
|     FuriRecord* record = FuriRecordDict_get(furi_record_data.records, name_str); | ||||
|     furi_check(osMutexAcquire(furi_record_data->records_mutex, osWaitForever) == osOK); | ||||
|     FuriRecord* record = FuriRecordDict_get(furi_record_data->records, name_str); | ||||
|     if(record && record->owner == thread_id && osThreadIdSet_size(record->holders) == 0) { | ||||
|         osThreadIdSet_clear(record->holders); | ||||
|         FuriRecordDict_erase(furi_record_data.records, name_str); | ||||
|         FuriRecordDict_erase(furi_record_data->records, name_str); | ||||
|         destroyed = true; | ||||
|     } | ||||
|     furi_check(osMutexRelease(furi_record_data.records_mutex) == osOK); | ||||
|     furi_check(osMutexRelease(furi_record_data->records_mutex) == osOK); | ||||
| 
 | ||||
|     string_clear(name_str); | ||||
|     return destroyed; | ||||
| } | ||||
| 
 | ||||
| void* furi_record_open(const char* name) { | ||||
|     assert(furi_record_data); | ||||
|     osThreadId_t thread_id = osThreadGetId(); | ||||
| 
 | ||||
|     string_t name_str; | ||||
| @ -92,10 +100,10 @@ void* furi_record_open(const char* name) { | ||||
| 
 | ||||
|     FuriRecord* record = NULL; | ||||
|     while(1) { | ||||
|         furi_check(osMutexAcquire(furi_record_data.records_mutex, osWaitForever) == osOK); | ||||
|         furi_check(osMutexAcquire(furi_record_data->records_mutex, osWaitForever) == osOK); | ||||
|         record = furi_record_get_or_create(name_str); | ||||
|         osThreadIdSet_push(record->holders, (uint32_t)thread_id); | ||||
|         furi_check(osMutexRelease(furi_record_data.records_mutex) == osOK); | ||||
|         furi_check(osMutexRelease(furi_record_data->records_mutex) == osOK); | ||||
|         // Check if owner is already arrived
 | ||||
|         if(record->owner) { | ||||
|             break; | ||||
| @ -109,15 +117,16 @@ void* furi_record_open(const char* name) { | ||||
| } | ||||
| 
 | ||||
| void furi_record_close(const char* name) { | ||||
|     assert(furi_record_data); | ||||
|     osThreadId_t thread_id = osThreadGetId(); | ||||
| 
 | ||||
|     string_t name_str; | ||||
|     string_init_set_str(name_str, name); | ||||
| 
 | ||||
|     furi_check(osMutexAcquire(furi_record_data.records_mutex, osWaitForever) == osOK); | ||||
|     FuriRecord* record = FuriRecordDict_get(furi_record_data.records, name_str); | ||||
|     furi_check(osMutexAcquire(furi_record_data->records_mutex, osWaitForever) == osOK); | ||||
|     FuriRecord* record = FuriRecordDict_get(furi_record_data->records, name_str); | ||||
|     osThreadIdSet_erase(record->holders, (uint32_t)thread_id); | ||||
|     furi_check(osMutexRelease(furi_record_data.records_mutex) == osOK); | ||||
|     furi_check(osMutexRelease(furi_record_data->records_mutex) == osOK); | ||||
| 
 | ||||
|     string_clear(name_str); | ||||
| } | ||||
|  | ||||
| @ -1,12 +1,57 @@ | ||||
| #include "stdglue.h" | ||||
| #include <main.h> | ||||
| #include "check.h" | ||||
| #include "memmgr.h" | ||||
| 
 | ||||
| #include <main.h> | ||||
| #include <cmsis_os2.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <m-dict.h> | ||||
| 
 | ||||
| extern UART_HandleTypeDef DEBUG_UART; | ||||
| 
 | ||||
| DICT_DEF2( | ||||
|     FuriStdglueCallbackDict, | ||||
|     uint32_t, | ||||
|     M_DEFAULT_OPLIST, | ||||
|     FuriStdglueWriteCallback, | ||||
|     M_PTR_OPLIST) | ||||
| 
 | ||||
| typedef struct { | ||||
|     osMutexId_t mutex; | ||||
|     FuriStdglueCallbackDict_t global_outputs; | ||||
|     FuriStdglueCallbackDict_t thread_outputs; | ||||
| } FuriStdglue; | ||||
| 
 | ||||
| static FuriStdglue* furi_stdglue = NULL; | ||||
| 
 | ||||
| static ssize_t stdout_write(void* _cookie, const char* data, size_t size) { | ||||
|     assert(furi_stdglue); | ||||
|     osKernelState_t state = osKernelGetState(); | ||||
|     osThreadId_t thread_id = osThreadGetId(); | ||||
|     if(state == osKernelRunning && thread_id && | ||||
|        osMutexAcquire(furi_stdglue->mutex, osWaitForever) == osOK) { | ||||
|         // We are in the thread context
 | ||||
|         // Handle global callbacks
 | ||||
|         FuriStdglueCallbackDict_it_t it; | ||||
|         for(FuriStdglueCallbackDict_it(it, furi_stdglue->global_outputs); | ||||
|             !FuriStdglueCallbackDict_end_p(it); | ||||
|             FuriStdglueCallbackDict_next(it)) { | ||||
|             osThreadId_t it_thread = (osThreadId_t)FuriStdglueCallbackDict_ref(it)->key; | ||||
|             FuriStdglueWriteCallback it_callback = FuriStdglueCallbackDict_ref(it)->value; | ||||
|             if(thread_id != it_thread) { | ||||
|                 it_callback(_cookie, data, size); | ||||
|             } | ||||
|         } | ||||
|         // Handle thread callbacks
 | ||||
|         FuriStdglueWriteCallback* callback_ptr = | ||||
|             FuriStdglueCallbackDict_get(furi_stdglue->thread_outputs, (uint32_t)thread_id); | ||||
|         if(callback_ptr) { | ||||
|             (*callback_ptr)(_cookie, data, size); | ||||
|         } | ||||
|         furi_check(osMutexRelease(furi_stdglue->mutex) == osOK); | ||||
|     } | ||||
|     // Flush
 | ||||
|     if(data == 0) { | ||||
|         /*
 | ||||
|          * This means that we should flush internal buffers.  Since we | ||||
| @ -15,13 +60,20 @@ static ssize_t stdout_write(void* _cookie, const char* data, size_t size) { | ||||
|          */ | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     // Debug uart
 | ||||
|     HAL_UART_Transmit(&DEBUG_UART, (uint8_t*)data, (uint16_t)size, HAL_MAX_DELAY); | ||||
| 
 | ||||
|     // All data consumed
 | ||||
|     return size; | ||||
| } | ||||
| 
 | ||||
| bool furi_stdglue_init() { | ||||
| void furi_stdglue_init() { | ||||
|     furi_stdglue = furi_alloc(sizeof(FuriStdglue)); | ||||
|     // Init outputs structures
 | ||||
|     furi_stdglue->mutex = osMutexNew(NULL); | ||||
|     furi_check(furi_stdglue->mutex); | ||||
|     FuriStdglueCallbackDict_init(furi_stdglue->global_outputs); | ||||
|     FuriStdglueCallbackDict_init(furi_stdglue->thread_outputs); | ||||
|     // Prepare and set stdout descriptor
 | ||||
|     FILE* fp = fopencookie( | ||||
|         NULL, | ||||
|         "w", | ||||
| @ -31,8 +83,42 @@ bool furi_stdglue_init() { | ||||
|             .seek = NULL, | ||||
|             .close = NULL, | ||||
|         }); | ||||
|     setvbuf(fp, NULL, _IONBF, 0); | ||||
|     setvbuf(fp, NULL, _IOLBF, 0); | ||||
|     stdout = fp; | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool furi_stdglue_set_global_stdout_callback(FuriStdglueWriteCallback callback) { | ||||
|     assert(furi_stdglue); | ||||
|     osThreadId_t thread_id = osThreadGetId(); | ||||
|     if(thread_id) { | ||||
|         furi_check(osMutexAcquire(furi_stdglue->mutex, osWaitForever) == osOK); | ||||
|         if(callback) { | ||||
|             FuriStdglueCallbackDict_set_at( | ||||
|                 furi_stdglue->global_outputs, (uint32_t)thread_id, callback); | ||||
|         } else { | ||||
|             FuriStdglueCallbackDict_erase(furi_stdglue->global_outputs, (uint32_t)thread_id); | ||||
|         } | ||||
|         furi_check(osMutexRelease(furi_stdglue->mutex) == osOK); | ||||
|         return true; | ||||
|     } else { | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool furi_stdglue_set_thread_stdout_callback(FuriStdglueWriteCallback callback) { | ||||
|     assert(furi_stdglue); | ||||
|     osThreadId_t thread_id = osThreadGetId(); | ||||
|     if(thread_id) { | ||||
|         furi_check(osMutexAcquire(furi_stdglue->mutex, osWaitForever) == osOK); | ||||
|         if(callback) { | ||||
|             FuriStdglueCallbackDict_set_at( | ||||
|                 furi_stdglue->thread_outputs, (uint32_t)thread_id, callback); | ||||
|         } else { | ||||
|             FuriStdglueCallbackDict_erase(furi_stdglue->thread_outputs, (uint32_t)thread_id); | ||||
|         } | ||||
|         furi_check(osMutexRelease(furi_stdglue->mutex) == osOK); | ||||
|         return true; | ||||
|     } else { | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,12 +1,36 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <stdbool.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| bool furi_stdglue_init(); | ||||
| /* Write callback
 | ||||
|  * @param _cookie - pointer to cookie (see stdio gnu extension) | ||||
|  * @param data - pointer to data | ||||
|  * @param size - data size | ||||
|  * @warnign your handler must consume everything | ||||
|  */ | ||||
| typedef void (*FuriStdglueWriteCallback)(void* _cookie, const char* data, size_t size); | ||||
| 
 | ||||
| /* Initialized std library glue code */ | ||||
| void furi_stdglue_init(); | ||||
| 
 | ||||
| /* Set global STDOUT callback
 | ||||
|  * @param callback - callback or NULL to clear | ||||
|  * @return true on success, otherwise fail | ||||
|  * @warning function is thread aware, use this API from the same thread | ||||
|  */ | ||||
| bool furi_stdglue_set_global_stdout_callback(FuriStdglueWriteCallback callback); | ||||
| 
 | ||||
| /* Set STDOUT callback for your thread 
 | ||||
|  * @param callback - callback or NULL to clear | ||||
|  * @return true on success, otherwise fail | ||||
|  * @warning function is thread aware, use this API from the same thread | ||||
|  */ | ||||
| bool furi_stdglue_set_thread_stdout_callback(FuriStdglueWriteCallback callback); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
|  | ||||
| @ -10,10 +10,7 @@ bool init_composer(ValueComposer* composer, void* value) { | ||||
|     // mutex without name,
 | ||||
|     // no attributes (unfortunatly robust mutex is not supported by FreeRTOS),
 | ||||
|     // with dynamic memory allocation
 | ||||
|     const osMutexAttr_t value_mutex_attr = { | ||||
|         .name = NULL, .attr_bits = 0, .cb_mem = NULL, .cb_size = 0U}; | ||||
| 
 | ||||
|     composer->mutex = osMutexNew(&value_mutex_attr); | ||||
|     composer->mutex = osMutexNew(NULL); | ||||
|     if(composer->mutex == NULL) return false; | ||||
| 
 | ||||
|     if(!init_event(&composer->request)) return false; | ||||
|  | ||||
| @ -6,10 +6,7 @@ bool init_mutex(ValueMutex* valuemutex, void* value, size_t size) { | ||||
|     // mutex without name,
 | ||||
|     // no attributes (unfortunatly robust mutex is not supported by FreeRTOS),
 | ||||
|     // with dynamic memory allocation
 | ||||
|     const osMutexAttr_t value_mutext_attr = { | ||||
|         .name = NULL, .attr_bits = 0, .cb_mem = NULL, .cb_size = 0U}; | ||||
| 
 | ||||
|     valuemutex->mutex = osMutexNew(&value_mutext_attr); | ||||
|     valuemutex->mutex = osMutexNew(NULL); | ||||
|     if(valuemutex->mutex == NULL) return false; | ||||
| 
 | ||||
|     valuemutex->value = value; | ||||
|  | ||||
| @ -16,6 +16,9 @@ typedef enum { | ||||
| /* Initialize drivers */ | ||||
| void api_hal_power_init(); | ||||
| 
 | ||||
| /* Check if deep sleep availble */ | ||||
| bool api_hal_power_deep_available(); | ||||
| 
 | ||||
| /* Go to deep sleep */ | ||||
| void api_hal_power_deep_sleep(); | ||||
| 
 | ||||
|  | ||||
| @ -25,7 +25,7 @@ size_t api_hal_vcp_rx(uint8_t* buffer, size_t size); | ||||
|  * @param buffer - pointer to buffer | ||||
|  * @param size - buffer size | ||||
|  */ | ||||
| void api_hal_vcp_tx(uint8_t* buffer, size_t size); | ||||
| void api_hal_vcp_tx(const uint8_t* buffer, size_t size); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
|  | ||||
| @ -58,12 +58,12 @@ | ||||
| /* USER CODE END 0 */ | ||||
| #endif | ||||
| #define configENABLE_FPU                         1 | ||||
| #define configENABLE_MPU                         0 | ||||
| #define configENABLE_MPU                         1 | ||||
| 
 | ||||
| #define configUSE_PREEMPTION                     1 | ||||
| #define configSUPPORT_STATIC_ALLOCATION          1 | ||||
| #define configSUPPORT_DYNAMIC_ALLOCATION         1 | ||||
| #define configUSE_IDLE_HOOK                      1 | ||||
| #define configUSE_IDLE_HOOK                      0 | ||||
| #define configUSE_TICK_HOOK                      0 | ||||
| #define configCPU_CLOCK_HZ                       ( SystemCoreClock ) | ||||
| #define configTICK_RATE_HZ                       ((TickType_t)1024) | ||||
| @ -71,8 +71,8 @@ | ||||
| #define configMINIMAL_STACK_SIZE                 ((uint16_t)128) | ||||
| #define configTOTAL_HEAP_SIZE                    ((size_t)131072) | ||||
| #define configMAX_TASK_NAME_LEN                  ( 16 ) | ||||
| #define configGENERATE_RUN_TIME_STATS            1 | ||||
| #define configUSE_TRACE_FACILITY                 1 | ||||
| #define configGENERATE_RUN_TIME_STATS            0 | ||||
| #define configUSE_TRACE_FACILITY                 0 | ||||
| #define configUSE_16_BIT_TICKS                   0 | ||||
| #define configUSE_MUTEXES                        1 | ||||
| #define configQUEUE_REGISTRY_SIZE                8 | ||||
| @ -83,6 +83,7 @@ | ||||
| #define configUSE_PORT_OPTIMISED_TASK_SELECTION  0 | ||||
| #define configUSE_TICKLESS_IDLE                  2 | ||||
| #define configRECORD_STACK_HIGH_ADDRESS          1 | ||||
| #define configUSE_NEWLIB_REENTRANT               0 | ||||
| /* USER CODE BEGIN MESSAGE_BUFFER_LENGTH_TYPE */ | ||||
| /* Defaults to size_t for backward compatibility, but can be changed
 | ||||
|    if lengths will always be less than the number of bytes in a size_t. */ | ||||
| @ -106,7 +107,6 @@ to exclude the API function. */ | ||||
| #define INCLUDE_vTaskPrioritySet             1 | ||||
| #define INCLUDE_uxTaskPriorityGet            1 | ||||
| #define INCLUDE_vTaskDelete                  1 | ||||
| #define INCLUDE_vTaskCleanUpResources        1 | ||||
| #define INCLUDE_vTaskSuspend                 1 | ||||
| #define INCLUDE_vTaskDelayUntil              1 | ||||
| #define INCLUDE_vTaskDelay                   1 | ||||
| @ -150,7 +150,7 @@ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ | ||||
| /* Normal assert() semantics without relying on the provision of an assert.h
 | ||||
| header file. */ | ||||
| /* USER CODE BEGIN 1 */ | ||||
| #define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );} | ||||
| #define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); asm("bkpt 1"); for( ;; );} | ||||
| /* USER CODE END 1 */ | ||||
| 
 | ||||
| /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
 | ||||
| @ -163,14 +163,4 @@ standard names. */ | ||||
| 
 | ||||
| /* #define xPortSysTickHandler SysTick_Handler */ | ||||
| 
 | ||||
| /* USER CODE BEGIN 2 */ | ||||
| /* Definitions needed when configGENERATE_RUN_TIME_STATS is on */ | ||||
| #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS configureTimerForRunTimeStats | ||||
| #define portGET_RUN_TIME_COUNTER_VALUE getRunTimeCounterValue | ||||
| /* USER CODE END 2 */ | ||||
| 
 | ||||
| /* USER CODE BEGIN Defines */ | ||||
| /* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */ | ||||
| /* USER CODE END Defines */ | ||||
| 
 | ||||
| #endif /* FREERTOS_CONFIG_H */ | ||||
|  | ||||
| @ -3,49 +3,23 @@ | ||||
| #include <task.h> | ||||
| #include <main.h> | ||||
| 
 | ||||
| void systemd(void *argument); | ||||
| 
 | ||||
| osThreadId_t systemdHandle; | ||||
| const osThreadAttr_t systemd_attributes = { | ||||
|     .name = "systemd", | ||||
|     .priority = (osPriority_t) osPriorityNormal, | ||||
|     .stack_size = 1024 * 4 | ||||
|     .stack_size = 1024 | ||||
| }; | ||||
| 
 | ||||
| void systemd(void *argument); | ||||
| 
 | ||||
| void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */ | ||||
| 
 | ||||
| /* Hook prototypes */ | ||||
| void configureTimerForRunTimeStats(void); | ||||
| unsigned long getRunTimeCounterValue(void); | ||||
| void vApplicationIdleHook(void); | ||||
| void vApplicationStackOverflowHook(TaskHandle_t xTask, signed char *pcTaskName); | ||||
| 
 | ||||
| __weak void configureTimerForRunTimeStats(void) { | ||||
| } | ||||
| 
 | ||||
| __weak unsigned long getRunTimeCounterValue(void) { | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| __weak void vApplicationIdleHook( void ) { | ||||
|     /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
 | ||||
|     to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle | ||||
|     task. It is essential that code added to this hook function never attempts | ||||
|     to block in any way (for example, call xQueueReceive() with a block time | ||||
|     specified, or call vTaskDelay()). If the application makes use of the | ||||
|     vTaskDelete() API function (as this demo application does) then it is also | ||||
|     important that vApplicationIdleHook() is permitted to return to its calling | ||||
|     function, because it is the responsibility of the idle task to clean up | ||||
|     memory allocated by the kernel to any task that has since been deleted. */ | ||||
| } | ||||
| 
 | ||||
| __weak void vApplicationStackOverflowHook(TaskHandle_t xTask, signed char *pcTaskName) { | ||||
| void vApplicationStackOverflowHook(TaskHandle_t xTask, signed char *pcTaskName) { | ||||
|     /* Run time stack overflow checking is performed if
 | ||||
|     configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook function is | ||||
|     called if a stack overflow is detected. */ | ||||
|     asm("bkpt 1"); | ||||
|     while(1); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void MX_FREERTOS_Init(void) { | ||||
|     systemdHandle = osThreadNew(systemd, NULL, &systemd_attributes); | ||||
| } | ||||
|  | ||||
| @ -111,7 +111,7 @@ void HardFault_Handler(void) | ||||
| void MemManage_Handler(void) | ||||
| { | ||||
|   /* USER CODE BEGIN MemoryManagement_IRQn 0 */ | ||||
| 
 | ||||
|   __asm("bkpt 1"); | ||||
|   /* USER CODE END MemoryManagement_IRQn 0 */ | ||||
|   while (1) | ||||
|   { | ||||
| @ -126,7 +126,7 @@ void MemManage_Handler(void) | ||||
| void BusFault_Handler(void) | ||||
| { | ||||
|   /* USER CODE BEGIN BusFault_IRQn 0 */ | ||||
| 
 | ||||
|   __asm("bkpt 1"); | ||||
|   /* USER CODE END BusFault_IRQn 0 */ | ||||
|   while (1) | ||||
|   { | ||||
| @ -141,7 +141,7 @@ void BusFault_Handler(void) | ||||
| void UsageFault_Handler(void) | ||||
| { | ||||
|   /* USER CODE BEGIN UsageFault_IRQn 0 */ | ||||
| 
 | ||||
|   __asm("bkpt 1"); | ||||
|   /* USER CODE END UsageFault_IRQn 0 */ | ||||
|   while (1) | ||||
|   { | ||||
| @ -399,7 +399,6 @@ extern void HW_TS_RTC_Wakeup_Handler(); | ||||
| extern void HW_IPCC_Tx_Handler(); | ||||
| extern void HW_IPCC_Rx_Handler(); | ||||
| 
 | ||||
| 
 | ||||
| void RTC_WKUP_IRQHandler(void) | ||||
| { | ||||
|   HW_TS_RTC_Wakeup_Handler(); | ||||
| @ -408,14 +407,11 @@ void RTC_WKUP_IRQHandler(void) | ||||
| void IPCC_C1_TX_IRQHandler(void) | ||||
| { | ||||
|   HW_IPCC_Tx_Handler(); | ||||
| 
 | ||||
|   return; | ||||
| } | ||||
| 
 | ||||
| void IPCC_C1_RX_IRQHandler(void) | ||||
| { | ||||
|   HW_IPCC_Rx_Handler(); | ||||
|   return; | ||||
| } | ||||
| 
 | ||||
| /* USER CODE END 1 */ | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| #include <api-hal-power.h> | ||||
| #include <api-hal-clock.h> | ||||
| #include <api-hal-bt.h> | ||||
| 
 | ||||
| #include <stm32wbxx_ll_rcc.h> | ||||
| #include <stm32wbxx_ll_pwr.h> | ||||
| @ -22,6 +23,10 @@ void api_hal_power_init() { | ||||
|     bq25896_init(); | ||||
| } | ||||
| 
 | ||||
| bool api_hal_power_deep_available() { | ||||
|     return api_hal_bt_is_alive(); | ||||
| } | ||||
| 
 | ||||
| void api_hal_power_deep_sleep() { | ||||
|   while( LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)); | ||||
| 
 | ||||
|  | ||||
| @ -69,7 +69,7 @@ static inline bool api_hal_timebase_timer_cmp_is_ok() { | ||||
| } | ||||
| 
 | ||||
| static inline uint32_t api_hal_timebase_timer_get_cmp() { | ||||
|     return LL_LPTIM_GetCompare(API_HAL_TIMEBASE_TIMER);; | ||||
|     return LL_LPTIM_GetCompare(API_HAL_TIMEBASE_TIMER); | ||||
| } | ||||
| 
 | ||||
| static inline void api_hal_timebase_timer_set_cmp(uint32_t value) { | ||||
|  | ||||
| @ -96,9 +96,12 @@ static inline uint32_t api_hal_timebase_sleep(TickType_t expected_idle_ticks) { | ||||
|     const uint16_t expected_cnt = (before_tick + expected_idle_ticks - 2) * API_HAL_TIMEBASE_CLK_PER_TICK; | ||||
|     api_hal_timebase_timer_set_cmp(expected_cnt); | ||||
| 
 | ||||
|     HAL_SuspendTick(); | ||||
|     // Go to stop2 mode
 | ||||
|     api_hal_power_deep_sleep(); | ||||
| 
 | ||||
|     HAL_ResumeTick(); | ||||
| 
 | ||||
|     // Spin till we are in timer safe zone
 | ||||
|     while(!api_hal_timebase_timer_is_safe()) {} | ||||
| 
 | ||||
| @ -124,14 +127,15 @@ static inline uint32_t api_hal_timebase_sleep(TickType_t expected_idle_ticks) { | ||||
| } | ||||
| 
 | ||||
| void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) { | ||||
|     if (!api_hal_power_deep_available() || api_hal_timebase.insomnia) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // Limit mount of ticks to maximum that timer can count
 | ||||
|     if (expected_idle_ticks > API_HAL_TIMEBASE_MAX_SLEEP) { | ||||
|         expected_idle_ticks = API_HAL_TIMEBASE_MAX_SLEEP; | ||||
|     } | ||||
| 
 | ||||
|     if (api_hal_timebase.insomnia)  | ||||
|         return; | ||||
|      | ||||
|     // Stop IRQ handling, no one should disturb us till we finish 
 | ||||
|     __disable_irq(); | ||||
| 
 | ||||
|  | ||||
| @ -12,7 +12,7 @@ typedef struct { | ||||
|     volatile bool underrun; | ||||
| } ApiHalVcp; | ||||
| 
 | ||||
| ApiHalVcp api_hal_vcp; | ||||
| static ApiHalVcp* api_hal_vcp = NULL; | ||||
| 
 | ||||
| static const uint8_t ascii_soh = 0x01; | ||||
| static const uint8_t ascii_eot = 0x04; | ||||
| @ -24,19 +24,20 @@ void _api_hal_vcp_rx_callback(const uint8_t* buffer, size_t size); | ||||
| void _api_hal_vcp_tx_complete(size_t size); | ||||
| 
 | ||||
| void api_hal_vcp_init() { | ||||
|     api_hal_vcp.rx_stream = xStreamBufferCreate(API_HAL_VCP_RX_BUFFER_SIZE, 1); | ||||
|     api_hal_vcp.tx_semaphore = osSemaphoreNew(1, 1, NULL); | ||||
|     api_hal_vcp.alive = false; | ||||
|     api_hal_vcp.underrun = false; | ||||
|     api_hal_vcp = furi_alloc(sizeof(ApiHalVcp)); | ||||
|     api_hal_vcp->rx_stream = xStreamBufferCreate(API_HAL_VCP_RX_BUFFER_SIZE, 1); | ||||
|     api_hal_vcp->tx_semaphore = osSemaphoreNew(1, 1, NULL); | ||||
|     api_hal_vcp->alive = false; | ||||
|     api_hal_vcp->underrun = false; | ||||
| } | ||||
| 
 | ||||
| void _api_hal_vcp_init() { | ||||
|     osSemaphoreRelease(api_hal_vcp.tx_semaphore); | ||||
|     osSemaphoreRelease(api_hal_vcp->tx_semaphore); | ||||
| } | ||||
| 
 | ||||
| void _api_hal_vcp_deinit() { | ||||
|     api_hal_vcp.alive = false; | ||||
|     osSemaphoreRelease(api_hal_vcp.tx_semaphore); | ||||
|     api_hal_vcp->alive = false; | ||||
|     osSemaphoreRelease(api_hal_vcp->tx_semaphore); | ||||
| } | ||||
| 
 | ||||
| void _api_hal_vcp_control_line(uint8_t state) { | ||||
| @ -45,43 +46,46 @@ void _api_hal_vcp_control_line(uint8_t state) { | ||||
|     bool rts = state & 0b10; | ||||
| 
 | ||||
|     if (rts) { | ||||
|         api_hal_vcp.alive = true; | ||||
|         api_hal_vcp->alive = true; | ||||
|         _api_hal_vcp_rx_callback(&ascii_soh, 1); // SOH
 | ||||
|     } else { | ||||
|         api_hal_vcp.alive = false; | ||||
|         api_hal_vcp->alive = false; | ||||
|         _api_hal_vcp_rx_callback(&ascii_eot, 1); // EOT
 | ||||
|     } | ||||
| 
 | ||||
|     osSemaphoreRelease(api_hal_vcp.tx_semaphore); | ||||
|     osSemaphoreRelease(api_hal_vcp->tx_semaphore); | ||||
| } | ||||
| 
 | ||||
| void _api_hal_vcp_rx_callback(const uint8_t* buffer, size_t size) { | ||||
|     BaseType_t xHigherPriorityTaskWoken = pdFALSE; | ||||
|     size_t ret = xStreamBufferSendFromISR(api_hal_vcp.rx_stream, buffer, size, &xHigherPriorityTaskWoken); | ||||
|     size_t ret = xStreamBufferSendFromISR(api_hal_vcp->rx_stream, buffer, size, &xHigherPriorityTaskWoken); | ||||
|     if (ret != size) { | ||||
|         api_hal_vcp.underrun = true; | ||||
|         api_hal_vcp->underrun = true; | ||||
|     } | ||||
|     portYIELD_FROM_ISR(xHigherPriorityTaskWoken); | ||||
| } | ||||
| 
 | ||||
| void _api_hal_vcp_tx_complete(size_t size) { | ||||
|     osSemaphoreRelease(api_hal_vcp.tx_semaphore); | ||||
|     osSemaphoreRelease(api_hal_vcp->tx_semaphore); | ||||
| } | ||||
| 
 | ||||
| size_t api_hal_vcp_rx(uint8_t* buffer, size_t size) { | ||||
|     return xStreamBufferReceive(api_hal_vcp.rx_stream, buffer, size, portMAX_DELAY); | ||||
|     furi_assert(api_hal_vcp); | ||||
|     return xStreamBufferReceive(api_hal_vcp->rx_stream, buffer, size, portMAX_DELAY); | ||||
| } | ||||
| 
 | ||||
| void api_hal_vcp_tx(uint8_t* buffer, size_t size) { | ||||
|     while (size > 0 && api_hal_vcp.alive) { | ||||
|         furi_check(osSemaphoreAcquire(api_hal_vcp.tx_semaphore, osWaitForever) == osOK); | ||||
| void api_hal_vcp_tx(const uint8_t* buffer, size_t size) { | ||||
|     furi_assert(api_hal_vcp); | ||||
| 
 | ||||
|     while (size > 0 && api_hal_vcp->alive) { | ||||
|         furi_check(osSemaphoreAcquire(api_hal_vcp->tx_semaphore, osWaitForever) == osOK); | ||||
| 
 | ||||
|         size_t batch_size = size; | ||||
|         if (batch_size > APP_TX_DATA_SIZE) { | ||||
|             batch_size = APP_TX_DATA_SIZE; | ||||
|         } | ||||
| 
 | ||||
|         if (CDC_Transmit_FS(buffer, batch_size) == USBD_OK) { | ||||
|         if (CDC_Transmit_FS((uint8_t*)buffer, batch_size) == USBD_OK) { | ||||
|             size -= batch_size; | ||||
|             buffer += batch_size; | ||||
|         } else { | ||||
|  | ||||
| @ -1,7 +1,6 @@ | ||||
| #include "main.h" | ||||
| 
 | ||||
| #include "app_common.h" | ||||
| 
 | ||||
| #include "dbg_trace.h" | ||||
| #include "ble.h" | ||||
| #include "tl.h" | ||||
| @ -14,6 +13,8 @@ | ||||
| #include "dis_app.h" | ||||
| #include "hrs_app.h" | ||||
| 
 | ||||
| #include <api-hal.h> | ||||
| 
 | ||||
| typedef struct _tSecurityParams { | ||||
|   uint8_t ioCapability; | ||||
|   uint8_t mitm_mode; | ||||
| @ -214,10 +215,11 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt ) | ||||
|       if (disconnection_complete_event->Connection_Handle == BleApplicationContext.BleApplicationContext_legacy.connectionHandle) { | ||||
|         BleApplicationContext.BleApplicationContext_legacy.connectionHandle = 0; | ||||
|         BleApplicationContext.Device_Connection_Status = APP_BLE_IDLE; | ||||
|         APP_DBG_MSG("\r\n\r** DISCONNECTION EVENT WITH CLIENT \n"); | ||||
|         APP_DBG_MSG("\r\n\r** DISCONNECTION EVENT WITH CLIENT \r\n"); | ||||
|       } | ||||
|       /* restart advertising */ | ||||
|       Adv_Request(APP_BLE_FAST_ADV); | ||||
|       api_hal_timebase_insomnia_exit(); | ||||
|     } | ||||
|     break; /* EVT_DISCONN_COMPLETE */ | ||||
| 
 | ||||
| @ -227,45 +229,46 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt ) | ||||
|       switch (meta_evt->subevent) | ||||
|       { | ||||
|         case EVT_LE_CONN_UPDATE_COMPLETE: | ||||
|           APP_DBG_MSG("\r\n\r** CONNECTION UPDATE EVENT WITH CLIENT \n"); | ||||
|           APP_DBG_MSG("\r\n\r** CONNECTION UPDATE EVENT WITH CLIENT \r\n"); | ||||
| 
 | ||||
|           /* USER CODE BEGIN EVT_LE_CONN_UPDATE_COMPLETE */ | ||||
| 
 | ||||
|           /* USER CODE END EVT_LE_CONN_UPDATE_COMPLETE */ | ||||
|           break; | ||||
|         case EVT_LE_PHY_UPDATE_COMPLETE: | ||||
|           APP_DBG_MSG("EVT_UPDATE_PHY_COMPLETE \n"); | ||||
|           APP_DBG_MSG("EVT_UPDATE_PHY_COMPLETE \r\n"); | ||||
|           evt_le_phy_update_complete = (hci_le_phy_update_complete_event_rp0*)meta_evt->data; | ||||
|           if (evt_le_phy_update_complete->Status == 0) | ||||
|           { | ||||
|             APP_DBG_MSG("EVT_UPDATE_PHY_COMPLETE, status ok \n"); | ||||
|             APP_DBG_MSG("EVT_UPDATE_PHY_COMPLETE, status ok \r\n"); | ||||
|           } | ||||
|           else | ||||
|           { | ||||
|             APP_DBG_MSG("EVT_UPDATE_PHY_COMPLETE, status nok \n"); | ||||
|             APP_DBG_MSG("EVT_UPDATE_PHY_COMPLETE, status nok \r\n"); | ||||
|           } | ||||
| 
 | ||||
|           ret = hci_le_read_phy(BleApplicationContext.BleApplicationContext_legacy.connectionHandle,&TX_PHY,&RX_PHY); | ||||
|           if (ret == BLE_STATUS_SUCCESS) | ||||
|           { | ||||
|             APP_DBG_MSG("Read_PHY success \n"); | ||||
|             APP_DBG_MSG("Read_PHY success \r\n"); | ||||
| 
 | ||||
|             if ((TX_PHY == TX_2M) && (RX_PHY == RX_2M)) | ||||
|             { | ||||
|               APP_DBG_MSG("PHY Param  TX= %d, RX= %d \n", TX_PHY, RX_PHY); | ||||
|               APP_DBG_MSG("PHY Param  TX= %d, RX= %d \r\n", TX_PHY, RX_PHY); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|               APP_DBG_MSG("PHY Param  TX= %d, RX= %d \n", TX_PHY, RX_PHY); | ||||
|               APP_DBG_MSG("PHY Param  TX= %d, RX= %d \r\n", TX_PHY, RX_PHY); | ||||
|             } | ||||
|           } | ||||
|           else | ||||
|           { | ||||
|             APP_DBG_MSG("Read conf not succeess \n"); | ||||
|             APP_DBG_MSG("Read conf not succeess \r\n"); | ||||
|           } | ||||
|           break; | ||||
|         case EVT_LE_CONN_COMPLETE: | ||||
|         { | ||||
|           api_hal_timebase_insomnia_enter(); | ||||
|           hci_le_connection_complete_event_rp0 *connection_complete_event; | ||||
| 
 | ||||
|           /**
 | ||||
| @ -275,7 +278,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt ) | ||||
| 
 | ||||
|           HW_TS_Stop(BleApplicationContext.Advertising_mgr_timer_Id); | ||||
| 
 | ||||
|           APP_DBG_MSG("EVT_LE_CONN_COMPLETE for connection handle 0x%x\n", connection_complete_event->Connection_Handle); | ||||
|           APP_DBG_MSG("EVT_LE_CONN_COMPLETE for connection handle 0x%x\r\n", connection_complete_event->Connection_Handle); | ||||
|           if (BleApplicationContext.Device_Connection_Status == APP_BLE_LP_CONNECTING) | ||||
|           { | ||||
|             /* Connection as client */ | ||||
| @ -301,71 +304,71 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt ) | ||||
|         aci_gap_pairing_complete_event_rp0 *pairing_complete; | ||||
| 
 | ||||
|       case EVT_BLUE_GAP_LIMITED_DISCOVERABLE:  | ||||
|         APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_LIMITED_DISCOVERABLE \n"); | ||||
|         APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_LIMITED_DISCOVERABLE \r\n"); | ||||
|           break; /* EVT_BLUE_GAP_LIMITED_DISCOVERABLE */ | ||||
|            | ||||
|       case EVT_BLUE_GAP_PASS_KEY_REQUEST:   | ||||
|         APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_PASS_KEY_REQUEST \n"); | ||||
|         APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_PASS_KEY_REQUEST \r\n"); | ||||
| 
 | ||||
|         aci_gap_pass_key_resp(BleApplicationContext.BleApplicationContext_legacy.connectionHandle,123456); | ||||
| 
 | ||||
|         APP_DBG_MSG("\r\n\r** aci_gap_pass_key_resp \n"); | ||||
|         APP_DBG_MSG("\r\n\r** aci_gap_pass_key_resp \r\n"); | ||||
|           break; /* EVT_BLUE_GAP_PASS_KEY_REQUEST */ | ||||
| 
 | ||||
|       case EVT_BLUE_GAP_AUTHORIZATION_REQUEST:     | ||||
|         APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_AUTHORIZATION_REQUEST \n"); | ||||
|         APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_AUTHORIZATION_REQUEST \r\n"); | ||||
|           break; /* EVT_BLUE_GAP_AUTHORIZATION_REQUEST */ | ||||
| 
 | ||||
|       case EVT_BLUE_GAP_SLAVE_SECURITY_INITIATED:    | ||||
|         APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_SLAVE_SECURITY_INITIATED \n"); | ||||
|         APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_SLAVE_SECURITY_INITIATED \r\n"); | ||||
|           break; /* EVT_BLUE_GAP_SLAVE_SECURITY_INITIATED */ | ||||
| 
 | ||||
|       case EVT_BLUE_GAP_BOND_LOST:     | ||||
|         APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_BOND_LOST \n"); | ||||
|         APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_BOND_LOST \r\n"); | ||||
|           aci_gap_allow_rebond(BleApplicationContext.BleApplicationContext_legacy.connectionHandle); | ||||
|         APP_DBG_MSG("\r\n\r** Send allow rebond \n"); | ||||
|         APP_DBG_MSG("\r\n\r** Send allow rebond \r\n"); | ||||
|           break; /* EVT_BLUE_GAP_BOND_LOST */ | ||||
| 
 | ||||
|       case EVT_BLUE_GAP_DEVICE_FOUND:   | ||||
|         APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_DEVICE_FOUND \n"); | ||||
|         APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_DEVICE_FOUND \r\n"); | ||||
|           break; /* EVT_BLUE_GAP_DEVICE_FOUND */ | ||||
| 
 | ||||
|       case EVT_BLUE_GAP_ADDR_NOT_RESOLVED: | ||||
|          APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_DEVICE_FOUND \n"); | ||||
|          APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_DEVICE_FOUND \r\n"); | ||||
|           break; /* EVT_BLUE_GAP_DEVICE_FOUND */ | ||||
|        | ||||
|       case (EVT_BLUE_GAP_KEYPRESS_NOTIFICATION): | ||||
|          APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_KEYPRESS_NOTIFICATION \n"); | ||||
|          APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_KEYPRESS_NOTIFICATION \r\n"); | ||||
|           break; /* EVT_BLUE_GAP_KEY_PRESS_NOTIFICATION */     | ||||
| 
 | ||||
|        case (EVT_BLUE_GAP_NUMERIC_COMPARISON_VALUE): | ||||
|           APP_DBG_MSG("numeric_value = %ld\n", | ||||
|           APP_DBG_MSG("numeric_value = %ld\r\n", | ||||
|                       ((aci_gap_numeric_comparison_value_event_rp0 *)(blue_evt->data))->Numeric_Value); | ||||
| 
 | ||||
|           APP_DBG_MSG("Hex_value = %lx\n", | ||||
|           APP_DBG_MSG("Hex_value = %lx\r\n", | ||||
|                       ((aci_gap_numeric_comparison_value_event_rp0 *)(blue_evt->data))->Numeric_Value); | ||||
| 
 | ||||
|           aci_gap_numeric_comparison_value_confirm_yesno(BleApplicationContext.BleApplicationContext_legacy.connectionHandle, 1); /* CONFIRM_YES = 1 */ | ||||
| 
 | ||||
|           APP_DBG_MSG("\r\n\r** aci_gap_numeric_comparison_value_confirm_yesno-->YES \n"); | ||||
|           APP_DBG_MSG("\r\n\r** aci_gap_numeric_comparison_value_confirm_yesno-->YES \r\n"); | ||||
|           break; | ||||
| 
 | ||||
|         case (EVT_BLUE_GAP_PAIRING_CMPLT): | ||||
|           { | ||||
|             pairing_complete = (aci_gap_pairing_complete_event_rp0*)blue_evt->data; | ||||
| 
 | ||||
|             APP_DBG_MSG("BLE_CTRL_App_Notification: EVT_BLUE_GAP_PAIRING_CMPLT, pairing_complete->Status = %d\n",pairing_complete->Status); | ||||
|             APP_DBG_MSG("BLE_CTRL_App_Notification: EVT_BLUE_GAP_PAIRING_CMPLT, pairing_complete->Status = %d\r\n",pairing_complete->Status); | ||||
|             if (pairing_complete->Status == 0) { | ||||
|               APP_DBG_MSG("\r\n\r** Pairing OK \n"); | ||||
|               APP_DBG_MSG("\r\n\r** Pairing OK \r\n"); | ||||
|             } else { | ||||
|               APP_DBG_MSG("\r\n\r** Pairing KO \n"); | ||||
|               APP_DBG_MSG("\r\n\r** Pairing KO \r\n"); | ||||
|             } | ||||
|           } | ||||
|           break; | ||||
| 
 | ||||
|       /* USER CODE END ecode */ | ||||
|         case EVT_BLUE_GAP_PROCEDURE_COMPLETE: | ||||
|           APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_PROCEDURE_COMPLETE \n"); | ||||
|           APP_DBG_MSG("\r\n\r** EVT_BLUE_GAP_PROCEDURE_COMPLETE \r\n"); | ||||
|           break; | ||||
|       } | ||||
|       break; /* EVT_VENDOR */ | ||||
| @ -385,9 +388,9 @@ void APP_BLE_Key_Button1_Action() { | ||||
|   tBleStatus ret = BLE_STATUS_INVALID_PARAMS; | ||||
|   ret = aci_gap_clear_security_db(); | ||||
|   if (ret == BLE_STATUS_SUCCESS) { | ||||
|     APP_DBG_MSG("Successfully aci_gap_clear_security_db()\n"); | ||||
|     APP_DBG_MSG("Successfully aci_gap_clear_security_db()\r\n"); | ||||
|   } else { | ||||
|     APP_DBG_MSG("aci_gap_clear_security_db() Failed , result: %d \n", ret); | ||||
|     APP_DBG_MSG("aci_gap_clear_security_db() Failed , result: %d \r\n", ret); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @ -397,7 +400,7 @@ void APP_BLE_Key_Button2_Action() { | ||||
|   if (ret == BLE_STATUS_SUCCESS) { | ||||
|     APP_DBG_MSG("Successfully aci_gap_slave_security_req()"); | ||||
|   } else { | ||||
|     APP_DBG_MSG("aci_gap_slave_security_req() Failed , result: %d \n", ret); | ||||
|     APP_DBG_MSG("aci_gap_slave_security_req() Failed , result: %d \r\n", ret); | ||||
|   } | ||||
| } | ||||
|    | ||||
| @ -406,23 +409,23 @@ void APP_BLE_Key_Button3_Action() { | ||||
|   tBleStatus ret = BLE_STATUS_INVALID_PARAMS; | ||||
|   ret = hci_le_read_phy(BleApplicationContext.BleApplicationContext_legacy.connectionHandle,&TX_PHY,&RX_PHY); | ||||
|   if (ret == BLE_STATUS_SUCCESS) { | ||||
|     APP_DBG_MSG("Read_PHY success \n"); | ||||
|     APP_DBG_MSG("PHY Param  TX= %d, RX= %d \n", TX_PHY, RX_PHY); | ||||
|     APP_DBG_MSG("Read_PHY success \r\n"); | ||||
|     APP_DBG_MSG("PHY Param  TX= %d, RX= %d \r\n", TX_PHY, RX_PHY); | ||||
|     if ((TX_PHY == TX_2M) && (RX_PHY == RX_2M)) { | ||||
|       APP_DBG_MSG("hci_le_set_phy PHY Param  TX= %d, RX= %d \n", TX_1M, RX_1M); | ||||
|       APP_DBG_MSG("hci_le_set_phy PHY Param  TX= %d, RX= %d \r\n", TX_1M, RX_1M); | ||||
|       ret = hci_le_set_phy(BleApplicationContext.BleApplicationContext_legacy.connectionHandle,ALL_PHYS_PREFERENCE,TX_1M,RX_1M,0); | ||||
|     } else { | ||||
|       APP_DBG_MSG("hci_le_set_phy PHY Param  TX= %d, RX= %d \n", TX_2M_PREFERRED, RX_2M_PREFERRED); | ||||
|       APP_DBG_MSG("hci_le_set_phy PHY Param  TX= %d, RX= %d \r\n", TX_2M_PREFERRED, RX_2M_PREFERRED); | ||||
|       ret = hci_le_set_phy(BleApplicationContext.BleApplicationContext_legacy.connectionHandle,ALL_PHYS_PREFERENCE,TX_2M_PREFERRED,RX_2M_PREFERRED,0); | ||||
|     }  | ||||
|   } else { | ||||
|     APP_DBG_MSG("Read conf not succeess \n"); | ||||
|     APP_DBG_MSG("Read conf not succeess \r\n"); | ||||
|   } | ||||
| 
 | ||||
|   if (ret == BLE_STATUS_SUCCESS) { | ||||
|     APP_DBG_MSG("set PHY cmd ok\n"); | ||||
|     APP_DBG_MSG("set PHY cmd ok\r\n"); | ||||
|   } else { | ||||
|     APP_DBG_MSG("set PHY cmd NOK\n"); | ||||
|     APP_DBG_MSG("set PHY cmd NOK\r\n"); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @ -538,7 +541,7 @@ static void Ble_Hci_Gap_Gatt_Init() { | ||||
| 
 | ||||
|     if (aci_gatt_update_char_value(gap_service_handle, gap_dev_name_char_handle, 0, strlen(name), (uint8_t *) name)) | ||||
|     { | ||||
|       BLE_DBG_SVCCTL_MSG("Device Name aci_gatt_update_char_value failed.\n"); | ||||
|       BLE_DBG_SVCCTL_MSG("Device Name aci_gatt_update_char_value failed.\r\n"); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| @ -548,7 +551,7 @@ static void Ble_Hci_Gap_Gatt_Init() { | ||||
|                                 2, | ||||
|                                 (uint8_t *)&appearance)) | ||||
|   { | ||||
|     BLE_DBG_SVCCTL_MSG("Appearance aci_gatt_update_char_value failed.\n"); | ||||
|     BLE_DBG_SVCCTL_MSG("Appearance aci_gatt_update_char_value failed.\r\n"); | ||||
|   } | ||||
|   /**
 | ||||
|    * Initialize Default PHY | ||||
| @ -613,7 +616,7 @@ static void Adv_Request(APP_BLE_ConnStatus_t New_Status) | ||||
|      */ | ||||
|     HW_TS_Stop(BleApplicationContext.Advertising_mgr_timer_Id); | ||||
| 
 | ||||
|     APP_DBG_MSG("First index in %d state \n", BleApplicationContext.Device_Connection_Status); | ||||
|     APP_DBG_MSG("First index in %d state \r\n", BleApplicationContext.Device_Connection_Status); | ||||
| 
 | ||||
|     if ((New_Status == APP_BLE_LP_ADV) | ||||
|         && ((BleApplicationContext.Device_Connection_Status == APP_BLE_FAST_ADV) | ||||
| @ -623,11 +626,11 @@ static void Adv_Request(APP_BLE_ConnStatus_t New_Status) | ||||
|       ret = aci_gap_set_non_discoverable(); | ||||
|       if (ret == BLE_STATUS_SUCCESS) | ||||
|       { | ||||
|         APP_DBG_MSG("Successfully Stopped Advertising \n"); | ||||
|         APP_DBG_MSG("Successfully Stopped Advertising \r\n"); | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         APP_DBG_MSG("Stop Advertising Failed , result: %d \n", ret); | ||||
|         APP_DBG_MSG("Stop Advertising Failed , result: %d \r\n", ret); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
| @ -650,17 +653,17 @@ static void Adv_Request(APP_BLE_ConnStatus_t New_Status) | ||||
|     ret = aci_gap_update_adv_data(sizeof(manuf_data), (uint8_t*) manuf_data); | ||||
|     if (ret == BLE_STATUS_SUCCESS) { | ||||
|       if (New_Status == APP_BLE_FAST_ADV) { | ||||
|         APP_DBG_MSG("Successfully Start Fast Advertising \n" ); | ||||
|         APP_DBG_MSG("Successfully Start Fast Advertising \r\n" ); | ||||
|         /* Start Timer to STOP ADV - TIMEOUT */ | ||||
|         HW_TS_Start(BleApplicationContext.Advertising_mgr_timer_Id, INITIAL_ADV_TIMEOUT); | ||||
|       } else { | ||||
|         APP_DBG_MSG("Successfully Start Low Power Advertising \n"); | ||||
|         APP_DBG_MSG("Successfully Start Low Power Advertising \r\n"); | ||||
|       } | ||||
|     } else { | ||||
|       if (New_Status == APP_BLE_FAST_ADV) { | ||||
|         APP_DBG_MSG("Start Fast Advertising Failed , result: %d \n", ret); | ||||
|         APP_DBG_MSG("Start Fast Advertising Failed , result: %d \r\n", ret); | ||||
|       } else { | ||||
|         APP_DBG_MSG("Start Low Power Advertising Failed , result: %d \n", ret); | ||||
|         APP_DBG_MSG("Start Low Power Advertising Failed , result: %d \r\n", ret); | ||||
|       } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
| #include "hw_if.h" | ||||
| #include "ble_bufsize.h" | ||||
| 
 | ||||
| #define CFG_TX_POWER                      (0x18) /* -0.15dBm */ | ||||
| #define CFG_TX_POWER                      (0x1F) /* +6dBm */ | ||||
| 
 | ||||
| /**
 | ||||
|  * Define Advertising parameters | ||||
| @ -21,7 +21,7 @@ | ||||
|  */ | ||||
| #define CFG_BONDING_MODE                 (1) | ||||
| #define CFG_FIXED_PIN                    (111111) | ||||
| #define CFG_USED_FIXED_PIN               (0) | ||||
| #define CFG_USED_FIXED_PIN               (1) | ||||
| #define CFG_ENCRYPTION_KEY_SIZE_MAX      (16) | ||||
| #define CFG_ENCRYPTION_KEY_SIZE_MIN      (8) | ||||
| 
 | ||||
| @ -367,12 +367,12 @@ typedef enum | ||||
| /**
 | ||||
|  * When set to 1, the traces are enabled in the BLE services | ||||
|  */ | ||||
| #define CFG_DEBUG_BLE_TRACE     0 | ||||
| #define CFG_DEBUG_BLE_TRACE     1 | ||||
| 
 | ||||
| /**
 | ||||
|  * Enable or Disable traces in application | ||||
|  */ | ||||
| #define CFG_DEBUG_APP_TRACE     0 | ||||
| #define CFG_DEBUG_APP_TRACE     1 | ||||
| 
 | ||||
| #if (CFG_DEBUG_APP_TRACE != 0) | ||||
| #define APP_DBG_MSG                 PRINT_MESG_DBG | ||||
|  | ||||
| @ -393,7 +393,7 @@ void DbgOutputTraces(  uint8_t *p_data, uint16_t size, void (*cb)(void) ) | ||||
| /* USER CODE END DbgOutputTraces */ | ||||
|   // HW_UART_Transmit_DMA(CFG_DEBUG_TRACE_UART, p_data, size, cb);
 | ||||
|   HAL_UART_Transmit(&DEBUG_UART, (uint8_t*)p_data, (uint16_t)size, HAL_MAX_DELAY); | ||||
| 
 | ||||
|   cb(); | ||||
| /* USER CODE END DbgOutputTraces */ | ||||
|   return; | ||||
| } | ||||
|  | ||||
| @ -40,14 +40,14 @@ extern UART_HandleTypeDef DEBUG_UART; | ||||
|  * Enable or Disable traces | ||||
|  * The raw data output is the hci binary packet format as specified by the BT specification * | ||||
|  */ | ||||
| #define TL_SHCI_CMD_DBG_EN      1   /* Reports System commands sent to CPU2 and the command response */ | ||||
| #define TL_SHCI_CMD_DBG_EN      0   /* Reports System commands sent to CPU2 and the command response */ | ||||
| #define TL_SHCI_CMD_DBG_RAW_EN  0   /* Reports raw data System commands sent to CPU2 and the command response */ | ||||
| #define TL_SHCI_EVT_DBG_EN      1   /* Reports System Asynchronous Events received from CPU2 */ | ||||
| #define TL_SHCI_EVT_DBG_EN      0   /* Reports System Asynchronous Events received from CPU2 */ | ||||
| #define TL_SHCI_EVT_DBG_RAW_EN  0   /* Reports raw data System Asynchronous Events received from CPU2 */ | ||||
| 
 | ||||
| #define TL_HCI_CMD_DBG_EN       1   /* Reports BLE command sent to CPU2 and the command response */ | ||||
| #define TL_HCI_CMD_DBG_EN       0   /* Reports BLE command sent to CPU2 and the command response */ | ||||
| #define TL_HCI_CMD_DBG_RAW_EN   0   /* Reports raw data BLE command sent to CPU2 and the command response */ | ||||
| #define TL_HCI_EVT_DBG_EN       1   /* Reports BLE Asynchronous Events received from CPU2 */ | ||||
| #define TL_HCI_EVT_DBG_EN       0   /* Reports BLE Asynchronous Events received from CPU2 */ | ||||
| #define TL_HCI_EVT_DBG_RAW_EN   0   /* Reports raw data BLE Asynchronous Events received from CPU2 */ | ||||
| 
 | ||||
| #define TL_MM_DBG_EN            1   /* Reports the informations of the buffer released to CPU2 */ | ||||
|  | ||||
| @ -1,7 +1,5 @@ | ||||
| TOOLCHAIN = arm | ||||
| 
 | ||||
| OPENOCD_OPTS	= -f interface/stlink.cfg -c "transport select hla_swd" -f ../debug/stm32wbx.cfg -c "stm32wbx.cpu configure -rtos auto" | ||||
| 
 | ||||
| BOOT_ADDRESS	= 0x08000000 | ||||
| FW_ADDRESS		= 0x08008000 | ||||
| OS_OFFSET		= 0x00008000 | ||||
| @ -16,6 +14,7 @@ FLASH_ADDRESS	= 0x08000000 | ||||
| CFLAGS			+= -DNO_BOOTLOADER | ||||
| endif | ||||
| 
 | ||||
| OPENOCD_OPTS	= -f interface/stlink.cfg -c "transport select hla_swd" -f ../debug/stm32wbx.cfg -c "stm32wbx.cpu configure -rtos auto" -c "init" | ||||
| BOOT_CFLAGS		= -DBOOT_ADDRESS=$(BOOT_ADDRESS) -DFW_ADDRESS=$(FW_ADDRESS) -DOS_OFFSET=$(OS_OFFSET) | ||||
| MCU_FLAGS		= -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard | ||||
| 
 | ||||
|  | ||||
| @ -11,6 +11,10 @@ OBJECTS += $(addprefix $(OBJ_DIR)/, $(notdir $(CPP_SOURCES:.cpp=.o))) | ||||
| # Generate dependencies
 | ||||
| DEPS = $(OBJECTS:.o=.d) | ||||
| 
 | ||||
| ifdef DFU_SERIAL | ||||
| 	DFU_OPTIONS += -S $(DFU_SERIAL) | ||||
| endif | ||||
| 
 | ||||
| $(shell test -d $(OBJ_DIR) || mkdir -p $(OBJ_DIR)) | ||||
| 
 | ||||
| BUILD_FLAGS_SHELL=\
 | ||||
| @ -59,7 +63,7 @@ $(OBJ_DIR)/flash: $(OBJ_DIR)/$(PROJECT).bin | ||||
| 	touch $@ | ||||
| 
 | ||||
| $(OBJ_DIR)/upload: $(OBJ_DIR)/$(PROJECT).bin | ||||
| 	dfu-util -D $(OBJ_DIR)/$(PROJECT).bin -a 0 -s $(FLASH_ADDRESS) -S $(DFU_SERIAL) | ||||
| 	dfu-util -D $(OBJ_DIR)/$(PROJECT).bin -a 0 -s $(FLASH_ADDRESS) $(DFU_OPTIONS) | ||||
| 	touch $@ | ||||
| 
 | ||||
| $(ASSETS): $(ASSETS_SOURCES) $(ASSETS_COMPILLER) | ||||
| @ -80,6 +84,9 @@ debug: flash | ||||
| 		-ex "compare-sections" \
 | ||||
| 		$(OBJ_DIR)/$(PROJECT).elf; \
 | ||||
| 
 | ||||
| openocd: | ||||
| 	openocd $(OPENOCD_OPTS) | ||||
| 
 | ||||
| bm_debug: flash | ||||
| 	set -m; blackmagic & echo $$! > $(OBJ_DIR)/agent.PID | ||||
| 	arm-none-eabi-gdb \
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 あく
						あく