diff --git a/ReadMe.md b/ReadMe.md index d0cfd6320..f3c1098ea 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -14,24 +14,14 @@ Our goal is to create nice and clean code with good documentation, to make it a Flipper Zero's firmware consists of three components: -- Core2 firmware set - proprietary components by ST: FUS + radio stack. -- Core1 Bootloader - controls basic hardware initialization and loads firmware -- Core1 Firmware - HAL + OS + Drivers + Applications +- Core2 firmware set - proprietary components by ST: FUS + radio stack. FUS is flashed at factory and you should never update it. +- Core1 Bootloader - controls basic hardware initialization and loads firmware. +- Core1 Firmware - HAL + OS + Drivers + Applications. All 3 of them must be flashed in order described. ## With STLink -### Core2 flashing procedures - -Prerequisites: - -- Linux / macOS -- Terminal -- STM32_Programmer_CLI added to $PATH - -One liner: `./flash_core2_ble.sh` - ### Core1 Bootloader + Firmware Prerequisites: @@ -41,13 +31,23 @@ Prerequisites: - [arm-gcc-none-eabi](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads) - openocd -One liner: `./flash_core1_main.sh` +One liner: `make flash` + +### Core2 flashing procedures + +Prerequisites: + +- Linux / macOS +- Terminal +- STM32_Programmer_CLI (v2.5.0) added to $PATH + +One liner: `make flash_radio` ## With USB DFU 1. Download latest [Firmware](https://update.flipperzero.one) -2. Reboot Flipper to Bootloader +2. Reboot Flipper to Bootloader - Press and hold `← Left` + `↩ Back` for reset - Release `↩ Back` and keep holding `← Left` until blue LED lights up - Release `← Left` @@ -61,9 +61,10 @@ One liner: `./flash_core1_main.sh` 1. Install [Docker Engine and Docker Compose](https://www.docker.com/get-started) 2. Prepare the container: - ```sh - docker-compose up -d - ``` + + ```sh + docker-compose up -d + ``` ## Compile everything diff --git a/applications/ibutton/ibutton-cli.cpp b/applications/ibutton/ibutton-cli.cpp index 3c26f5ecf..c87447662 100644 --- a/applications/ibutton/ibutton-cli.cpp +++ b/applications/ibutton/ibutton-cli.cpp @@ -255,7 +255,6 @@ void onewire_cli_search(Cli* cli) { printf("Search finished\r\n"); onewire.reset_search(); done = true; - return; } else { printf("Found: "); for(uint8_t i = 0; i < 8; i++) { diff --git a/applications/storage/storage-processing.c b/applications/storage/storage-processing.c index 0ab7f551a..8ae648aa9 100644 --- a/applications/storage/storage-processing.c +++ b/applications/storage/storage-processing.c @@ -377,7 +377,7 @@ static FS_Error storage_process_common_rename(Storage* app, const char* old, con StorageType type_old = storage_get_type_by_path(old); StorageType type_new = storage_get_type_by_path(new); - if(storage_type_is_not_valid(type_old) || storage_type_is_not_valid(type_old)) { + if(storage_type_is_not_valid(type_old) || storage_type_is_not_valid(type_new)) { ret = FSE_INVALID_NAME; } else { if(type_old != type_new) { diff --git a/applications/storage/storages/storage-ext.c b/applications/storage/storages/storage-ext.c index 51de76122..22724a743 100644 --- a/applications/storage/storages/storage-ext.c +++ b/applications/storage/storages/storage-ext.c @@ -512,7 +512,7 @@ static FS_Error storage_ext_common_fs_info( /******************* Init Storage *******************/ void storage_ext_init(StorageData* storage) { - SDData* sd_data = malloc(sizeof(SDData)); + SDData* sd_data = furi_alloc(sizeof(SDData)); sd_data->fs = &USERFatFS; sd_data->path = "0:/"; sd_data->sd_was_present = true; diff --git a/applications/subghz/subghz_cli.c b/applications/subghz/subghz_cli.c index cd6c6ac21..2578fb263 100644 --- a/applications/subghz/subghz_cli.c +++ b/applications/subghz/subghz_cli.c @@ -102,13 +102,13 @@ static void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context static void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { uint32_t frequency = 433920000; uint32_t key = 0x0074BADE; - size_t repeat = 10; + uint32_t repeat = 10; if(string_size(args)) { - int ret = sscanf(string_get_cstr(args), "%lx %lu %u", &key, &frequency, &repeat); + int ret = sscanf(string_get_cstr(args), "%lx %lu %lu", &key, &frequency, &repeat); if(ret != 3) { printf( - "sscanf returned %d, key: %lx, frequency: %lu, repeat: %u\r\n", + "sscanf returned %d, key: %lx, frequency: %lu, repeat: %lu\r\n", ret, key, frequency, @@ -128,7 +128,7 @@ static void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { } printf( - "Transmitting at %lu, key %lx, repeat %u. Press CTRL+C to stop\r\n", + "Transmitting at %lu, key %lx, repeat %lu. Press CTRL+C to stop\r\n", frequency, key, repeat); diff --git a/applications/subghz/subghz_i.c b/applications/subghz/subghz_i.c index c04cdb348..ea06aae71 100644 --- a/applications/subghz/subghz_i.c +++ b/applications/subghz/subghz_i.c @@ -41,8 +41,8 @@ bool subghz_get_preset_name(SubGhz* subghz, string_t preset) { case FuriHalSubGhzPreset2FSKDev476Async: preset_name = "FuriHalSubGhzPreset2FSKDev476Async"; break; - FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unknown preset"); default: + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unknown preset"); return false; break; } diff --git a/core/furi/record.c b/core/furi/record.c index 29e33cafe..fe75c7bc9 100644 --- a/core/furi/record.c +++ b/core/furi/record.c @@ -52,6 +52,24 @@ static void furi_record_unlock() { furi_check(osMutexRelease(furi_record->mutex) == osOK); } +bool furi_record_exists(const char* name) { + furi_assert(furi_record); + furi_assert(name); + + bool ret = false; + + string_t name_str; + string_init_set_str(name_str, name); + + furi_record_lock(); + ret = (FuriRecordDataDict_get(furi_record->records, name_str) != NULL); + furi_record_unlock(); + + string_clear(name_str); + + return ret; +} + void furi_record_create(const char* name, void* data) { furi_assert(furi_record); diff --git a/core/furi/record.h b/core/furi/record.h index d5d92deb6..2d5f2c490 100644 --- a/core/furi/record.h +++ b/core/furi/record.h @@ -15,6 +15,14 @@ extern "C" { */ void furi_record_init(); +/** Check if record exists + * + * @param name record name + * @note Thread safe. Create and destroy must be executed from the same + * thread. + */ +bool furi_record_exists(const char* name); + /** Create record * * @param name record name diff --git a/firmware/targets/f6/fatfs/stm32_adafruit_sd.c b/firmware/targets/f6/fatfs/stm32_adafruit_sd.c index 0d7ff4c0e..1c571d639 100644 --- a/firmware/targets/f6/fatfs/stm32_adafruit_sd.c +++ b/firmware/targets/f6/fatfs/stm32_adafruit_sd.c @@ -405,7 +405,7 @@ BSP_SD_ReadBlocks(uint32_t* pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint goto error; } - ptr = malloc(sizeof(uint8_t) * BlockSize); + ptr = furi_alloc(sizeof(uint8_t) * BlockSize); if(ptr == NULL) { goto error; } @@ -483,7 +483,7 @@ BSP_SD_WriteBlocks(uint32_t* pData, uint32_t WriteAddr, uint32_t NumOfBlocks, ui goto error; } - ptr = malloc(sizeof(uint8_t) * BlockSize); + ptr = furi_alloc(sizeof(uint8_t) * BlockSize); if(ptr == NULL) { goto error; } diff --git a/firmware/targets/f6/furi-hal/furi-hal-i2c.c b/firmware/targets/f6/furi-hal/furi-hal-i2c.c index 2fd5c5e38..3e64b3908 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-i2c.c +++ b/firmware/targets/f6/furi-hal/furi-hal-i2c.c @@ -46,38 +46,48 @@ bool furi_hal_i2c_tx( const uint8_t* data, uint8_t size, uint32_t timeout) { + furi_check(handle->bus->current_handle == handle); - uint32_t time_left = timeout; + furi_assert(timeout > 0); + bool ret = true; + uint32_t timeout_tick = osKernelGetTickCount() + timeout; - while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c)) - ; - - LL_I2C_HandleTransfer( - handle->bus->i2c, - address, - LL_I2C_ADDRSLAVE_7BIT, - size, - LL_I2C_MODE_AUTOEND, - LL_I2C_GENERATE_START_WRITE); - - while(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c) || size > 0) { - if(LL_I2C_IsActiveFlag_TXIS(handle->bus->i2c)) { - LL_I2C_TransmitData8(handle->bus->i2c, (*data)); - data++; - size--; - time_left = timeout; - } - - if(LL_SYSTICK_IsActiveCounterFlag()) { - if(--time_left == 0) { + do { + while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c)) { + if(osKernelGetTickCount() >= timeout_tick) { ret = false; break; } } - } - LL_I2C_ClearFlag_STOP(handle->bus->i2c); + if(!ret) { + break; + } + + LL_I2C_HandleTransfer( + handle->bus->i2c, + address, + LL_I2C_ADDRSLAVE_7BIT, + size, + LL_I2C_MODE_AUTOEND, + LL_I2C_GENERATE_START_WRITE); + + while(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c) || size > 0) { + if(LL_I2C_IsActiveFlag_TXIS(handle->bus->i2c)) { + LL_I2C_TransmitData8(handle->bus->i2c, (*data)); + data++; + size--; + } + + if(osKernelGetTickCount() >= timeout_tick) { + ret = false; + break; + } + } + + LL_I2C_ClearFlag_STOP(handle->bus->i2c); + } while(0); return ret; } @@ -88,38 +98,48 @@ bool furi_hal_i2c_rx( uint8_t* data, uint8_t size, uint32_t timeout) { + furi_check(handle->bus->current_handle == handle); - uint32_t time_left = timeout; + furi_assert(timeout > 0); + bool ret = true; + uint32_t timeout_tick = osKernelGetTickCount() + timeout; - while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c)) - ; - - LL_I2C_HandleTransfer( - handle->bus->i2c, - address, - LL_I2C_ADDRSLAVE_7BIT, - size, - LL_I2C_MODE_AUTOEND, - LL_I2C_GENERATE_START_READ); - - while(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c) || size > 0) { - if(LL_I2C_IsActiveFlag_RXNE(handle->bus->i2c)) { - *data = LL_I2C_ReceiveData8(handle->bus->i2c); - data++; - size--; - time_left = timeout; - } - - if(LL_SYSTICK_IsActiveCounterFlag()) { - if(--time_left == 0) { + do { + while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c)) { + if(osKernelGetTickCount() >= timeout_tick) { ret = false; break; } } - } - LL_I2C_ClearFlag_STOP(handle->bus->i2c); + if(!ret) { + break; + } + + LL_I2C_HandleTransfer( + handle->bus->i2c, + address, + LL_I2C_ADDRSLAVE_7BIT, + size, + LL_I2C_MODE_AUTOEND, + LL_I2C_GENERATE_START_READ); + + while(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c) || size > 0) { + if(LL_I2C_IsActiveFlag_RXNE(handle->bus->i2c)) { + *data = LL_I2C_ReceiveData8(handle->bus->i2c); + data++; + size--; + } + + if(osKernelGetTickCount() >= timeout_tick) { + ret = false; + break; + } + } + + LL_I2C_ClearFlag_STOP(handle->bus->i2c); + } while(0); return ret; } @@ -132,6 +152,7 @@ bool furi_hal_i2c_trx( uint8_t* rx_data, uint8_t rx_size, uint32_t timeout) { + if(furi_hal_i2c_tx(handle, address, tx_data, tx_size, timeout) && furi_hal_i2c_rx(handle, address, rx_data, rx_size, timeout)) { return true; diff --git a/firmware/targets/f6/furi-hal/furi-hal.c b/firmware/targets/f6/furi-hal/furi-hal.c index 491cdf0d3..d213af955 100644 --- a/firmware/targets/f6/furi-hal/furi-hal.c +++ b/firmware/targets/f6/furi-hal/furi-hal.c @@ -17,6 +17,9 @@ void furi_hal_init() { furi_hal_interrupt_init(); furi_hal_delay_init(); + // FreeRTOS glue + furi_hal_os_init(); + MX_GPIO_Init(); FURI_LOG_I(TAG, "GPIO OK"); @@ -56,9 +59,6 @@ void furi_hal_init() { furi_hal_bt_init(); furi_hal_compress_icon_init(); - // FreeRTOS glue - furi_hal_os_init(); - // FatFS driver initialization MX_FATFS_Init(); FURI_LOG_I(TAG, "FATFS OK"); diff --git a/firmware/targets/f7/fatfs/stm32_adafruit_sd.c b/firmware/targets/f7/fatfs/stm32_adafruit_sd.c index 0d7ff4c0e..1c571d639 100644 --- a/firmware/targets/f7/fatfs/stm32_adafruit_sd.c +++ b/firmware/targets/f7/fatfs/stm32_adafruit_sd.c @@ -405,7 +405,7 @@ BSP_SD_ReadBlocks(uint32_t* pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint goto error; } - ptr = malloc(sizeof(uint8_t) * BlockSize); + ptr = furi_alloc(sizeof(uint8_t) * BlockSize); if(ptr == NULL) { goto error; } @@ -483,7 +483,7 @@ BSP_SD_WriteBlocks(uint32_t* pData, uint32_t WriteAddr, uint32_t NumOfBlocks, ui goto error; } - ptr = malloc(sizeof(uint8_t) * BlockSize); + ptr = furi_alloc(sizeof(uint8_t) * BlockSize); if(ptr == NULL) { goto error; } diff --git a/firmware/targets/f7/furi-hal/furi-hal-i2c.c b/firmware/targets/f7/furi-hal/furi-hal-i2c.c index 2fd5c5e38..3e64b3908 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-i2c.c +++ b/firmware/targets/f7/furi-hal/furi-hal-i2c.c @@ -46,38 +46,48 @@ bool furi_hal_i2c_tx( const uint8_t* data, uint8_t size, uint32_t timeout) { + furi_check(handle->bus->current_handle == handle); - uint32_t time_left = timeout; + furi_assert(timeout > 0); + bool ret = true; + uint32_t timeout_tick = osKernelGetTickCount() + timeout; - while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c)) - ; - - LL_I2C_HandleTransfer( - handle->bus->i2c, - address, - LL_I2C_ADDRSLAVE_7BIT, - size, - LL_I2C_MODE_AUTOEND, - LL_I2C_GENERATE_START_WRITE); - - while(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c) || size > 0) { - if(LL_I2C_IsActiveFlag_TXIS(handle->bus->i2c)) { - LL_I2C_TransmitData8(handle->bus->i2c, (*data)); - data++; - size--; - time_left = timeout; - } - - if(LL_SYSTICK_IsActiveCounterFlag()) { - if(--time_left == 0) { + do { + while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c)) { + if(osKernelGetTickCount() >= timeout_tick) { ret = false; break; } } - } - LL_I2C_ClearFlag_STOP(handle->bus->i2c); + if(!ret) { + break; + } + + LL_I2C_HandleTransfer( + handle->bus->i2c, + address, + LL_I2C_ADDRSLAVE_7BIT, + size, + LL_I2C_MODE_AUTOEND, + LL_I2C_GENERATE_START_WRITE); + + while(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c) || size > 0) { + if(LL_I2C_IsActiveFlag_TXIS(handle->bus->i2c)) { + LL_I2C_TransmitData8(handle->bus->i2c, (*data)); + data++; + size--; + } + + if(osKernelGetTickCount() >= timeout_tick) { + ret = false; + break; + } + } + + LL_I2C_ClearFlag_STOP(handle->bus->i2c); + } while(0); return ret; } @@ -88,38 +98,48 @@ bool furi_hal_i2c_rx( uint8_t* data, uint8_t size, uint32_t timeout) { + furi_check(handle->bus->current_handle == handle); - uint32_t time_left = timeout; + furi_assert(timeout > 0); + bool ret = true; + uint32_t timeout_tick = osKernelGetTickCount() + timeout; - while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c)) - ; - - LL_I2C_HandleTransfer( - handle->bus->i2c, - address, - LL_I2C_ADDRSLAVE_7BIT, - size, - LL_I2C_MODE_AUTOEND, - LL_I2C_GENERATE_START_READ); - - while(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c) || size > 0) { - if(LL_I2C_IsActiveFlag_RXNE(handle->bus->i2c)) { - *data = LL_I2C_ReceiveData8(handle->bus->i2c); - data++; - size--; - time_left = timeout; - } - - if(LL_SYSTICK_IsActiveCounterFlag()) { - if(--time_left == 0) { + do { + while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c)) { + if(osKernelGetTickCount() >= timeout_tick) { ret = false; break; } } - } - LL_I2C_ClearFlag_STOP(handle->bus->i2c); + if(!ret) { + break; + } + + LL_I2C_HandleTransfer( + handle->bus->i2c, + address, + LL_I2C_ADDRSLAVE_7BIT, + size, + LL_I2C_MODE_AUTOEND, + LL_I2C_GENERATE_START_READ); + + while(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c) || size > 0) { + if(LL_I2C_IsActiveFlag_RXNE(handle->bus->i2c)) { + *data = LL_I2C_ReceiveData8(handle->bus->i2c); + data++; + size--; + } + + if(osKernelGetTickCount() >= timeout_tick) { + ret = false; + break; + } + } + + LL_I2C_ClearFlag_STOP(handle->bus->i2c); + } while(0); return ret; } @@ -132,6 +152,7 @@ bool furi_hal_i2c_trx( uint8_t* rx_data, uint8_t rx_size, uint32_t timeout) { + if(furi_hal_i2c_tx(handle, address, tx_data, tx_size, timeout) && furi_hal_i2c_rx(handle, address, rx_data, rx_size, timeout)) { return true; diff --git a/firmware/targets/f7/furi-hal/furi-hal.c b/firmware/targets/f7/furi-hal/furi-hal.c index 491cdf0d3..d213af955 100644 --- a/firmware/targets/f7/furi-hal/furi-hal.c +++ b/firmware/targets/f7/furi-hal/furi-hal.c @@ -17,6 +17,9 @@ void furi_hal_init() { furi_hal_interrupt_init(); furi_hal_delay_init(); + // FreeRTOS glue + furi_hal_os_init(); + MX_GPIO_Init(); FURI_LOG_I(TAG, "GPIO OK"); @@ -56,9 +59,6 @@ void furi_hal_init() { furi_hal_bt_init(); furi_hal_compress_icon_init(); - // FreeRTOS glue - furi_hal_os_init(); - // FatFS driver initialization MX_FATFS_Init(); FURI_LOG_I(TAG, "FATFS OK");