Merge remote-tracking branch 'origin/dev' into release-candidate
This commit is contained in:
commit
81e490117a
2
.github/actions/submit_sdk/action.yml
vendored
2
.github/actions/submit_sdk/action.yml
vendored
@ -58,7 +58,7 @@ runs:
|
||||
echo "API version is already released"
|
||||
exit 0
|
||||
fi
|
||||
if ! echo "${{ inputs.firmware-version }}" | grep -q "-rc" ; then
|
||||
if ! echo "${{ inputs.firmware-version }}" | grep -q -- "-rc" ; then
|
||||
SDK_ID=$(jq -r ._id found_sdk.json)
|
||||
echo "Marking SDK $SDK_ID as released"
|
||||
curl -X 'POST' \
|
||||
|
||||
@ -77,6 +77,8 @@ if GetOption("fullenv") or any(
|
||||
"${COPRO_DISCLAIMER}",
|
||||
"--obdata",
|
||||
'"${ROOT_DIR.abspath}/${COPRO_OB_DATA}"',
|
||||
"--stackversion",
|
||||
"${COPRO_CUBE_VERSION}",
|
||||
]
|
||||
dist_resource_arguments = [
|
||||
"-r",
|
||||
|
||||
16
applications/debug/ccid_test/application.fam
Normal file
16
applications/debug/ccid_test/application.fam
Normal file
@ -0,0 +1,16 @@
|
||||
App(
|
||||
appid="ccid_test",
|
||||
name="CCID Debug",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="ccid_test_app",
|
||||
cdefines=["CCID_TEST"],
|
||||
requires=[
|
||||
"gui",
|
||||
],
|
||||
provides=[
|
||||
"ccid_test",
|
||||
],
|
||||
stack_size=1 * 1024,
|
||||
order=120,
|
||||
fap_category="Debug",
|
||||
)
|
||||
159
applications/debug/ccid_test/ccid_test_app.c
Normal file
159
applications/debug/ccid_test/ccid_test_app.c
Normal file
@ -0,0 +1,159 @@
|
||||
#include <stdint.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#include <gui/view.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/gui.h>
|
||||
|
||||
#include "iso7816_t0_apdu.h"
|
||||
|
||||
typedef enum {
|
||||
EventTypeInput,
|
||||
} EventType;
|
||||
|
||||
typedef struct {
|
||||
Gui* gui;
|
||||
ViewPort* view_port;
|
||||
FuriMessageQueue* event_queue;
|
||||
FuriHalUsbCcidConfig ccid_cfg;
|
||||
} CcidTestApp;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
InputEvent input;
|
||||
};
|
||||
EventType type;
|
||||
} CcidTestAppEvent;
|
||||
|
||||
typedef enum {
|
||||
CcidTestSubmenuIndexInsertSmartcard,
|
||||
CcidTestSubmenuIndexRemoveSmartcard,
|
||||
CcidTestSubmenuIndexInsertSmartcardReader
|
||||
} SubmenuIndex;
|
||||
|
||||
void icc_power_on_callback(uint8_t* atrBuffer, uint32_t* atrlen, void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
iso7816_answer_to_reset(atrBuffer, atrlen);
|
||||
}
|
||||
|
||||
void xfr_datablock_callback(uint8_t* dataBlock, uint32_t* dataBlockLen, void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
struct ISO7816_Response_APDU responseAPDU;
|
||||
//class not supported
|
||||
responseAPDU.SW1 = 0x6E;
|
||||
responseAPDU.SW2 = 0x00;
|
||||
|
||||
iso7816_write_response_apdu(&responseAPDU, dataBlock, dataBlockLen);
|
||||
}
|
||||
|
||||
static const CcidCallbacks ccid_cb = {
|
||||
icc_power_on_callback,
|
||||
xfr_datablock_callback,
|
||||
};
|
||||
|
||||
static void ccid_test_app_render_callback(Canvas* canvas, void* ctx) {
|
||||
UNUSED(ctx);
|
||||
canvas_clear(canvas);
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str(canvas, 0, 10, "CCID Test App");
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str(canvas, 0, 63, "Hold [back] to exit");
|
||||
}
|
||||
|
||||
static void ccid_test_app__input_callback(InputEvent* input_event, void* ctx) {
|
||||
FuriMessageQueue* event_queue = ctx;
|
||||
|
||||
CcidTestAppEvent event;
|
||||
event.type = EventTypeInput;
|
||||
event.input = *input_event;
|
||||
furi_message_queue_put(event_queue, &event, FuriWaitForever);
|
||||
}
|
||||
|
||||
uint32_t ccid_test_exit(void* context) {
|
||||
UNUSED(context);
|
||||
return VIEW_NONE;
|
||||
}
|
||||
|
||||
CcidTestApp* ccid_test_app_alloc() {
|
||||
CcidTestApp* app = malloc(sizeof(CcidTestApp));
|
||||
|
||||
// Gui
|
||||
app->gui = furi_record_open(RECORD_GUI);
|
||||
|
||||
//viewport
|
||||
app->view_port = view_port_alloc();
|
||||
gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);
|
||||
view_port_draw_callback_set(app->view_port, ccid_test_app_render_callback, NULL);
|
||||
|
||||
//message queue
|
||||
app->event_queue = furi_message_queue_alloc(8, sizeof(CcidTestAppEvent));
|
||||
furi_check(app->event_queue);
|
||||
view_port_input_callback_set(app->view_port, ccid_test_app__input_callback, app->event_queue);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
void ccid_test_app_free(CcidTestApp* app) {
|
||||
furi_assert(app);
|
||||
|
||||
//message queue
|
||||
furi_message_queue_free(app->event_queue);
|
||||
|
||||
//view port
|
||||
gui_remove_view_port(app->gui, app->view_port);
|
||||
view_port_free(app->view_port);
|
||||
|
||||
// Close gui record
|
||||
furi_record_close(RECORD_GUI);
|
||||
app->gui = NULL;
|
||||
|
||||
// Free rest
|
||||
free(app);
|
||||
}
|
||||
|
||||
int32_t ccid_test_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
//setup view
|
||||
CcidTestApp* app = ccid_test_app_alloc();
|
||||
|
||||
//setup CCID USB
|
||||
// On linux: set VID PID using: /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist
|
||||
app->ccid_cfg.vid = 0x1234;
|
||||
app->ccid_cfg.pid = 0x5678;
|
||||
|
||||
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
|
||||
furi_hal_usb_unlock();
|
||||
furi_hal_ccid_set_callbacks((CcidCallbacks*)&ccid_cb);
|
||||
furi_check(furi_hal_usb_set_config(&usb_ccid, &app->ccid_cfg) == true);
|
||||
|
||||
//handle button events
|
||||
CcidTestAppEvent event;
|
||||
while(1) {
|
||||
FuriStatus event_status =
|
||||
furi_message_queue_get(app->event_queue, &event, FuriWaitForever);
|
||||
|
||||
if(event_status == FuriStatusOk) {
|
||||
if(event.type == EventTypeInput) {
|
||||
if(event.input.type == InputTypeLong && event.input.key == InputKeyBack) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
view_port_update(app->view_port);
|
||||
}
|
||||
|
||||
//tear down USB
|
||||
furi_hal_usb_set_config(usb_mode_prev, NULL);
|
||||
furi_hal_ccid_set_callbacks(NULL);
|
||||
|
||||
//teardown view
|
||||
ccid_test_app_free(app);
|
||||
return 0;
|
||||
}
|
||||
36
applications/debug/ccid_test/iso7816_t0_apdu.c
Normal file
36
applications/debug/ccid_test/iso7816_t0_apdu.c
Normal file
@ -0,0 +1,36 @@
|
||||
/* Implements rudimentary iso7816-3 support for APDU (T=0) */
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <furi.h>
|
||||
#include "iso7816_t0_apdu.h"
|
||||
|
||||
void iso7816_answer_to_reset(uint8_t* atrBuffer, uint32_t* atrlen) {
|
||||
//minimum valid ATR: https://smartcard-atr.apdu.fr/parse?ATR=3B+00
|
||||
uint8_t AtrBuffer[2] = {
|
||||
0x3B, //TS (direct convention)
|
||||
0x00 // T0 (Y(1): b0000, K: 0 (historical bytes))
|
||||
};
|
||||
*atrlen = 2;
|
||||
|
||||
memcpy(atrBuffer, AtrBuffer, sizeof(uint8_t) * (*atrlen));
|
||||
}
|
||||
|
||||
void iso7816_read_command_apdu(
|
||||
struct ISO7816_Command_APDU* command,
|
||||
const uint8_t* dataBuffer,
|
||||
uint32_t dataLen) {
|
||||
furi_assert(dataLen <= 4);
|
||||
command->CLA = dataBuffer[0];
|
||||
command->INS = dataBuffer[1];
|
||||
command->P1 = dataBuffer[2];
|
||||
command->P2 = dataBuffer[3];
|
||||
}
|
||||
|
||||
void iso7816_write_response_apdu(
|
||||
const struct ISO7816_Response_APDU* response,
|
||||
uint8_t* dataBuffer,
|
||||
uint32_t* dataLen) {
|
||||
dataBuffer[0] = response->SW1;
|
||||
dataBuffer[1] = response->SW2;
|
||||
*dataLen = 2;
|
||||
}
|
||||
32
applications/debug/ccid_test/iso7816_t0_apdu.h
Normal file
32
applications/debug/ccid_test/iso7816_t0_apdu.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef _ISO7816_T0_APDU_H_
|
||||
#define _ISO7816_T0_APDU_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct ISO7816_Command_APDU {
|
||||
//header
|
||||
uint8_t CLA;
|
||||
uint32_t INS;
|
||||
uint8_t P1;
|
||||
uint8_t P2;
|
||||
|
||||
//body
|
||||
uint8_t Nc;
|
||||
uint8_t Ne;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ISO7816_Response_APDU {
|
||||
uint8_t SW1;
|
||||
uint32_t SW2;
|
||||
} __attribute__((packed));
|
||||
|
||||
void iso7816_answer_to_reset(uint8_t* atrBuffer, uint32_t* atrlen);
|
||||
void iso7816_read_command_apdu(
|
||||
struct ISO7816_Command_APDU* command,
|
||||
const uint8_t* dataBuffer,
|
||||
uint32_t dataLen);
|
||||
void iso7816_write_response_apdu(
|
||||
const struct ISO7816_Response_APDU* response,
|
||||
uint8_t* dataBuffer,
|
||||
uint32_t* dataLen);
|
||||
#endif //_ISO7816_T0_APDU_H_
|
||||
@ -5,6 +5,11 @@
|
||||
#include "../minunit.h"
|
||||
|
||||
#define DATA_SIZE 4
|
||||
#define EEPROM_ADDRESS 0b10101000
|
||||
#define EEPROM_ADDRESS_HIGH (EEPROM_ADDRESS | 0b10)
|
||||
#define EEPROM_SIZE 512
|
||||
#define EEPROM_PAGE_SIZE 16
|
||||
#define EEPROM_WRITE_DELAY_MS 6
|
||||
|
||||
static void furi_hal_i2c_int_setup() {
|
||||
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
||||
@ -14,6 +19,14 @@ static void furi_hal_i2c_int_teardown() {
|
||||
furi_hal_i2c_release(&furi_hal_i2c_handle_power);
|
||||
}
|
||||
|
||||
static void furi_hal_i2c_ext_setup() {
|
||||
furi_hal_i2c_acquire(&furi_hal_i2c_handle_external);
|
||||
}
|
||||
|
||||
static void furi_hal_i2c_ext_teardown() {
|
||||
furi_hal_i2c_release(&furi_hal_i2c_handle_external);
|
||||
}
|
||||
|
||||
MU_TEST(furi_hal_i2c_int_1b) {
|
||||
bool ret = false;
|
||||
uint8_t data_one = 0;
|
||||
@ -103,14 +116,116 @@ MU_TEST(furi_hal_i2c_int_1b_fail) {
|
||||
mu_assert(data_one != 0, "9 invalid data");
|
||||
}
|
||||
|
||||
MU_TEST(furi_hal_i2c_int_ext_3b) {
|
||||
bool ret = false;
|
||||
uint8_t data_many[DATA_SIZE] = {0};
|
||||
|
||||
// 3 byte: read
|
||||
data_many[0] = LP5562_CHANNEL_BLUE_CURRENT_REGISTER;
|
||||
ret = furi_hal_i2c_tx_ext(
|
||||
&furi_hal_i2c_handle_power,
|
||||
LP5562_ADDRESS,
|
||||
false,
|
||||
data_many,
|
||||
1,
|
||||
FuriHalI2cBeginStart,
|
||||
FuriHalI2cEndAwaitRestart,
|
||||
LP5562_I2C_TIMEOUT);
|
||||
mu_assert(ret, "3 tx failed");
|
||||
|
||||
// Send a RESTART condition, then read the 3 bytes one after the other
|
||||
ret = furi_hal_i2c_rx_ext(
|
||||
&furi_hal_i2c_handle_power,
|
||||
LP5562_ADDRESS,
|
||||
false,
|
||||
data_many + 1,
|
||||
1,
|
||||
FuriHalI2cBeginRestart,
|
||||
FuriHalI2cEndPause,
|
||||
LP5562_I2C_TIMEOUT);
|
||||
mu_assert(ret, "4 rx failed");
|
||||
mu_assert(data_many[1] != 0, "4 invalid data");
|
||||
ret = furi_hal_i2c_rx_ext(
|
||||
&furi_hal_i2c_handle_power,
|
||||
LP5562_ADDRESS,
|
||||
false,
|
||||
data_many + 2,
|
||||
1,
|
||||
FuriHalI2cBeginResume,
|
||||
FuriHalI2cEndPause,
|
||||
LP5562_I2C_TIMEOUT);
|
||||
mu_assert(ret, "5 rx failed");
|
||||
mu_assert(data_many[2] != 0, "5 invalid data");
|
||||
ret = furi_hal_i2c_rx_ext(
|
||||
&furi_hal_i2c_handle_power,
|
||||
LP5562_ADDRESS,
|
||||
false,
|
||||
data_many + 3,
|
||||
1,
|
||||
FuriHalI2cBeginResume,
|
||||
FuriHalI2cEndStop,
|
||||
LP5562_I2C_TIMEOUT);
|
||||
mu_assert(ret, "6 rx failed");
|
||||
mu_assert(data_many[3] != 0, "6 invalid data");
|
||||
}
|
||||
|
||||
MU_TEST(furi_hal_i2c_ext_eeprom) {
|
||||
if(!furi_hal_i2c_is_device_ready(&furi_hal_i2c_handle_external, EEPROM_ADDRESS, 100)) {
|
||||
printf("no device connected, skipping\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
uint8_t buffer[EEPROM_SIZE] = {0};
|
||||
|
||||
for(size_t page = 0; page < (EEPROM_SIZE / EEPROM_PAGE_SIZE); ++page) {
|
||||
// Fill page buffer
|
||||
for(size_t page_byte = 0; page_byte < EEPROM_PAGE_SIZE; ++page_byte) {
|
||||
// Each byte is its position in the EEPROM modulo 256
|
||||
uint8_t byte = ((page * EEPROM_PAGE_SIZE) + page_byte) % 256;
|
||||
|
||||
buffer[page_byte] = byte;
|
||||
}
|
||||
|
||||
uint8_t address = (page < 16) ? EEPROM_ADDRESS : EEPROM_ADDRESS_HIGH;
|
||||
|
||||
ret = furi_hal_i2c_write_mem(
|
||||
&furi_hal_i2c_handle_external,
|
||||
address,
|
||||
page * EEPROM_PAGE_SIZE,
|
||||
buffer,
|
||||
EEPROM_PAGE_SIZE,
|
||||
20);
|
||||
|
||||
mu_assert(ret, "EEPROM write failed");
|
||||
furi_delay_ms(EEPROM_WRITE_DELAY_MS);
|
||||
}
|
||||
|
||||
ret = furi_hal_i2c_read_mem(
|
||||
&furi_hal_i2c_handle_external, EEPROM_ADDRESS, 0, buffer, EEPROM_SIZE, 100);
|
||||
|
||||
mu_assert(ret, "EEPROM read failed");
|
||||
|
||||
for(size_t pos = 0; pos < EEPROM_SIZE; ++pos) {
|
||||
mu_assert_int_eq(pos % 256, buffer[pos]);
|
||||
}
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(furi_hal_i2c_int_suite) {
|
||||
MU_SUITE_CONFIGURE(&furi_hal_i2c_int_setup, &furi_hal_i2c_int_teardown);
|
||||
MU_RUN_TEST(furi_hal_i2c_int_1b);
|
||||
MU_RUN_TEST(furi_hal_i2c_int_3b);
|
||||
MU_RUN_TEST(furi_hal_i2c_int_ext_3b);
|
||||
MU_RUN_TEST(furi_hal_i2c_int_1b_fail);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(furi_hal_i2c_ext_suite) {
|
||||
MU_SUITE_CONFIGURE(&furi_hal_i2c_ext_setup, &furi_hal_i2c_ext_teardown);
|
||||
MU_RUN_TEST(furi_hal_i2c_ext_eeprom);
|
||||
}
|
||||
|
||||
int run_minunit_test_furi_hal() {
|
||||
MU_RUN_SUITE(furi_hal_i2c_int_suite);
|
||||
MU_RUN_SUITE(furi_hal_i2c_ext_suite);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
||||
|
||||
@ -98,9 +98,9 @@ static bool subghz_decoder_test(const char* path, const char* name_decoder) {
|
||||
}
|
||||
subghz_file_encoder_worker_free(file_worker_encoder_handler);
|
||||
}
|
||||
FURI_LOG_T(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count);
|
||||
FURI_LOG_T(TAG, "Decoder count parse %d", subghz_test_decoder_count);
|
||||
if(furi_get_tick() - test_start > TEST_TIMEOUT) {
|
||||
printf("\033[0;31mTest decoder %s ERROR TimeOut\033[0m\r\n", name_decoder);
|
||||
printf("Test decoder %s ERROR TimeOut\r\n", name_decoder);
|
||||
return false;
|
||||
} else {
|
||||
return subghz_test_decoder_count ? true : false;
|
||||
@ -137,9 +137,9 @@ static bool subghz_decode_random_test(const char* path) {
|
||||
}
|
||||
subghz_file_encoder_worker_free(file_worker_encoder_handler);
|
||||
}
|
||||
FURI_LOG_D(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count);
|
||||
FURI_LOG_D(TAG, "Decoder count parse %d", subghz_test_decoder_count);
|
||||
if(furi_get_tick() - test_start > TEST_TIMEOUT * 10) {
|
||||
printf("\033[0;31mRandom test ERROR TimeOut\033[0m\r\n");
|
||||
printf("Random test ERROR TimeOut\r\n");
|
||||
return false;
|
||||
} else if(subghz_test_decoder_count == TEST_RANDOM_COUNT_PARSE) {
|
||||
return true;
|
||||
@ -200,10 +200,9 @@ static bool subghz_encoder_test(const char* path) {
|
||||
subghz_transmitter_free(transmitter);
|
||||
}
|
||||
flipper_format_free(fff_data_file);
|
||||
FURI_LOG_T(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count);
|
||||
FURI_LOG_T(TAG, "Decoder count parse %d", subghz_test_decoder_count);
|
||||
if(furi_get_tick() - test_start > TEST_TIMEOUT) {
|
||||
printf(
|
||||
"\033[0;31mTest encoder %s ERROR TimeOut\033[0m\r\n", furi_string_get_cstr(temp_str));
|
||||
printf("Test encoder %s ERROR TimeOut\r\n", furi_string_get_cstr(temp_str));
|
||||
subghz_test_decoder_count = 0;
|
||||
}
|
||||
furi_string_free(temp_str);
|
||||
|
||||
@ -43,6 +43,11 @@ GpioApp* gpio_app_alloc() {
|
||||
|
||||
app->notifications = furi_record_open(RECORD_NOTIFICATION);
|
||||
|
||||
// Dialog view
|
||||
app->dialog = dialog_ex_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, GpioAppViewExitConfirm, dialog_ex_get_view(app->dialog));
|
||||
|
||||
app->var_item_list = variable_item_list_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
@ -79,10 +84,12 @@ void gpio_app_free(GpioApp* app) {
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewUsbUart);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewUsbUartCfg);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewUsbUartCloseRpc);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewExitConfirm);
|
||||
variable_item_list_free(app->var_item_list);
|
||||
widget_free(app->widget);
|
||||
gpio_test_free(app->gpio_test);
|
||||
gpio_usb_uart_free(app->gpio_usb_uart);
|
||||
dialog_ex_free(app->dialog);
|
||||
|
||||
// View dispatcher
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include <notification/notification_messages.h>
|
||||
#include <gui/modules/variable_item_list.h>
|
||||
#include <gui/modules/widget.h>
|
||||
#include <gui/modules/dialog_ex.h>
|
||||
#include "views/gpio_test.h"
|
||||
#include "views/gpio_usb_uart.h"
|
||||
#include <assets_icons.h>
|
||||
@ -23,6 +24,7 @@ struct GpioApp {
|
||||
ViewDispatcher* view_dispatcher;
|
||||
SceneManager* scene_manager;
|
||||
Widget* widget;
|
||||
DialogEx* dialog;
|
||||
|
||||
VariableItemList* var_item_list;
|
||||
VariableItem* var_item_flow;
|
||||
@ -39,4 +41,5 @@ typedef enum {
|
||||
GpioAppViewUsbUart,
|
||||
GpioAppViewUsbUartCfg,
|
||||
GpioAppViewUsbUartCloseRpc,
|
||||
GpioAppViewExitConfirm,
|
||||
} GpioAppView;
|
||||
|
||||
@ -3,3 +3,4 @@ ADD_SCENE(gpio, test, Test)
|
||||
ADD_SCENE(gpio, usb_uart, UsbUart)
|
||||
ADD_SCENE(gpio, usb_uart_cfg, UsbUartCfg)
|
||||
ADD_SCENE(gpio, usb_uart_close_rpc, UsbUartCloseRpc)
|
||||
ADD_SCENE(gpio, exit_confirm, ExitConfirm)
|
||||
|
||||
44
applications/main/gpio/scenes/gpio_scene_exit_confirm.c
Normal file
44
applications/main/gpio/scenes/gpio_scene_exit_confirm.c
Normal file
@ -0,0 +1,44 @@
|
||||
#include "gpio_app_i.h"
|
||||
|
||||
void gpio_scene_exit_confirm_dialog_callback(DialogExResult result, void* context) {
|
||||
GpioApp* app = context;
|
||||
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, result);
|
||||
}
|
||||
|
||||
void gpio_scene_exit_confirm_on_enter(void* context) {
|
||||
GpioApp* app = context;
|
||||
DialogEx* dialog = app->dialog;
|
||||
|
||||
dialog_ex_set_context(dialog, app);
|
||||
dialog_ex_set_left_button_text(dialog, "Exit");
|
||||
dialog_ex_set_right_button_text(dialog, "Stay");
|
||||
dialog_ex_set_header(dialog, "Exit USB-UART?", 22, 12, AlignLeft, AlignTop);
|
||||
dialog_ex_set_result_callback(dialog, gpio_scene_exit_confirm_dialog_callback);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewExitConfirm);
|
||||
}
|
||||
|
||||
bool gpio_scene_exit_confirm_on_event(void* context, SceneManagerEvent event) {
|
||||
GpioApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == DialogExResultRight) {
|
||||
consumed = scene_manager_previous_scene(app->scene_manager);
|
||||
} else if(event.event == DialogExResultLeft) {
|
||||
scene_manager_search_and_switch_to_previous_scene(app->scene_manager, GpioSceneStart);
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void gpio_scene_exit_confirm_on_exit(void* context) {
|
||||
GpioApp* app = context;
|
||||
|
||||
// Clean view
|
||||
dialog_ex_reset(app->dialog);
|
||||
}
|
||||
@ -42,6 +42,9 @@ bool gpio_scene_usb_uart_on_event(void* context, SceneManagerEvent event) {
|
||||
scene_manager_set_scene_state(app->scene_manager, GpioSceneUsbUart, 1);
|
||||
scene_manager_next_scene(app->scene_manager, GpioSceneUsbUartCfg);
|
||||
return true;
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
scene_manager_next_scene(app->scene_manager, GpioSceneExitConfirm);
|
||||
return true;
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
uint32_t tx_cnt_last = scene_usb_uart->state.tx_cnt;
|
||||
uint32_t rx_cnt_last = scene_usb_uart->state.rx_cnt;
|
||||
|
||||
@ -290,6 +290,7 @@ void elements_multiline_text_aligned(
|
||||
} else if((y + font_height) > canvas_height(canvas)) {
|
||||
line = furi_string_alloc_printf("%.*s...\n", chars_fit, start);
|
||||
} else {
|
||||
chars_fit -= 1; // account for the dash
|
||||
line = furi_string_alloc_printf("%.*s-\n", chars_fit, start);
|
||||
}
|
||||
canvas_draw_str_aligned(canvas, x, y, horizontal, vertical, furi_string_get_cstr(line));
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
#include "gui.h"
|
||||
#include "gui_i.h"
|
||||
|
||||
#define TAG "ViewPort"
|
||||
|
||||
_Static_assert(ViewPortOrientationMAX == 4, "Incorrect ViewPortOrientation count");
|
||||
_Static_assert(
|
||||
(ViewPortOrientationHorizontal == 0 && ViewPortOrientationHorizontalFlip == 1 &&
|
||||
@ -174,9 +176,15 @@ void view_port_input_callback_set(
|
||||
|
||||
void view_port_update(ViewPort* view_port) {
|
||||
furi_assert(view_port);
|
||||
furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk);
|
||||
|
||||
// We are not going to lockup system, but will notify you instead
|
||||
// Make sure that you don't call viewport methods inside of another mutex, especially one that is used in draw call
|
||||
if(furi_mutex_acquire(view_port->mutex, 2) != FuriStatusOk) {
|
||||
FURI_LOG_W(TAG, "ViewPort lockup: see %s:%d", __FILE__, __LINE__ - 3);
|
||||
}
|
||||
|
||||
if(view_port->gui && view_port->is_enabled) gui_update(view_port->gui);
|
||||
furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk);
|
||||
furi_mutex_release(view_port->mutex);
|
||||
}
|
||||
|
||||
void view_port_gui_set(ViewPort* view_port, Gui* gui) {
|
||||
@ -189,14 +197,21 @@ void view_port_gui_set(ViewPort* view_port, Gui* gui) {
|
||||
void view_port_draw(ViewPort* view_port, Canvas* canvas) {
|
||||
furi_assert(view_port);
|
||||
furi_assert(canvas);
|
||||
furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk);
|
||||
|
||||
// We are not going to lockup system, but will notify you instead
|
||||
// Make sure that you don't call viewport methods inside of another mutex, especially one that is used in draw call
|
||||
if(furi_mutex_acquire(view_port->mutex, 2) != FuriStatusOk) {
|
||||
FURI_LOG_W(TAG, "ViewPort lockup: see %s:%d", __FILE__, __LINE__ - 3);
|
||||
}
|
||||
|
||||
furi_check(view_port->gui);
|
||||
|
||||
if(view_port->draw_callback) {
|
||||
view_port_setup_canvas_orientation(view_port, canvas);
|
||||
view_port->draw_callback(canvas, view_port->draw_callback_context);
|
||||
}
|
||||
furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk);
|
||||
|
||||
furi_mutex_release(view_port->mutex);
|
||||
}
|
||||
|
||||
void view_port_input(ViewPort* view_port, InputEvent* event) {
|
||||
|
||||
@ -424,4 +424,5 @@ command: 05 FA 00 00
|
||||
name: Next
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 87 7C 00 0
|
||||
address: 87 7C 00 00
|
||||
command: 06 F9 00 00
|
||||
|
||||
@ -56,6 +56,7 @@ The following parameters are used only for [FAPs](./AppsOnSDCard.md):
|
||||
- **fap_weburl**: string, may be empty. Application's homepage.
|
||||
- **fap_icon_assets**: string. If present, it defines a folder name to be used for gathering image assets for this application. These images will be preprocessed and built alongside the application. See [FAP assets](./AppsOnSDCard.md#fap-assets) for details.
|
||||
- **fap_extbuild**: provides support for parts of application sources to be built by external tools. Contains a list of `ExtFile(path="file name", command="shell command")` definitions. **`fbt`** will run the specified command for each file in the list.
|
||||
- **fal_embedded**: boolean, default `False`. Applies only to PLUGIN type. If `True`, the plugin will be embedded into host application's .fap file as a resource and extracted to `apps_assets/APPID` folder on its start. This allows plugins to be distributed as a part of the host application.
|
||||
|
||||
Note that commands are executed at the firmware root folder, and all intermediate files must be placed in an application's temporary build folder. For that, you can use pattern expansion by **`fbt`**: `${FAP_WORK_DIR}` will be replaced with the path to the application's temporary build folder, and `${FAP_SRC_DIR}` will be replaced with the path to the application's source folder. You can also use other variables defined internally by **`fbt`**.
|
||||
|
||||
|
||||
2
fbt
2
fbt
@ -25,7 +25,7 @@ if [ -z "$FBT_VERBOSE" ]; then
|
||||
fi
|
||||
|
||||
if [ -z "$FBT_NO_SYNC" ]; then
|
||||
if [ ! -d "$SCRIPT_PATH/.git" ]; then
|
||||
if [ ! -e "$SCRIPT_PATH/.git" ]; then
|
||||
echo "\".git\" directory not found, please clone repo via \"git clone\"";
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
@ -22,7 +22,7 @@ DIST_SUFFIX = "local"
|
||||
COPRO_OB_DATA = "scripts/ob.data"
|
||||
|
||||
# Must match lib/stm32wb_copro version
|
||||
COPRO_CUBE_VERSION = "1.15.0"
|
||||
COPRO_CUBE_VERSION = "1.17.2"
|
||||
|
||||
COPRO_CUBE_DIR = "lib/stm32wb_copro"
|
||||
|
||||
|
||||
@ -143,7 +143,7 @@ fwenv.PrepareApplicationsBuild()
|
||||
|
||||
# Build external apps + configure SDK
|
||||
if env["IS_BASE_FIRMWARE"]:
|
||||
fwenv.SetDefault(FBT_FAP_DEBUG_ELF_ROOT="${BUILD_DIR}/.extapps")
|
||||
fwenv.SetDefault(FBT_FAP_DEBUG_ELF_ROOT=fwenv["BUILD_DIR"].Dir(".extapps"))
|
||||
fwenv["FW_EXTAPPS"] = SConscript(
|
||||
"site_scons/extapps.scons",
|
||||
exports={"ENV": fwenv},
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,38.0,,
|
||||
Version,+,39.1,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
Header,+,applications/services/cli/cli_vcp.h,,
|
||||
@ -76,6 +76,7 @@ Header,+,firmware/targets/furi_hal_include/furi_hal_sd.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_speaker.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_spi.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_usb.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_ccid.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,,
|
||||
@ -105,6 +106,7 @@ Header,+,lib/libusb_stm32/inc/hid_usage_telephony.h,,
|
||||
Header,+,lib/libusb_stm32/inc/hid_usage_vr.h,,
|
||||
Header,-,lib/libusb_stm32/inc/stm32_compat.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_ccid.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_cdc.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_cdca.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_cdce.h,,
|
||||
@ -1008,6 +1010,9 @@ Function,+,furi_hal_bus_enable,void,FuriHalBus
|
||||
Function,+,furi_hal_bus_init_early,void,
|
||||
Function,+,furi_hal_bus_is_enabled,_Bool,FuriHalBus
|
||||
Function,+,furi_hal_bus_reset,void,FuriHalBus
|
||||
Function,+,furi_hal_ccid_ccid_insert_smartcard,void,
|
||||
Function,+,furi_hal_ccid_ccid_remove_smartcard,void,
|
||||
Function,+,furi_hal_ccid_set_callbacks,void,CcidCallbacks*
|
||||
Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t
|
||||
Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t
|
||||
Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t"
|
||||
@ -1020,8 +1025,10 @@ Function,+,furi_hal_clock_mco_disable,void,
|
||||
Function,+,furi_hal_clock_mco_enable,void,"FuriHalClockMcoSourceId, FuriHalClockMcoDivisorId"
|
||||
Function,-,furi_hal_clock_resume_tick,void,
|
||||
Function,-,furi_hal_clock_suspend_tick,void,
|
||||
Function,-,furi_hal_clock_switch_to_hsi,void,
|
||||
Function,-,furi_hal_clock_switch_to_pll,void,
|
||||
Function,-,furi_hal_clock_switch_hse2hsi,void,
|
||||
Function,-,furi_hal_clock_switch_hse2pll,_Bool,
|
||||
Function,-,furi_hal_clock_switch_hsi2hse,void,
|
||||
Function,-,furi_hal_clock_switch_pll2hse,_Bool,
|
||||
Function,+,furi_hal_console_disable,void,
|
||||
Function,+,furi_hal_console_enable,void,
|
||||
Function,+,furi_hal_console_init,void,
|
||||
@ -1103,14 +1110,16 @@ Function,-,furi_hal_i2c_deinit_early,void,
|
||||
Function,-,furi_hal_i2c_init,void,
|
||||
Function,-,furi_hal_i2c_init_early,void,
|
||||
Function,+,furi_hal_i2c_is_device_ready,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_read_mem,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t*, uint8_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_read_mem,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t*, size_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_read_reg_16,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint16_t*, uint32_t"
|
||||
Function,+,furi_hal_i2c_read_reg_8,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t*, uint32_t"
|
||||
Function,+,furi_hal_i2c_release,void,FuriHalI2cBusHandle*
|
||||
Function,+,furi_hal_i2c_rx,_Bool,"FuriHalI2cBusHandle*, const uint8_t, uint8_t*, const uint8_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_trx,_Bool,"FuriHalI2cBusHandle*, const uint8_t, const uint8_t*, const uint8_t, uint8_t*, const uint8_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_tx,_Bool,"FuriHalI2cBusHandle*, const uint8_t, const uint8_t*, const uint8_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_write_mem,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t*, uint8_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_rx,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t*, size_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_rx_ext,_Bool,"FuriHalI2cBusHandle*, uint16_t, _Bool, uint8_t*, size_t, FuriHalI2cBegin, FuriHalI2cEnd, uint32_t"
|
||||
Function,+,furi_hal_i2c_trx,_Bool,"FuriHalI2cBusHandle*, uint8_t, const uint8_t*, size_t, uint8_t*, size_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_tx,_Bool,"FuriHalI2cBusHandle*, uint8_t, const uint8_t*, size_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_tx_ext,_Bool,"FuriHalI2cBusHandle*, uint16_t, _Bool, const uint8_t*, size_t, FuriHalI2cBegin, FuriHalI2cEnd, uint32_t"
|
||||
Function,+,furi_hal_i2c_write_mem,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, const uint8_t*, size_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_write_reg_16,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint16_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_write_reg_8,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t, uint32_t"
|
||||
Function,+,furi_hal_info_get,void,"PropertyValueCallback, char, void*"
|
||||
@ -2688,6 +2697,7 @@ Variable,+,sequence_single_vibro,const NotificationSequence,
|
||||
Variable,+,sequence_solid_yellow,const NotificationSequence,
|
||||
Variable,+,sequence_success,const NotificationSequence,
|
||||
Variable,-,suboptarg,char*,
|
||||
Variable,+,usb_ccid,FuriHalUsbInterface,
|
||||
Variable,+,usb_cdc_dual,FuriHalUsbInterface,
|
||||
Variable,+,usb_cdc_single,FuriHalUsbInterface,
|
||||
Variable,+,usb_hid,FuriHalUsbInterface,
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,38.0,,
|
||||
Version,+,39.1,,
|
||||
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
@ -82,6 +82,7 @@ Header,+,firmware/targets/furi_hal_include/furi_hal_sd.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_speaker.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_spi.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_usb.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_ccid.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,,
|
||||
@ -123,6 +124,7 @@ Header,+,lib/libusb_stm32/inc/hid_usage_telephony.h,,
|
||||
Header,+,lib/libusb_stm32/inc/hid_usage_vr.h,,
|
||||
Header,-,lib/libusb_stm32/inc/stm32_compat.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_ccid.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_cdc.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_cdca.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_cdce.h,,
|
||||
@ -1079,6 +1081,9 @@ Function,+,furi_hal_bus_enable,void,FuriHalBus
|
||||
Function,+,furi_hal_bus_init_early,void,
|
||||
Function,+,furi_hal_bus_is_enabled,_Bool,FuriHalBus
|
||||
Function,+,furi_hal_bus_reset,void,FuriHalBus
|
||||
Function,+,furi_hal_ccid_ccid_insert_smartcard,void,
|
||||
Function,+,furi_hal_ccid_ccid_remove_smartcard,void,
|
||||
Function,+,furi_hal_ccid_set_callbacks,void,CcidCallbacks*
|
||||
Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t
|
||||
Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t
|
||||
Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t"
|
||||
@ -1091,8 +1096,10 @@ Function,+,furi_hal_clock_mco_disable,void,
|
||||
Function,+,furi_hal_clock_mco_enable,void,"FuriHalClockMcoSourceId, FuriHalClockMcoDivisorId"
|
||||
Function,-,furi_hal_clock_resume_tick,void,
|
||||
Function,-,furi_hal_clock_suspend_tick,void,
|
||||
Function,-,furi_hal_clock_switch_to_hsi,void,
|
||||
Function,-,furi_hal_clock_switch_to_pll,void,
|
||||
Function,-,furi_hal_clock_switch_hse2hsi,void,
|
||||
Function,-,furi_hal_clock_switch_hse2pll,_Bool,
|
||||
Function,-,furi_hal_clock_switch_hsi2hse,void,
|
||||
Function,-,furi_hal_clock_switch_pll2hse,_Bool,
|
||||
Function,+,furi_hal_console_disable,void,
|
||||
Function,+,furi_hal_console_enable,void,
|
||||
Function,+,furi_hal_console_init,void,
|
||||
@ -1174,14 +1181,16 @@ Function,-,furi_hal_i2c_deinit_early,void,
|
||||
Function,-,furi_hal_i2c_init,void,
|
||||
Function,-,furi_hal_i2c_init_early,void,
|
||||
Function,+,furi_hal_i2c_is_device_ready,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_read_mem,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t*, uint8_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_read_mem,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t*, size_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_read_reg_16,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint16_t*, uint32_t"
|
||||
Function,+,furi_hal_i2c_read_reg_8,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t*, uint32_t"
|
||||
Function,+,furi_hal_i2c_release,void,FuriHalI2cBusHandle*
|
||||
Function,+,furi_hal_i2c_rx,_Bool,"FuriHalI2cBusHandle*, const uint8_t, uint8_t*, const uint8_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_trx,_Bool,"FuriHalI2cBusHandle*, const uint8_t, const uint8_t*, const uint8_t, uint8_t*, const uint8_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_tx,_Bool,"FuriHalI2cBusHandle*, const uint8_t, const uint8_t*, const uint8_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_write_mem,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t*, uint8_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_rx,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t*, size_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_rx_ext,_Bool,"FuriHalI2cBusHandle*, uint16_t, _Bool, uint8_t*, size_t, FuriHalI2cBegin, FuriHalI2cEnd, uint32_t"
|
||||
Function,+,furi_hal_i2c_trx,_Bool,"FuriHalI2cBusHandle*, uint8_t, const uint8_t*, size_t, uint8_t*, size_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_tx,_Bool,"FuriHalI2cBusHandle*, uint8_t, const uint8_t*, size_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_tx_ext,_Bool,"FuriHalI2cBusHandle*, uint16_t, _Bool, const uint8_t*, size_t, FuriHalI2cBegin, FuriHalI2cEnd, uint32_t"
|
||||
Function,+,furi_hal_i2c_write_mem,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, const uint8_t*, size_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_write_reg_16,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint16_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_write_reg_8,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t, uint32_t"
|
||||
Function,+,furi_hal_ibutton_emulate_set_next,void,uint32_t
|
||||
@ -3475,6 +3484,7 @@ Variable,+,subghz_protocol_raw_decoder,const SubGhzProtocolDecoder,
|
||||
Variable,+,subghz_protocol_raw_encoder,const SubGhzProtocolEncoder,
|
||||
Variable,+,subghz_protocol_registry,const SubGhzProtocolRegistry,
|
||||
Variable,-,suboptarg,char*,
|
||||
Variable,+,usb_ccid,FuriHalUsbInterface,
|
||||
Variable,+,usb_cdc_dual,FuriHalUsbInterface,
|
||||
Variable,+,usb_cdc_single,FuriHalUsbInterface,
|
||||
Variable,+,usb_hid,FuriHalUsbInterface,
|
||||
|
||||
|
@ -1,30 +1,4 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : app_common.h
|
||||
* Description : App Common application configuration file for STM32WPAN Middleware.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef APP_COMMON_H
|
||||
#define APP_COMMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
@ -36,5 +10,3 @@ extern "C" {
|
||||
#include <tl.h>
|
||||
|
||||
#include "app_conf.h"
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,80 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "hw_conf.h"
|
||||
#include "hw_if.h"
|
||||
|
||||
#include <interface/patterns/ble_thread/hw.h>
|
||||
#include <ble/core/ble_bufsize.h>
|
||||
#include <ble/core/ble_defs.h>
|
||||
|
||||
#define CFG_TX_POWER (0x19) /* +0dBm */
|
||||
|
||||
#define CFG_IDENTITY_ADDRESS GAP_PUBLIC_ADDR
|
||||
|
||||
/**
|
||||
* Define Advertising parameters
|
||||
*/
|
||||
#define CFG_ADV_BD_ADDRESS (0x7257acd87a6c)
|
||||
#define CFG_FAST_CONN_ADV_INTERVAL_MIN (0x80) /**< 80ms */
|
||||
#define CFG_FAST_CONN_ADV_INTERVAL_MAX (0xa0) /**< 100ms */
|
||||
#define CFG_LP_CONN_ADV_INTERVAL_MIN (0x640) /**< 1s */
|
||||
#define CFG_LP_CONN_ADV_INTERVAL_MAX (0xfa0) /**< 2.5s */
|
||||
|
||||
/**
|
||||
* Define IO Authentication
|
||||
*/
|
||||
#define CFG_BONDING_MODE (1)
|
||||
#define CFG_FIXED_PIN (111111)
|
||||
#define CFG_USED_FIXED_PIN (1)
|
||||
#define CFG_USED_FIXED_PIN USE_FIXED_PIN_FOR_PAIRING_FORBIDDEN
|
||||
#define CFG_ENCRYPTION_KEY_SIZE_MAX (16)
|
||||
#define CFG_ENCRYPTION_KEY_SIZE_MIN (8)
|
||||
|
||||
/**
|
||||
* Define IO capabilities
|
||||
*/
|
||||
#define CFG_IO_CAPABILITY_DISPLAY_ONLY (0x00)
|
||||
#define CFG_IO_CAPABILITY_DISPLAY_YES_NO (0x01)
|
||||
#define CFG_IO_CAPABILITY_KEYBOARD_ONLY (0x02)
|
||||
#define CFG_IO_CAPABILITY_NO_INPUT_NO_OUTPUT (0x03)
|
||||
#define CFG_IO_CAPABILITY_KEYBOARD_DISPLAY (0x04)
|
||||
|
||||
#define CFG_IO_CAPABILITY CFG_IO_CAPABILITY_DISPLAY_YES_NO
|
||||
#define CFG_IO_CAPABILITY IO_CAP_DISPLAY_YES_NO
|
||||
|
||||
/**
|
||||
* Define MITM modes
|
||||
*/
|
||||
#define CFG_MITM_PROTECTION_NOT_REQUIRED (0x00)
|
||||
#define CFG_MITM_PROTECTION_REQUIRED (0x01)
|
||||
|
||||
#define CFG_MITM_PROTECTION CFG_MITM_PROTECTION_REQUIRED
|
||||
#define CFG_MITM_PROTECTION MITM_PROTECTION_REQUIRED
|
||||
|
||||
/**
|
||||
* Define Secure Connections Support
|
||||
*/
|
||||
#define CFG_SECURE_NOT_SUPPORTED (0x00)
|
||||
#define CFG_SECURE_OPTIONAL (0x01)
|
||||
#define CFG_SECURE_MANDATORY (0x02)
|
||||
|
||||
#define CFG_SC_SUPPORT CFG_SECURE_OPTIONAL
|
||||
|
||||
/**
|
||||
* Define Keypress Notification Support
|
||||
*/
|
||||
#define CFG_KEYPRESS_NOT_SUPPORTED (0x00)
|
||||
#define CFG_KEYPRESS_SUPPORTED (0x01)
|
||||
|
||||
#define CFG_KEYPRESS_NOTIFICATION_SUPPORT CFG_KEYPRESS_NOT_SUPPORTED
|
||||
|
||||
/**
|
||||
* Numeric Comparison Answers
|
||||
*/
|
||||
#define YES (0x01)
|
||||
#define NO (0x00)
|
||||
|
||||
/**
|
||||
* Device name configuration for Generic Access Service
|
||||
*/
|
||||
#define CFG_GAP_DEVICE_NAME "TEMPLATE"
|
||||
#define CFG_GAP_DEVICE_NAME_LENGTH (8)
|
||||
#define CFG_SC_SUPPORT SC_PAIRING_OPTIONAL
|
||||
|
||||
/**
|
||||
* Define PHY
|
||||
@ -87,42 +39,6 @@
|
||||
#define RX_1M 0x01
|
||||
#define RX_2M 0x02
|
||||
|
||||
/**
|
||||
* Identity root key used to derive LTK and CSRK
|
||||
*/
|
||||
#define CFG_BLE_IRK \
|
||||
{ \
|
||||
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, \
|
||||
0xf0 \
|
||||
}
|
||||
|
||||
/**
|
||||
* Encryption root key used to derive LTK and CSRK
|
||||
*/
|
||||
#define CFG_BLE_ERK \
|
||||
{ \
|
||||
0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, 0x21, 0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, \
|
||||
0x21 \
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN Generic_Parameters */
|
||||
/**
|
||||
* SMPS supply
|
||||
* SMPS not used when Set to 0
|
||||
* SMPS used when Set to 1
|
||||
*/
|
||||
#define CFG_USE_SMPS 1
|
||||
/* USER CODE END Generic_Parameters */
|
||||
|
||||
/**< specific parameters */
|
||||
/*****************************************************/
|
||||
|
||||
/**
|
||||
* AD Element - Group B Feature
|
||||
*/
|
||||
/* LSB - Second Byte */
|
||||
#define CFG_FEATURE_OTA_REBOOT (0x20)
|
||||
|
||||
/******************************************************************************
|
||||
* BLE Stack
|
||||
******************************************************************************/
|
||||
@ -203,7 +119,9 @@
|
||||
* 1 : external high speed crystal HSE/32/32
|
||||
* 0 : external low speed crystal ( no calibration )
|
||||
*/
|
||||
#define CFG_BLE_LSE_SOURCE 0
|
||||
#define CFG_BLE_LSE_SOURCE \
|
||||
SHCI_C2_BLE_INIT_CFG_BLE_LS_CLK_LSE | SHCI_C2_BLE_INIT_CFG_BLE_LS_OTHER_DEV | \
|
||||
SHCI_C2_BLE_INIT_CFG_BLE_LS_CALIB
|
||||
|
||||
/**
|
||||
* Start up time of the high speed (16 or 32 MHz) crystal oscillator in units of 625/256 us (~2.44 us)
|
||||
@ -253,8 +171,8 @@
|
||||
*/
|
||||
#define CFG_BLE_OPTIONS \
|
||||
(SHCI_C2_BLE_INIT_OPTIONS_LL_HOST | SHCI_C2_BLE_INIT_OPTIONS_WITH_SVC_CHANGE_DESC | \
|
||||
SHCI_C2_BLE_INIT_OPTIONS_DEVICE_NAME_RW | SHCI_C2_BLE_INIT_OPTIONS_NO_EXT_ADV | \
|
||||
SHCI_C2_BLE_INIT_OPTIONS_NO_CS_ALGO2 | SHCI_C2_BLE_INIT_OPTIONS_POWER_CLASS_2_3)
|
||||
SHCI_C2_BLE_INIT_OPTIONS_DEVICE_NAME_RO | SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV | \
|
||||
SHCI_C2_BLE_INIT_OPTIONS_CS_ALGO2 | SHCI_C2_BLE_INIT_OPTIONS_POWER_CLASS_2_3)
|
||||
|
||||
/**
|
||||
* Queue length of BLE Event
|
||||
@ -282,187 +200,3 @@
|
||||
255 /**< Set to 255 with the memory manager and the mailbox */
|
||||
|
||||
#define TL_BLE_EVENT_FRAME_SIZE (TL_EVT_HDR_SIZE + CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE)
|
||||
/******************************************************************************
|
||||
* UART interfaces
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Select UART interfaces
|
||||
*/
|
||||
#define CFG_DEBUG_TRACE_UART hw_uart1
|
||||
#define CFG_CONSOLE_MENU 0
|
||||
|
||||
/******************************************************************************
|
||||
* Low Power
|
||||
******************************************************************************/
|
||||
/**
|
||||
* When set to 1, the low power mode is enable
|
||||
* When set to 0, the device stays in RUN mode
|
||||
*/
|
||||
#define CFG_LPM_SUPPORTED 1
|
||||
|
||||
/******************************************************************************
|
||||
* Timer Server
|
||||
******************************************************************************/
|
||||
/**
|
||||
* CFG_RTC_WUCKSEL_DIVIDER: This sets the RTCCLK divider to the wakeup timer.
|
||||
* The lower is the value, the better is the power consumption and the accuracy of the timerserver
|
||||
* The higher is the value, the finest is the granularity
|
||||
*
|
||||
* CFG_RTC_ASYNCH_PRESCALER: This sets the asynchronous prescaler of the RTC. It should as high as possible ( to ouput
|
||||
* clock as low as possible) but the output clock should be equal or higher frequency compare to the clock feeding
|
||||
* the wakeup timer. A lower clock speed would impact the accuracy of the timer server.
|
||||
*
|
||||
* CFG_RTC_SYNCH_PRESCALER: This sets the synchronous prescaler of the RTC.
|
||||
* When the 1Hz calendar clock is required, it shall be sets according to other settings
|
||||
* When the 1Hz calendar clock is not needed, CFG_RTC_SYNCH_PRESCALER should be set to 0x7FFF (MAX VALUE)
|
||||
*
|
||||
* CFG_RTCCLK_DIVIDER_CONF:
|
||||
* Shall be set to either 0,2,4,8,16
|
||||
* When set to either 2,4,8,16, the 1Hhz calendar is supported
|
||||
* When set to 0, the user sets its own configuration
|
||||
*
|
||||
* The following settings are computed with LSI as input to the RTC
|
||||
*/
|
||||
#define CFG_RTCCLK_DIVIDER_CONF 0
|
||||
|
||||
#if(CFG_RTCCLK_DIVIDER_CONF == 0)
|
||||
/**
|
||||
* Custom configuration
|
||||
* It does not support 1Hz calendar
|
||||
* It divides the RTC CLK by 16
|
||||
*/
|
||||
#define CFG_RTCCLK_DIV (16)
|
||||
#define CFG_RTC_WUCKSEL_DIVIDER (0)
|
||||
#define CFG_RTC_ASYNCH_PRESCALER (CFG_RTCCLK_DIV - 1)
|
||||
#define CFG_RTC_SYNCH_PRESCALER (0x7FFF)
|
||||
|
||||
#else
|
||||
|
||||
#if(CFG_RTCCLK_DIVIDER_CONF == 2)
|
||||
/**
|
||||
* It divides the RTC CLK by 2
|
||||
*/
|
||||
#define CFG_RTC_WUCKSEL_DIVIDER (3)
|
||||
#endif
|
||||
|
||||
#if(CFG_RTCCLK_DIVIDER_CONF == 4)
|
||||
/**
|
||||
* It divides the RTC CLK by 4
|
||||
*/
|
||||
#define CFG_RTC_WUCKSEL_DIVIDER (2)
|
||||
#endif
|
||||
|
||||
#if(CFG_RTCCLK_DIVIDER_CONF == 8)
|
||||
/**
|
||||
* It divides the RTC CLK by 8
|
||||
*/
|
||||
#define CFG_RTC_WUCKSEL_DIVIDER (1)
|
||||
#endif
|
||||
|
||||
#if(CFG_RTCCLK_DIVIDER_CONF == 16)
|
||||
/**
|
||||
* It divides the RTC CLK by 16
|
||||
*/
|
||||
#define CFG_RTC_WUCKSEL_DIVIDER (0)
|
||||
#endif
|
||||
|
||||
#define CFG_RTCCLK_DIV CFG_RTCCLK_DIVIDER_CONF
|
||||
#define CFG_RTC_ASYNCH_PRESCALER (CFG_RTCCLK_DIV - 1)
|
||||
#define CFG_RTC_SYNCH_PRESCALER (DIVR(LSE_VALUE, (CFG_RTC_ASYNCH_PRESCALER + 1)) - 1)
|
||||
|
||||
#endif
|
||||
|
||||
/** tick timer value in us */
|
||||
#define CFG_TS_TICK_VAL DIVR((CFG_RTCCLK_DIV * 1000000), LSE_VALUE)
|
||||
|
||||
typedef enum {
|
||||
CFG_TIM_PROC_ID_ISR,
|
||||
/* USER CODE BEGIN CFG_TimProcID_t */
|
||||
|
||||
/* USER CODE END CFG_TimProcID_t */
|
||||
} CFG_TimProcID_t;
|
||||
|
||||
/******************************************************************************
|
||||
* Debug
|
||||
******************************************************************************/
|
||||
/**
|
||||
* When set, this resets some hw resources to set the device in the same state than the power up
|
||||
* The FW resets only register that may prevent the FW to run properly
|
||||
*
|
||||
* This shall be set to 0 in a final product
|
||||
*
|
||||
*/
|
||||
#define CFG_HW_RESET_BY_FW 0
|
||||
|
||||
/**
|
||||
* keep debugger enabled while in any low power mode when set to 1
|
||||
* should be set to 0 in production
|
||||
*/
|
||||
#define CFG_DEBUGGER_SUPPORTED 1
|
||||
|
||||
/**
|
||||
* When set to 1, the traces are enabled in the BLE services
|
||||
*/
|
||||
#define CFG_DEBUG_BLE_TRACE 0
|
||||
|
||||
/**
|
||||
* Enable or Disable traces in application
|
||||
*/
|
||||
#define CFG_DEBUG_APP_TRACE 0
|
||||
|
||||
#if(CFG_DEBUG_APP_TRACE != 0)
|
||||
#define APP_DBG_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define APP_DBG_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if((CFG_DEBUG_BLE_TRACE != 0) || (CFG_DEBUG_APP_TRACE != 0))
|
||||
#define CFG_DEBUG_TRACE 1
|
||||
#endif
|
||||
|
||||
#if(CFG_DEBUG_TRACE != 0)
|
||||
#undef CFG_LPM_SUPPORTED
|
||||
#undef CFG_DEBUGGER_SUPPORTED
|
||||
#define CFG_LPM_SUPPORTED 0
|
||||
#define CFG_DEBUGGER_SUPPORTED 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* When CFG_DEBUG_TRACE_FULL is set to 1, the trace are output with the API name, the file name and the line number
|
||||
* When CFG_DEBUG_TRACE_LIGHT is set to 1, only the debug message is output
|
||||
*
|
||||
* When both are set to 0, no trace are output
|
||||
* When both are set to 1, CFG_DEBUG_TRACE_FULL is selected
|
||||
*/
|
||||
#define CFG_DEBUG_TRACE_LIGHT 0
|
||||
#define CFG_DEBUG_TRACE_FULL 0
|
||||
|
||||
#if((CFG_DEBUG_TRACE != 0) && (CFG_DEBUG_TRACE_LIGHT == 0) && (CFG_DEBUG_TRACE_FULL == 0))
|
||||
#undef CFG_DEBUG_TRACE_FULL
|
||||
#undef CFG_DEBUG_TRACE_LIGHT
|
||||
#define CFG_DEBUG_TRACE_FULL 0
|
||||
#define CFG_DEBUG_TRACE_LIGHT 1
|
||||
#endif
|
||||
|
||||
#if(CFG_DEBUG_TRACE == 0)
|
||||
#undef CFG_DEBUG_TRACE_FULL
|
||||
#undef CFG_DEBUG_TRACE_LIGHT
|
||||
#define CFG_DEBUG_TRACE_FULL 0
|
||||
#define CFG_DEBUG_TRACE_LIGHT 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* When not set, the traces is looping on sending the trace over UART
|
||||
*/
|
||||
#define DBG_TRACE_USE_CIRCULAR_QUEUE 0
|
||||
|
||||
/**
|
||||
* max buffer Size to queue data traces and max data trace allowed.
|
||||
* Only Used if DBG_TRACE_USE_CIRCULAR_QUEUE is defined
|
||||
*/
|
||||
#define DBG_TRACE_MSG_QUEUE_SIZE 4096
|
||||
#define MAX_DBG_TRACE_MSG_SIZE 1024
|
||||
|
||||
#define CFG_OTP_BASE_ADDRESS OTP_AREA_BASE
|
||||
#define CFG_OTP_END_ADRESS OTP_AREA_END_ADDR
|
||||
|
||||
@ -6,6 +6,9 @@
|
||||
#include <utilities/dbg_trace.h>
|
||||
#include <utilities/utilities_common.h>
|
||||
|
||||
#include "stm32wbxx_ll_bus.h"
|
||||
#include "stm32wbxx_ll_pwr.h"
|
||||
|
||||
#include <furi_hal.h>
|
||||
|
||||
typedef PACKED_STRUCT {
|
||||
@ -108,10 +111,6 @@ static void APPD_SetCPU2GpioConfig(void);
|
||||
static void APPD_BleDtbCfg(void);
|
||||
|
||||
void APPD_Init() {
|
||||
#if(CFG_DEBUG_TRACE != 0)
|
||||
DbgTraceInit();
|
||||
#endif
|
||||
|
||||
APPD_SetCPU2GpioConfig();
|
||||
APPD_BleDtbCfg();
|
||||
}
|
||||
@ -252,13 +251,3 @@ static void APPD_BleDtbCfg(void) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if(CFG_DEBUG_TRACE != 0)
|
||||
void DbgOutputInit(void) {
|
||||
}
|
||||
|
||||
void DbgOutputTraces(uint8_t* p_data, uint16_t size, void (*cb)(void)) {
|
||||
furi_hal_console_tx(p_data, size);
|
||||
cb();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1,26 +1,4 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : app_debug.h
|
||||
* Description : Header for app_debug.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __APP_DEBUG_H
|
||||
#define __APP_DEBUG_H
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -32,7 +10,3 @@ void APPD_EnableCPU2(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__APP_DEBUG_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
@ -18,8 +18,8 @@ PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static TL_CmdPacket_t ble_app_cmd_buffer;
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint32_t ble_app_nvm[BLE_NVM_SRAM_SIZE];
|
||||
|
||||
_Static_assert(
|
||||
sizeof(SHCI_C2_Ble_Init_Cmd_Packet_t) == 57,
|
||||
"Ble stack config structure size mismatch (check new config options - last updated for v.1.15.0)");
|
||||
sizeof(SHCI_C2_Ble_Init_Cmd_Packet_t) == 58,
|
||||
"Ble stack config structure size mismatch (check new config options - last updated for v.1.17.2)");
|
||||
|
||||
typedef struct {
|
||||
FuriMutex* hci_mtx;
|
||||
@ -72,10 +72,13 @@ static const SHCI_C2_Ble_Init_Cmd_Packet_t ble_init_cmd_packet = {
|
||||
.rx_model_config = 1,
|
||||
/* New stack (13.3->15.0) */
|
||||
.max_adv_set_nbr = 1, // Only used if SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV is set
|
||||
.max_adv_data_len = 31, // Only used if SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV is set
|
||||
.max_adv_data_len = 1650, // Only used if SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV is set
|
||||
.tx_path_compens = 0, // RF TX Path Compensation, * 0.1 dB
|
||||
.rx_path_compens = 0, // RF RX Path Compensation, * 0.1 dB
|
||||
.ble_core_version = 11, // BLE Core Version: 11(5.2), 12(5.3)
|
||||
.ble_core_version = SHCI_C2_BLE_INIT_BLE_CORE_5_4,
|
||||
/*15.0->17.0*/
|
||||
.Options_extension = SHCI_C2_BLE_INIT_OPTIONS_ENHANCED_ATT_NOTSUPPORTED |
|
||||
SHCI_C2_BLE_INIT_OPTIONS_APPEARANCE_READONLY,
|
||||
}};
|
||||
|
||||
bool ble_app_init() {
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
bool ble_app_init();
|
||||
void ble_app_get_key_storage_buff(uint8_t** addr, uint16_t* size);
|
||||
void ble_app_thread_stop();
|
||||
|
||||
@ -1,51 +1,7 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : App/ble_conf.h
|
||||
* Description : Configuration file for BLE Middleware.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef BLE_CONF_H
|
||||
#define BLE_CONF_H
|
||||
#pragma once
|
||||
|
||||
#include "app_conf.h"
|
||||
|
||||
#ifndef __weak
|
||||
#define __weak __attribute__((weak))
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* BLE SERVICES CONFIGURATION
|
||||
* blesvc
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* This setting shall be set to '1' if the device needs to support the Peripheral Role
|
||||
* In the MS configuration, both BLE_CFG_PERIPHERAL and BLE_CFG_CENTRAL shall be set to '1'
|
||||
*/
|
||||
#define BLE_CFG_PERIPHERAL 1
|
||||
|
||||
/**
|
||||
* This setting shall be set to '1' if the device needs to support the Central Role
|
||||
* In the MS configuration, both BLE_CFG_PERIPHERAL and BLE_CFG_CENTRAL shall be set to '1'
|
||||
*/
|
||||
#define BLE_CFG_CENTRAL 0
|
||||
|
||||
/**
|
||||
* There is one handler per service enabled
|
||||
* Note: There is no handler for the Device Information Service
|
||||
@ -56,18 +12,3 @@
|
||||
#define BLE_CFG_SVC_MAX_NBR_CB 7
|
||||
|
||||
#define BLE_CFG_CLT_MAX_NBR_CB 0
|
||||
|
||||
/******************************************************************************
|
||||
* GAP Service - Apprearance
|
||||
******************************************************************************/
|
||||
|
||||
#define BLE_CFG_UNKNOWN_APPEARANCE (0)
|
||||
#define BLE_CFG_GAP_APPEARANCE (0x0086)
|
||||
|
||||
/******************************************************************************
|
||||
* Over The Air Feature (OTA) - STM Proprietary
|
||||
******************************************************************************/
|
||||
#define BLE_CFG_OTA_REBOOT_CHAR 0 /**< REBOOT OTA MODE CHARACTERISTIC */
|
||||
|
||||
#endif /*BLE_CONF_H */
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
@ -1,22 +1,4 @@
|
||||
/*****************************************************************************
|
||||
* @file ble_const.h
|
||||
* @author MDG
|
||||
* @brief This file contains the definitions which are compiler dependent.
|
||||
*****************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2018-2022 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef BLE_CONST_H__
|
||||
#define BLE_CONST_H__
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
@ -115,5 +97,3 @@ extern int hci_send_req(struct hci_request* req, uint8_t async);
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#endif /* BLE_CONST_H__ */
|
||||
|
||||
@ -1,199 +1 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : App/ble_dbg_conf.h
|
||||
* Description : Debug configuration file for BLE Middleware.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __BLE_DBG_CONF_H
|
||||
#define __BLE_DBG_CONF_H
|
||||
|
||||
/**
|
||||
* Enable or Disable traces from BLE
|
||||
*/
|
||||
|
||||
#define BLE_DBG_APP_EN 1
|
||||
#define BLE_DBG_DIS_EN 1
|
||||
#define BLE_DBG_HRS_EN 1
|
||||
#define BLE_DBG_SVCCTL_EN 1
|
||||
#define BLE_DBG_BLS_EN 1
|
||||
#define BLE_DBG_HTS_EN 1
|
||||
#define BLE_DBG_P2P_STM_EN 1
|
||||
|
||||
/**
|
||||
* Macro definition
|
||||
*/
|
||||
#if(BLE_DBG_APP_EN != 0)
|
||||
#define BLE_DBG_APP_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_APP_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_DIS_EN != 0)
|
||||
#define BLE_DBG_DIS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_DIS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_HRS_EN != 0)
|
||||
#define BLE_DBG_HRS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_HRS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_P2P_STM_EN != 0)
|
||||
#define BLE_DBG_P2P_STM_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_P2P_STM_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_TEMPLATE_STM_EN != 0)
|
||||
#define BLE_DBG_TEMPLATE_STM_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_TEMPLATE_STM_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_EDS_STM_EN != 0)
|
||||
#define BLE_DBG_EDS_STM_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_EDS_STM_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_LBS_STM_EN != 0)
|
||||
#define BLE_DBG_LBS_STM_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_LBS_STM_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_SVCCTL_EN != 0)
|
||||
#define BLE_DBG_SVCCTL_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_SVCCTL_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_CTS_EN != 0)
|
||||
#define BLE_DBG_CTS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_CTS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_HIDS_EN != 0)
|
||||
#define BLE_DBG_HIDS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_HIDS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_PASS_EN != 0)
|
||||
#define BLE_DBG_PASS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_PASS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_BLS_EN != 0)
|
||||
#define BLE_DBG_BLS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_BLS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_HTS_EN != 0)
|
||||
#define BLE_DBG_HTS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_HTS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_ANS_EN != 0)
|
||||
#define BLE_DBG_ANS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_ANS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_ESS_EN != 0)
|
||||
#define BLE_DBG_ESS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_ESS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_GLS_EN != 0)
|
||||
#define BLE_DBG_GLS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_GLS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_BAS_EN != 0)
|
||||
#define BLE_DBG_BAS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_BAS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_RTUS_EN != 0)
|
||||
#define BLE_DBG_RTUS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_RTUS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_HPS_EN != 0)
|
||||
#define BLE_DBG_HPS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_HPS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_TPS_EN != 0)
|
||||
#define BLE_DBG_TPS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_TPS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_LLS_EN != 0)
|
||||
#define BLE_DBG_LLS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_LLS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_IAS_EN != 0)
|
||||
#define BLE_DBG_IAS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_IAS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_WSS_EN != 0)
|
||||
#define BLE_DBG_WSS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_WSS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_LNS_EN != 0)
|
||||
#define BLE_DBG_LNS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_LNS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_SCPS_EN != 0)
|
||||
#define BLE_DBG_SCPS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_SCPS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_DTS_EN != 0)
|
||||
#define BLE_DBG_DTS_MSG PRINT_MESG_DBG
|
||||
#define BLE_DBG_DTS_BUF PRINT_LOG_BUFF_DBG
|
||||
#else
|
||||
#define BLE_DBG_DTS_MSG PRINT_NO_MESG
|
||||
#define BLE_DBG_DTS_BUF PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#endif /*__BLE_DBG_CONF_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
#pragma once
|
||||
|
||||
@ -32,7 +32,6 @@ static uint8_t ble_glue_ble_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_
|
||||
|
||||
typedef struct {
|
||||
FuriMutex* shci_mtx;
|
||||
FuriSemaphore* shci_sem;
|
||||
FuriThread* thread;
|
||||
BleGlueStatus status;
|
||||
BleGlueKeyStorageChangedCallback callback;
|
||||
@ -104,7 +103,6 @@ void ble_glue_init() {
|
||||
TL_Init();
|
||||
|
||||
ble_glue->shci_mtx = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
ble_glue->shci_sem = furi_semaphore_alloc(1, 0);
|
||||
|
||||
// FreeRTOS system task creation
|
||||
ble_glue->thread = furi_thread_alloc_ex("BleShciDriver", 1024, ble_glue_shci_thread, ble_glue);
|
||||
@ -393,7 +391,6 @@ void ble_glue_thread_stop() {
|
||||
furi_thread_free(ble_glue->thread);
|
||||
// Free resources
|
||||
furi_mutex_free(ble_glue->shci_mtx);
|
||||
furi_semaphore_free(ble_glue->shci_sem);
|
||||
ble_glue_clear_shared_memory();
|
||||
free(ble_glue);
|
||||
ble_glue = NULL;
|
||||
@ -427,22 +424,6 @@ void shci_notify_asynch_evt(void* pdata) {
|
||||
}
|
||||
}
|
||||
|
||||
void shci_cmd_resp_release(uint32_t flag) {
|
||||
UNUSED(flag);
|
||||
if(ble_glue) {
|
||||
furi_semaphore_release(ble_glue->shci_sem);
|
||||
}
|
||||
}
|
||||
|
||||
void shci_cmd_resp_wait(uint32_t timeout) {
|
||||
UNUSED(timeout);
|
||||
if(ble_glue) {
|
||||
furi_hal_power_insomnia_enter();
|
||||
furi_semaphore_acquire(ble_glue->shci_sem, FuriWaitForever);
|
||||
furi_hal_power_insomnia_exit();
|
||||
}
|
||||
}
|
||||
|
||||
bool ble_glue_reinit_c2() {
|
||||
return SHCI_C2_Reinit() == SHCI_Success;
|
||||
}
|
||||
|
||||
@ -1,22 +1,4 @@
|
||||
/*****************************************************************************
|
||||
* @file compiler.h
|
||||
* @author MDG
|
||||
* @brief This file contains the definitions which are compiler dependent.
|
||||
*****************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2018-2023 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef COMPILER_H__
|
||||
#define COMPILER_H__
|
||||
#pragma once
|
||||
|
||||
#ifndef __PACKED_STRUCT
|
||||
#define __PACKED_STRUCT PACKED(struct)
|
||||
@ -154,5 +136,3 @@
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* COMPILER_H__ */
|
||||
|
||||
81
firmware/targets/f7/ble_glue/hsem_map.h
Normal file
81
firmware/targets/f7/ble_glue/hsem_map.h
Normal file
@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************
|
||||
* Semaphores
|
||||
* THIS SHALL NO BE CHANGED AS THESE SEMAPHORES ARE USED AS WELL ON THE CM0+
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Index of the semaphore used the prevent conflicts after standby sleep.
|
||||
* Each CPUs takes this semaphore at standby wakeup until conflicting elements are restored.
|
||||
*/
|
||||
#define CFG_HW_PWR_STANDBY_SEMID 10
|
||||
/**
|
||||
* The CPU2 may be configured to store the Thread persistent data either in internal NVM storage on CPU2 or in
|
||||
* SRAM2 buffer provided by the user application. This can be configured with the system command SHCI_C2_Config()
|
||||
* When the CPU2 is requested to store persistent data in SRAM2, it can write data in this buffer at any time when needed.
|
||||
* In order to read consistent data with the CPU1 from the SRAM2 buffer, the flow should be:
|
||||
* + CPU1 takes CFG_HW_THREAD_NVM_SRAM_SEMID semaphore
|
||||
* + CPU1 reads all persistent data from SRAM2 (most of the time, the goal is to write these data into an NVM managed by CPU1)
|
||||
* + CPU1 releases CFG_HW_THREAD_NVM_SRAM_SEMID semaphore
|
||||
* CFG_HW_THREAD_NVM_SRAM_SEMID semaphore makes sure CPU2 does not update the persistent data in SRAM2 at the same time CPU1 is reading them.
|
||||
* There is no timing constraint on how long this semaphore can be kept.
|
||||
*/
|
||||
#define CFG_HW_THREAD_NVM_SRAM_SEMID 9
|
||||
|
||||
/**
|
||||
* The CPU2 may be configured to store the BLE persistent data either in internal NVM storage on CPU2 or in
|
||||
* SRAM2 buffer provided by the user application. This can be configured with the system command SHCI_C2_Config()
|
||||
* When the CPU2 is requested to store persistent data in SRAM2, it can write data in this buffer at any time when needed.
|
||||
* In order to read consistent data with the CPU1 from the SRAM2 buffer, the flow should be:
|
||||
* + CPU1 takes CFG_HW_BLE_NVM_SRAM_SEMID semaphore
|
||||
* + CPU1 reads all persistent data from SRAM2 (most of the time, the goal is to write these data into an NVM managed by CPU1)
|
||||
* + CPU1 releases CFG_HW_BLE_NVM_SRAM_SEMID semaphore
|
||||
* CFG_HW_BLE_NVM_SRAM_SEMID semaphore makes sure CPU2 does not update the persistent data in SRAM2 at the same time CPU1 is reading them.
|
||||
* There is no timing constraint on how long this semaphore can be kept.
|
||||
*/
|
||||
#define CFG_HW_BLE_NVM_SRAM_SEMID 8
|
||||
|
||||
/**
|
||||
* Index of the semaphore used by CPU2 to prevent the CPU1 to either write or erase data in flash
|
||||
* The CPU1 shall not either write or erase in flash when this semaphore is taken by the CPU2
|
||||
* When the CPU1 needs to either write or erase in flash, it shall first get the semaphore and release it just
|
||||
* after writing a raw (64bits data) or erasing one sector.
|
||||
* Once the Semaphore has been released, there shall be at least 1us before it can be taken again. This is required
|
||||
* to give the opportunity to CPU2 to take it.
|
||||
* On v1.4.0 and older CPU2 wireless firmware, this semaphore is unused and CPU2 is using PES bit.
|
||||
* By default, CPU2 is using the PES bit to protect its timing. The CPU1 may request the CPU2 to use the semaphore
|
||||
* instead of the PES bit by sending the system command SHCI_C2_SetFlashActivityControl()
|
||||
*/
|
||||
#define CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID 7
|
||||
|
||||
/**
|
||||
* Index of the semaphore used by CPU1 to prevent the CPU2 to either write or erase data in flash
|
||||
* In order to protect its timing, the CPU1 may get this semaphore to prevent the CPU2 to either
|
||||
* write or erase in flash (as this will stall both CPUs)
|
||||
* The PES bit shall not be used as this may stall the CPU2 in some cases.
|
||||
*/
|
||||
#define CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID 6
|
||||
|
||||
/**
|
||||
* Index of the semaphore used to manage the CLK48 clock configuration
|
||||
* When the USB is required, this semaphore shall be taken before configuring te CLK48 for USB
|
||||
* and should be released after the application switch OFF the clock when the USB is not used anymore
|
||||
* When using the RNG, it is good enough to use CFG_HW_RNG_SEMID to control CLK48.
|
||||
* More details in AN5289
|
||||
*/
|
||||
#define CFG_HW_CLK48_CONFIG_SEMID 5
|
||||
|
||||
/* Index of the semaphore used to manage the entry Stop Mode procedure */
|
||||
#define CFG_HW_ENTRY_STOP_MODE_SEMID 4
|
||||
|
||||
/* Index of the semaphore used to access the RCC */
|
||||
#define CFG_HW_RCC_SEMID 3
|
||||
|
||||
/* Index of the semaphore used to access the FLASH */
|
||||
#define CFG_HW_FLASH_SEMID 2
|
||||
|
||||
/* Index of the semaphore used to access the PKA */
|
||||
#define CFG_HW_PKA_SEMID 1
|
||||
|
||||
/* Index of the semaphore used to access the RNG */
|
||||
#define CFG_HW_RNG_SEMID 0
|
||||
@ -1,231 +0,0 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file hw_conf.h
|
||||
* @author MCD Application Team
|
||||
* @brief Configuration of hardware interface
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2019 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef HW_CONF_H
|
||||
#define HW_CONF_H
|
||||
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Semaphores
|
||||
* THIS SHALL NO BE CHANGED AS THESE SEMAPHORES ARE USED AS WELL ON THE CM0+
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Index of the semaphore used the prevent conflicts after standby sleep.
|
||||
* Each CPUs takes this semaphore at standby wakeup until conclicting elements are restored.
|
||||
*/
|
||||
#define CFG_HW_PWR_STANDBY_SEMID 10
|
||||
/**
|
||||
* The CPU2 may be configured to store the Thread persistent data either in internal NVM storage on CPU2 or in
|
||||
* SRAM2 buffer provided by the user application. This can be configured with the system command SHCI_C2_Config()
|
||||
* When the CPU2 is requested to store persistent data in SRAM2, it can write data in this buffer at any time when needed.
|
||||
* In order to read consistent data with the CPU1 from the SRAM2 buffer, the flow should be:
|
||||
* + CPU1 takes CFG_HW_THREAD_NVM_SRAM_SEMID semaphore
|
||||
* + CPU1 reads all persistent data from SRAM2 (most of the time, the goal is to write these data into an NVM managed by CPU1)
|
||||
* + CPU1 releases CFG_HW_THREAD_NVM_SRAM_SEMID semaphore
|
||||
* CFG_HW_THREAD_NVM_SRAM_SEMID semaphore makes sure CPU2 does not update the persistent data in SRAM2 at the same time CPU1 is reading them.
|
||||
* There is no timing constraint on how long this semaphore can be kept.
|
||||
*/
|
||||
#define CFG_HW_THREAD_NVM_SRAM_SEMID 9
|
||||
|
||||
/**
|
||||
* The CPU2 may be configured to store the BLE persistent data either in internal NVM storage on CPU2 or in
|
||||
* SRAM2 buffer provided by the user application. This can be configured with the system command SHCI_C2_Config()
|
||||
* When the CPU2 is requested to store persistent data in SRAM2, it can write data in this buffer at any time when needed.
|
||||
* In order to read consistent data with the CPU1 from the SRAM2 buffer, the flow should be:
|
||||
* + CPU1 takes CFG_HW_BLE_NVM_SRAM_SEMID semaphore
|
||||
* + CPU1 reads all persistent data from SRAM2 (most of the time, the goal is to write these data into an NVM managed by CPU1)
|
||||
* + CPU1 releases CFG_HW_BLE_NVM_SRAM_SEMID semaphore
|
||||
* CFG_HW_BLE_NVM_SRAM_SEMID semaphore makes sure CPU2 does not update the persistent data in SRAM2 at the same time CPU1 is reading them.
|
||||
* There is no timing constraint on how long this semaphore can be kept.
|
||||
*/
|
||||
#define CFG_HW_BLE_NVM_SRAM_SEMID 8
|
||||
|
||||
/**
|
||||
* Index of the semaphore used by CPU2 to prevent the CPU1 to either write or erase data in flash
|
||||
* The CPU1 shall not either write or erase in flash when this semaphore is taken by the CPU2
|
||||
* When the CPU1 needs to either write or erase in flash, it shall first get the semaphore and release it just
|
||||
* after writing a raw (64bits data) or erasing one sector.
|
||||
* Once the Semaphore has been released, there shall be at least 1us before it can be taken again. This is required
|
||||
* to give the opportunity to CPU2 to take it.
|
||||
* On v1.4.0 and older CPU2 wireless firmware, this semaphore is unused and CPU2 is using PES bit.
|
||||
* By default, CPU2 is using the PES bit to protect its timing. The CPU1 may request the CPU2 to use the semaphore
|
||||
* instead of the PES bit by sending the system command SHCI_C2_SetFlashActivityControl()
|
||||
*/
|
||||
#define CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID 7
|
||||
|
||||
/**
|
||||
* Index of the semaphore used by CPU1 to prevent the CPU2 to either write or erase data in flash
|
||||
* In order to protect its timing, the CPU1 may get this semaphore to prevent the CPU2 to either
|
||||
* write or erase in flash (as this will stall both CPUs)
|
||||
* The PES bit shall not be used as this may stall the CPU2 in some cases.
|
||||
*/
|
||||
#define CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID 6
|
||||
|
||||
/**
|
||||
* Index of the semaphore used to manage the CLK48 clock configuration
|
||||
* When the USB is required, this semaphore shall be taken before configuring te CLK48 for USB
|
||||
* and should be released after the application switch OFF the clock when the USB is not used anymore
|
||||
* When using the RNG, it is good enough to use CFG_HW_RNG_SEMID to control CLK48.
|
||||
* More details in AN5289
|
||||
*/
|
||||
#define CFG_HW_CLK48_CONFIG_SEMID 5
|
||||
|
||||
/* Index of the semaphore used to manage the entry Stop Mode procedure */
|
||||
#define CFG_HW_ENTRY_STOP_MODE_SEMID 4
|
||||
|
||||
/* Index of the semaphore used to access the RCC */
|
||||
#define CFG_HW_RCC_SEMID 3
|
||||
|
||||
/* Index of the semaphore used to access the FLASH */
|
||||
#define CFG_HW_FLASH_SEMID 2
|
||||
|
||||
/* Index of the semaphore used to access the PKA */
|
||||
#define CFG_HW_PKA_SEMID 1
|
||||
|
||||
/* Index of the semaphore used to access the RNG */
|
||||
#define CFG_HW_RNG_SEMID 0
|
||||
|
||||
/******************************************************************************
|
||||
* HW TIMER SERVER
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* The user may define the maximum number of virtual timers supported.
|
||||
* It shall not exceed 255
|
||||
*/
|
||||
#define CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER 6
|
||||
|
||||
/**
|
||||
* The user may define the priority in the NVIC of the RTC_WKUP interrupt handler that is used to manage the
|
||||
* wakeup timer.
|
||||
* This setting is the preemptpriority part of the NVIC.
|
||||
*/
|
||||
#define CFG_HW_TS_NVIC_RTC_WAKEUP_IT_PREEMPTPRIO \
|
||||
(configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1) /* FreeRTOS requirement */
|
||||
|
||||
/**
|
||||
* The user may define the priority in the NVIC of the RTC_WKUP interrupt handler that is used to manage the
|
||||
* wakeup timer.
|
||||
* This setting is the subpriority part of the NVIC. It does not exist on all processors. When it is not supported
|
||||
* on the CPU, the setting is ignored
|
||||
*/
|
||||
#define CFG_HW_TS_NVIC_RTC_WAKEUP_IT_SUBPRIO 0
|
||||
|
||||
/**
|
||||
* Define a critical section in the Timer server
|
||||
* The Timer server does not support the API to be nested
|
||||
* The Application shall either:
|
||||
* a) Ensure this will never happen
|
||||
* b) Define the critical section
|
||||
* The default implementations is masking all interrupts using the PRIMASK bit
|
||||
* The TimerServer driver uses critical sections to avoid context corruption. This is achieved with the macro
|
||||
* TIMER_ENTER_CRITICAL_SECTION and TIMER_EXIT_CRITICAL_SECTION. When CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION is set
|
||||
* to 1, all STM32 interrupts are masked with the PRIMASK bit of the CortexM CPU. It is possible to use the BASEPRI
|
||||
* register of the CortexM CPU to keep allowed some interrupts with high priority. In that case, the user shall
|
||||
* re-implement TIMER_ENTER_CRITICAL_SECTION and TIMER_EXIT_CRITICAL_SECTION and shall make sure that no TimerServer
|
||||
* API are called when the TIMER critical section is entered
|
||||
*/
|
||||
#define CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION 1
|
||||
|
||||
/**
|
||||
* This value shall reflect the maximum delay there could be in the application between the time the RTC interrupt
|
||||
* is generated by the Hardware and the time when the RTC interrupt handler is called. This time is measured in
|
||||
* number of RTCCLK ticks.
|
||||
* A relaxed timing would be 10ms
|
||||
* When the value is too short, the timerserver will not be able to count properly and all timeout may be random.
|
||||
* When the value is too long, the device may wake up more often than the most optimal configuration. However, the
|
||||
* impact on power consumption would be marginal (unless the value selected is extremely too long). It is strongly
|
||||
* recommended to select a value large enough to make sure it is not too short to ensure reliability of the system
|
||||
* as this will have marginal impact on low power mode
|
||||
*/
|
||||
#define CFG_HW_TS_RTC_HANDLER_MAX_DELAY (10 * (LSI_VALUE / 1000))
|
||||
|
||||
/**
|
||||
* Interrupt ID in the NVIC of the RTC Wakeup interrupt handler
|
||||
* It shall be type of IRQn_Type
|
||||
*/
|
||||
#define CFG_HW_TS_RTC_WAKEUP_HANDLER_ID RTC_WKUP_IRQn
|
||||
|
||||
/******************************************************************************
|
||||
* HW UART
|
||||
*****************************************************************************/
|
||||
#define CFG_HW_LPUART1_ENABLED 0
|
||||
#define CFG_HW_LPUART1_DMA_TX_SUPPORTED 0
|
||||
|
||||
#define CFG_HW_USART1_ENABLED 1
|
||||
#define CFG_HW_USART1_DMA_TX_SUPPORTED 1
|
||||
|
||||
/**
|
||||
* UART1
|
||||
*/
|
||||
#define CFG_HW_USART1_PREEMPTPRIORITY 0x0F
|
||||
#define CFG_HW_USART1_SUBPRIORITY 0
|
||||
|
||||
/** < The application shall check the selected source clock is enable */
|
||||
#define CFG_HW_USART1_SOURCE_CLOCK RCC_USART1CLKSOURCE_SYSCLK
|
||||
|
||||
#define CFG_HW_USART1_BAUDRATE 115200
|
||||
#define CFG_HW_USART1_WORDLENGTH UART_WORDLENGTH_8B
|
||||
#define CFG_HW_USART1_STOPBITS UART_STOPBITS_1
|
||||
#define CFG_HW_USART1_PARITY UART_PARITY_NONE
|
||||
#define CFG_HW_USART1_HWFLOWCTL UART_HWCONTROL_NONE
|
||||
#define CFG_HW_USART1_MODE UART_MODE_TX_RX
|
||||
#define CFG_HW_USART1_ADVFEATUREINIT UART_ADVFEATURE_NO_INIT
|
||||
#define CFG_HW_USART1_OVERSAMPLING UART_OVERSAMPLING_8
|
||||
|
||||
#define CFG_HW_USART1_TX_PORT_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE
|
||||
#define CFG_HW_USART1_TX_PORT GPIOB
|
||||
#define CFG_HW_USART1_TX_PIN GPIO_PIN_6
|
||||
#define CFG_HW_USART1_TX_MODE GPIO_MODE_AF_PP
|
||||
#define CFG_HW_USART1_TX_PULL GPIO_NOPULL
|
||||
#define CFG_HW_USART1_TX_SPEED GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define CFG_HW_USART1_TX_ALTERNATE GPIO_AF7_USART1
|
||||
|
||||
#define CFG_HW_USART1_RX_PORT_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE
|
||||
#define CFG_HW_USART1_RX_PORT GPIOB
|
||||
#define CFG_HW_USART1_RX_PIN GPIO_PIN_7
|
||||
#define CFG_HW_USART1_RX_MODE GPIO_MODE_AF_PP
|
||||
#define CFG_HW_USART1_RX_PULL GPIO_NOPULL
|
||||
#define CFG_HW_USART1_RX_SPEED GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define CFG_HW_USART1_RX_ALTERNATE GPIO_AF7_USART1
|
||||
|
||||
#define CFG_HW_USART1_CTS_PORT_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE
|
||||
#define CFG_HW_USART1_CTS_PORT GPIOA
|
||||
#define CFG_HW_USART1_CTS_PIN GPIO_PIN_11
|
||||
#define CFG_HW_USART1_CTS_MODE GPIO_MODE_AF_PP
|
||||
#define CFG_HW_USART1_CTS_PULL GPIO_PULLDOWN
|
||||
#define CFG_HW_USART1_CTS_SPEED GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define CFG_HW_USART1_CTS_ALTERNATE GPIO_AF7_USART1
|
||||
|
||||
#define CFG_HW_USART1_DMA_TX_PREEMPTPRIORITY 0x0F
|
||||
#define CFG_HW_USART1_DMA_TX_SUBPRIORITY 0
|
||||
|
||||
#define CFG_HW_USART1_DMAMUX_CLK_ENABLE __HAL_RCC_DMAMUX1_CLK_ENABLE
|
||||
#define CFG_HW_USART1_DMA_CLK_ENABLE __HAL_RCC_DMA2_CLK_ENABLE
|
||||
#define CFG_HW_USART1_TX_DMA_REQ DMA_REQUEST_USART1_TX
|
||||
#define CFG_HW_USART1_TX_DMA_CHANNEL DMA2_Channel4
|
||||
#define CFG_HW_USART1_TX_DMA_IRQn DMA2_Channel4_IRQn
|
||||
#define CFG_HW_USART1_DMA_TX_IRQHandler DMA2_Channel4_IRQHandler
|
||||
|
||||
#endif /*HW_CONF_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
@ -1,102 +0,0 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file hw_if.h
|
||||
* @author MCD Application Team
|
||||
* @brief Hardware Interface
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2019 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef HW_IF_H
|
||||
#define HW_IF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32wbxx.h"
|
||||
#include "stm32wbxx_ll_exti.h"
|
||||
#include "stm32wbxx_ll_system.h"
|
||||
#include "stm32wbxx_ll_rcc.h"
|
||||
#include "stm32wbxx_ll_ipcc.h"
|
||||
#include "stm32wbxx_ll_bus.h"
|
||||
#include "stm32wbxx_ll_pwr.h"
|
||||
#include "stm32wbxx_ll_cortex.h"
|
||||
#include "stm32wbxx_ll_utils.h"
|
||||
#include "stm32wbxx_ll_hsem.h"
|
||||
#include "stm32wbxx_ll_gpio.h"
|
||||
#include "stm32wbxx_ll_rtc.h"
|
||||
|
||||
#ifdef USE_STM32WBXX_USB_DONGLE
|
||||
#include "stm32wbxx_usb_dongle.h"
|
||||
#endif
|
||||
#ifdef USE_STM32WBXX_NUCLEO
|
||||
#include "stm32wbxx_nucleo.h"
|
||||
#endif
|
||||
#ifdef USE_X_NUCLEO_EPD
|
||||
#include "x_nucleo_epd.h"
|
||||
#endif
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/******************************************************************************
|
||||
* HW UART
|
||||
******************************************************************************/
|
||||
typedef enum {
|
||||
hw_uart1,
|
||||
hw_uart2,
|
||||
hw_lpuart1,
|
||||
} hw_uart_id_t;
|
||||
|
||||
typedef enum {
|
||||
hw_uart_ok,
|
||||
hw_uart_error,
|
||||
hw_uart_busy,
|
||||
hw_uart_to,
|
||||
} hw_status_t;
|
||||
|
||||
void HW_UART_Init(hw_uart_id_t hw_uart_id);
|
||||
void HW_UART_Receive_IT(
|
||||
hw_uart_id_t hw_uart_id,
|
||||
uint8_t* pData,
|
||||
uint16_t Size,
|
||||
void (*Callback)(void));
|
||||
void HW_UART_Transmit_IT(
|
||||
hw_uart_id_t hw_uart_id,
|
||||
uint8_t* pData,
|
||||
uint16_t Size,
|
||||
void (*Callback)(void));
|
||||
hw_status_t
|
||||
HW_UART_Transmit(hw_uart_id_t hw_uart_id, uint8_t* p_data, uint16_t size, uint32_t timeout);
|
||||
hw_status_t HW_UART_Transmit_DMA(
|
||||
hw_uart_id_t hw_uart_id,
|
||||
uint8_t* p_data,
|
||||
uint16_t size,
|
||||
void (*Callback)(void));
|
||||
void HW_UART_Interrupt_Handler(hw_uart_id_t hw_uart_id);
|
||||
void HW_UART_DMA_Interrupt_Handler(hw_uart_id_t hw_uart_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*HW_IF_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
@ -1,160 +1,52 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : Target/hw_ipcc.c
|
||||
* Description : Hardware IPCC source file for STM32WPAN Middleware.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "app_common.h"
|
||||
#include <interface/patterns/ble_thread/tl/mbox_def.h>
|
||||
#include <interface/patterns/ble_thread/hw.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
/* Global variables ---------------------------------------------------------*/
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
#define HW_IPCC_TX_PENDING(channel) \
|
||||
(!(LL_C1_IPCC_IsActiveFlag_CHx(IPCC, channel))) && (((~(IPCC->C1MR)) & ((channel) << 16U)))
|
||||
#define HW_IPCC_RX_PENDING(channel) \
|
||||
(LL_C2_IPCC_IsActiveFlag_CHx(IPCC, channel)) && (((~(IPCC->C1MR)) & ((channel) << 0U)))
|
||||
#include <stm32wbxx_ll_ipcc.h>
|
||||
#include <stm32wbxx_ll_pwr.h>
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
static void (*FreeBufCb)(void);
|
||||
#include <hsem_map.h>
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static void HW_IPCC_BLE_EvtHandler(void);
|
||||
static void HW_IPCC_BLE_AclDataEvtHandler(void);
|
||||
static void HW_IPCC_MM_FreeBufHandler(void);
|
||||
static void HW_IPCC_SYS_CmdEvtHandler(void);
|
||||
static void HW_IPCC_SYS_EvtHandler(void);
|
||||
static void HW_IPCC_TRACES_EvtHandler(void);
|
||||
#define HW_IPCC_TX_PENDING(channel) \
|
||||
((!(LL_C1_IPCC_IsActiveFlag_CHx(IPCC, channel))) && \
|
||||
LL_C1_IPCC_IsEnabledTransmitChannel(IPCC, channel))
|
||||
#define HW_IPCC_RX_PENDING(channel) \
|
||||
(LL_C2_IPCC_IsActiveFlag_CHx(IPCC, channel) && \
|
||||
LL_C1_IPCC_IsEnabledReceiveChannel(IPCC, channel))
|
||||
|
||||
#ifdef THREAD_WB
|
||||
static void HW_IPCC_OT_CmdEvtHandler(void);
|
||||
static void HW_IPCC_THREAD_NotEvtHandler(void);
|
||||
static void HW_IPCC_THREAD_CliNotEvtHandler(void);
|
||||
#endif
|
||||
static void (*FreeBufCb)();
|
||||
|
||||
#ifdef LLD_TESTS_WB
|
||||
static void HW_IPCC_LLDTESTS_ReceiveCliRspHandler(void);
|
||||
static void HW_IPCC_LLDTESTS_ReceiveM0CmdHandler(void);
|
||||
#endif
|
||||
#ifdef LLD_BLE_WB
|
||||
/*static void HW_IPCC_LLD_BLE_ReceiveCliRspHandler( void );*/
|
||||
static void HW_IPCC_LLD_BLE_ReceiveRspHandler(void);
|
||||
static void HW_IPCC_LLD_BLE_ReceiveM0CmdHandler(void);
|
||||
#endif
|
||||
static void HW_IPCC_BLE_EvtHandler();
|
||||
static void HW_IPCC_BLE_AclDataEvtHandler();
|
||||
static void HW_IPCC_MM_FreeBufHandler();
|
||||
static void HW_IPCC_SYS_CmdEvtHandler();
|
||||
static void HW_IPCC_SYS_EvtHandler();
|
||||
static void HW_IPCC_TRACES_EvtHandler();
|
||||
|
||||
#ifdef MAC_802_15_4_WB
|
||||
static void HW_IPCC_MAC_802_15_4_CmdEvtHandler(void);
|
||||
static void HW_IPCC_MAC_802_15_4_NotEvtHandler(void);
|
||||
#endif
|
||||
|
||||
#ifdef ZIGBEE_WB
|
||||
static void HW_IPCC_ZIGBEE_CmdEvtHandler(void);
|
||||
static void HW_IPCC_ZIGBEE_StackNotifEvtHandler(void);
|
||||
static void HW_IPCC_ZIGBEE_StackM0RequestHandler(void);
|
||||
#endif
|
||||
|
||||
/* Public function definition -----------------------------------------------*/
|
||||
|
||||
/******************************************************************************
|
||||
* INTERRUPT HANDLER
|
||||
******************************************************************************/
|
||||
void HW_IPCC_Rx_Handler(void) {
|
||||
void HW_IPCC_Rx_Handler() {
|
||||
if(HW_IPCC_RX_PENDING(HW_IPCC_SYSTEM_EVENT_CHANNEL)) {
|
||||
HW_IPCC_SYS_EvtHandler();
|
||||
}
|
||||
#ifdef MAC_802_15_4_WB
|
||||
else if(HW_IPCC_RX_PENDING(HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL)) {
|
||||
HW_IPCC_MAC_802_15_4_NotEvtHandler();
|
||||
}
|
||||
#endif /* MAC_802_15_4_WB */
|
||||
#ifdef THREAD_WB
|
||||
else if(HW_IPCC_RX_PENDING(HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL)) {
|
||||
HW_IPCC_THREAD_NotEvtHandler();
|
||||
} else if(HW_IPCC_RX_PENDING(HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL)) {
|
||||
HW_IPCC_THREAD_CliNotEvtHandler();
|
||||
}
|
||||
#endif /* THREAD_WB */
|
||||
#ifdef LLD_TESTS_WB
|
||||
else if(HW_IPCC_RX_PENDING(HW_IPCC_LLDTESTS_CLI_RSP_CHANNEL)) {
|
||||
HW_IPCC_LLDTESTS_ReceiveCliRspHandler();
|
||||
} else if(HW_IPCC_RX_PENDING(HW_IPCC_LLDTESTS_M0_CMD_CHANNEL)) {
|
||||
HW_IPCC_LLDTESTS_ReceiveM0CmdHandler();
|
||||
}
|
||||
#endif /* LLD_TESTS_WB */
|
||||
#ifdef LLD_BLE_WB
|
||||
else if(HW_IPCC_RX_PENDING(HW_IPCC_LLD_BLE_RSP_CHANNEL)) {
|
||||
HW_IPCC_LLD_BLE_ReceiveRspHandler();
|
||||
} else if(HW_IPCC_RX_PENDING(HW_IPCC_LLD_BLE_M0_CMD_CHANNEL)) {
|
||||
HW_IPCC_LLD_BLE_ReceiveM0CmdHandler();
|
||||
}
|
||||
#endif /* LLD_TESTS_WB */
|
||||
#ifdef ZIGBEE_WB
|
||||
else if(HW_IPCC_RX_PENDING(HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL)) {
|
||||
HW_IPCC_ZIGBEE_StackNotifEvtHandler();
|
||||
} else if(HW_IPCC_RX_PENDING(HW_IPCC_ZIGBEE_M0_REQUEST_CHANNEL)) {
|
||||
HW_IPCC_ZIGBEE_StackM0RequestHandler();
|
||||
}
|
||||
#endif /* ZIGBEE_WB */
|
||||
else if(HW_IPCC_RX_PENDING(HW_IPCC_BLE_EVENT_CHANNEL)) {
|
||||
} else if(HW_IPCC_RX_PENDING(HW_IPCC_BLE_EVENT_CHANNEL)) {
|
||||
HW_IPCC_BLE_EvtHandler();
|
||||
} else if(HW_IPCC_RX_PENDING(HW_IPCC_TRACES_CHANNEL)) {
|
||||
HW_IPCC_TRACES_EvtHandler();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_Tx_Handler(void) {
|
||||
void HW_IPCC_Tx_Handler() {
|
||||
if(HW_IPCC_TX_PENDING(HW_IPCC_SYSTEM_CMD_RSP_CHANNEL)) {
|
||||
HW_IPCC_SYS_CmdEvtHandler();
|
||||
}
|
||||
#ifdef MAC_802_15_4_WB
|
||||
else if(HW_IPCC_TX_PENDING(HW_IPCC_MAC_802_15_4_CMD_RSP_CHANNEL)) {
|
||||
HW_IPCC_MAC_802_15_4_CmdEvtHandler();
|
||||
}
|
||||
#endif /* MAC_802_15_4_WB */
|
||||
#ifdef THREAD_WB
|
||||
else if(HW_IPCC_TX_PENDING(HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL)) {
|
||||
HW_IPCC_OT_CmdEvtHandler();
|
||||
}
|
||||
#endif /* THREAD_WB */
|
||||
#ifdef LLD_TESTS_WB
|
||||
// No TX handler for LLD tests
|
||||
#endif /* LLD_TESTS_WB */
|
||||
#ifdef ZIGBEE_WB
|
||||
if(HW_IPCC_TX_PENDING(HW_IPCC_ZIGBEE_CMD_APPLI_CHANNEL)) {
|
||||
HW_IPCC_ZIGBEE_CmdEvtHandler();
|
||||
}
|
||||
#endif /* ZIGBEE_WB */
|
||||
else if(HW_IPCC_TX_PENDING(HW_IPCC_SYSTEM_CMD_RSP_CHANNEL)) {
|
||||
} else if(HW_IPCC_TX_PENDING(HW_IPCC_SYSTEM_CMD_RSP_CHANNEL)) {
|
||||
HW_IPCC_SYS_CmdEvtHandler();
|
||||
} else if(HW_IPCC_TX_PENDING(HW_IPCC_MM_RELEASE_BUFFER_CHANNEL)) {
|
||||
HW_IPCC_MM_FreeBufHandler();
|
||||
} else if(HW_IPCC_TX_PENDING(HW_IPCC_HCI_ACL_DATA_CHANNEL)) {
|
||||
HW_IPCC_BLE_AclDataEvtHandler();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
/******************************************************************************
|
||||
* GENERAL
|
||||
******************************************************************************/
|
||||
void HW_IPCC_Enable(void) {
|
||||
|
||||
void HW_IPCC_Enable() {
|
||||
/**
|
||||
* Such as IPCC IP available to the CPU2, it is required to keep the IPCC clock running
|
||||
when FUS is running on CPU2 and CPU1 enters deep sleep mode
|
||||
@ -177,11 +69,9 @@ void HW_IPCC_Enable(void) {
|
||||
__SEV(); /* Set the internal event flag and send an event to the CPU2 */
|
||||
__WFE(); /* Clear the internal event flag */
|
||||
LL_PWR_EnableBootC2();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_Init(void) {
|
||||
void HW_IPCC_Init() {
|
||||
LL_C1_IPCC_EnableIT_RXO(IPCC);
|
||||
LL_C1_IPCC_EnableIT_TXF(IPCC);
|
||||
|
||||
@ -189,366 +79,62 @@ void HW_IPCC_Init(void) {
|
||||
NVIC_EnableIRQ(IPCC_C1_RX_IRQn);
|
||||
NVIC_SetPriority(IPCC_C1_TX_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 6, 0));
|
||||
NVIC_EnableIRQ(IPCC_C1_TX_IRQn);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* BLE
|
||||
******************************************************************************/
|
||||
void HW_IPCC_BLE_Init(void) {
|
||||
void HW_IPCC_BLE_Init() {
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_BLE_EVENT_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_BLE_SendCmd(void) {
|
||||
void HW_IPCC_BLE_SendCmd() {
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_BLE_CMD_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_BLE_EvtHandler(void) {
|
||||
static void HW_IPCC_BLE_EvtHandler() {
|
||||
HW_IPCC_BLE_RxEvtNot();
|
||||
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_BLE_EVENT_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_BLE_SendAclData(void) {
|
||||
void HW_IPCC_BLE_SendAclData() {
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_HCI_ACL_DATA_CHANNEL);
|
||||
LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_HCI_ACL_DATA_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_BLE_AclDataEvtHandler(void) {
|
||||
static void HW_IPCC_BLE_AclDataEvtHandler() {
|
||||
LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_HCI_ACL_DATA_CHANNEL);
|
||||
|
||||
HW_IPCC_BLE_AclDataAckNot();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
__weak void HW_IPCC_BLE_AclDataAckNot(void){};
|
||||
__weak void HW_IPCC_BLE_RxEvtNot(void){};
|
||||
|
||||
/******************************************************************************
|
||||
* SYSTEM
|
||||
******************************************************************************/
|
||||
void HW_IPCC_SYS_Init(void) {
|
||||
void HW_IPCC_SYS_Init() {
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_SYSTEM_EVENT_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_SYS_SendCmd(void) {
|
||||
void HW_IPCC_SYS_SendCmd() {
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_SYSTEM_CMD_RSP_CHANNEL);
|
||||
LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_SYSTEM_CMD_RSP_CHANNEL);
|
||||
|
||||
return;
|
||||
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(33000000);
|
||||
|
||||
while(LL_C1_IPCC_IsActiveFlag_CHx(IPCC, HW_IPCC_SYSTEM_CMD_RSP_CHANNEL)) {
|
||||
furi_check(!furi_hal_cortex_timer_is_expired(timer), "HW_IPCC_SYS_SendCmd timeout");
|
||||
}
|
||||
|
||||
HW_IPCC_SYS_CmdEvtHandler();
|
||||
}
|
||||
|
||||
static void HW_IPCC_SYS_CmdEvtHandler(void) {
|
||||
static void HW_IPCC_SYS_CmdEvtHandler() {
|
||||
LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_SYSTEM_CMD_RSP_CHANNEL);
|
||||
|
||||
HW_IPCC_SYS_CmdEvtNot();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_SYS_EvtHandler(void) {
|
||||
static void HW_IPCC_SYS_EvtHandler() {
|
||||
HW_IPCC_SYS_EvtNot();
|
||||
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_SYSTEM_EVENT_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
__weak void HW_IPCC_SYS_CmdEvtNot(void){};
|
||||
__weak void HW_IPCC_SYS_EvtNot(void){};
|
||||
|
||||
/******************************************************************************
|
||||
* MAC 802.15.4
|
||||
******************************************************************************/
|
||||
#ifdef MAC_802_15_4_WB
|
||||
void HW_IPCC_MAC_802_15_4_Init(void) {
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_MAC_802_15_4_SendCmd(void) {
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_MAC_802_15_4_CMD_RSP_CHANNEL);
|
||||
LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_MAC_802_15_4_CMD_RSP_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_MAC_802_15_4_SendAck(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_MAC_802_15_4_CmdEvtHandler(void) {
|
||||
LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_MAC_802_15_4_CMD_RSP_CHANNEL);
|
||||
|
||||
HW_IPCC_MAC_802_15_4_CmdEvtNot();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_MAC_802_15_4_NotEvtHandler(void) {
|
||||
LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL);
|
||||
|
||||
HW_IPCC_MAC_802_15_4_EvtNot();
|
||||
|
||||
return;
|
||||
}
|
||||
__weak void HW_IPCC_MAC_802_15_4_CmdEvtNot(void){};
|
||||
__weak void HW_IPCC_MAC_802_15_4_EvtNot(void){};
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* THREAD
|
||||
******************************************************************************/
|
||||
#ifdef THREAD_WB
|
||||
void HW_IPCC_THREAD_Init(void) {
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_OT_SendCmd(void) {
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL);
|
||||
LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_CLI_SendCmd(void) {
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_THREAD_CLI_CMD_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_THREAD_SendAck(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_THREAD_CliSendAck(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_OT_CmdEvtHandler(void) {
|
||||
LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL);
|
||||
|
||||
HW_IPCC_OT_CmdEvtNot();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_THREAD_NotEvtHandler(void) {
|
||||
LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL);
|
||||
|
||||
HW_IPCC_THREAD_EvtNot();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_THREAD_CliNotEvtHandler(void) {
|
||||
LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL);
|
||||
|
||||
HW_IPCC_THREAD_CliEvtNot();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
__weak void HW_IPCC_OT_CmdEvtNot(void){};
|
||||
__weak void HW_IPCC_CLI_CmdEvtNot(void){};
|
||||
__weak void HW_IPCC_THREAD_EvtNot(void){};
|
||||
|
||||
#endif /* THREAD_WB */
|
||||
|
||||
/******************************************************************************
|
||||
* LLD TESTS
|
||||
******************************************************************************/
|
||||
#ifdef LLD_TESTS_WB
|
||||
void HW_IPCC_LLDTESTS_Init(void) {
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_CLI_RSP_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_M0_CMD_CHANNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_LLDTESTS_SendCliCmd(void) {
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_LLDTESTS_CLI_CMD_CHANNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_LLDTESTS_ReceiveCliRspHandler(void) {
|
||||
LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_CLI_RSP_CHANNEL);
|
||||
HW_IPCC_LLDTESTS_ReceiveCliRsp();
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_LLDTESTS_SendCliRspAck(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_LLDTESTS_CLI_RSP_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_CLI_RSP_CHANNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_LLDTESTS_ReceiveM0CmdHandler(void) {
|
||||
LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_M0_CMD_CHANNEL);
|
||||
HW_IPCC_LLDTESTS_ReceiveM0Cmd();
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_LLDTESTS_SendM0CmdAck(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_LLDTESTS_M0_CMD_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_M0_CMD_CHANNEL);
|
||||
return;
|
||||
}
|
||||
__weak void HW_IPCC_LLDTESTS_ReceiveCliRsp(void){};
|
||||
__weak void HW_IPCC_LLDTESTS_ReceiveM0Cmd(void){};
|
||||
#endif /* LLD_TESTS_WB */
|
||||
|
||||
/******************************************************************************
|
||||
* LLD BLE
|
||||
******************************************************************************/
|
||||
#ifdef LLD_BLE_WB
|
||||
void HW_IPCC_LLD_BLE_Init(void) {
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLD_BLE_RSP_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLD_BLE_M0_CMD_CHANNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_LLD_BLE_SendCliCmd(void) {
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_LLD_BLE_CLI_CMD_CHANNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
/*static void HW_IPCC_LLD_BLE_ReceiveCliRspHandler( void )
|
||||
{
|
||||
LL_C1_IPCC_DisableReceiveChannel( IPCC, HW_IPCC_LLD_BLE_CLI_RSP_CHANNEL );
|
||||
HW_IPCC_LLD_BLE_ReceiveCliRsp();
|
||||
return;
|
||||
}*/
|
||||
|
||||
void HW_IPCC_LLD_BLE_SendCliRspAck(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_LLD_BLE_CLI_RSP_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLD_BLE_CLI_RSP_CHANNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_LLD_BLE_ReceiveM0CmdHandler(void) {
|
||||
//LL_C1_IPCC_DisableReceiveChannel( IPCC, HW_IPCC_LLD_BLE_M0_CMD_CHANNEL );
|
||||
HW_IPCC_LLD_BLE_ReceiveM0Cmd();
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_LLD_BLE_SendM0CmdAck(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_LLD_BLE_M0_CMD_CHANNEL);
|
||||
//LL_C1_IPCC_EnableReceiveChannel( IPCC, HW_IPCC_LLD_BLE_M0_CMD_CHANNEL );
|
||||
return;
|
||||
}
|
||||
__weak void HW_IPCC_LLD_BLE_ReceiveCliRsp(void){};
|
||||
__weak void HW_IPCC_LLD_BLE_ReceiveM0Cmd(void){};
|
||||
|
||||
/* Transparent Mode */
|
||||
void HW_IPCC_LLD_BLE_SendCmd(void) {
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_LLD_BLE_CMD_CHANNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_LLD_BLE_ReceiveRspHandler(void) {
|
||||
LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_LLD_BLE_RSP_CHANNEL);
|
||||
HW_IPCC_LLD_BLE_ReceiveRsp();
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_LLD_BLE_SendRspAck(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_LLD_BLE_RSP_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLD_BLE_RSP_CHANNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* LLD_BLE_WB */
|
||||
|
||||
/******************************************************************************
|
||||
* ZIGBEE
|
||||
******************************************************************************/
|
||||
#ifdef ZIGBEE_WB
|
||||
void HW_IPCC_ZIGBEE_Init(void) {
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_M0_REQUEST_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_ZIGBEE_SendM4RequestToM0(void) {
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_ZIGBEE_CMD_APPLI_CHANNEL);
|
||||
LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_ZIGBEE_CMD_APPLI_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_ZIGBEE_SendM4AckToM0Notify(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_ZIGBEE_CmdEvtHandler(void) {
|
||||
LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_ZIGBEE_CMD_APPLI_CHANNEL);
|
||||
|
||||
HW_IPCC_ZIGBEE_RecvAppliAckFromM0();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_ZIGBEE_StackNotifEvtHandler(void) {
|
||||
LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL);
|
||||
|
||||
HW_IPCC_ZIGBEE_RecvM0NotifyToM4();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_ZIGBEE_StackM0RequestHandler(void) {
|
||||
LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_M0_REQUEST_CHANNEL);
|
||||
|
||||
HW_IPCC_ZIGBEE_RecvM0RequestToM4();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_ZIGBEE_SendM4AckToM0Request(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_ZIGBEE_M0_REQUEST_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_M0_REQUEST_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
__weak void HW_IPCC_ZIGBEE_RecvAppliAckFromM0(void){};
|
||||
__weak void HW_IPCC_ZIGBEE_RecvM0NotifyToM4(void){};
|
||||
__weak void HW_IPCC_ZIGBEE_RecvM0RequestToM4(void){};
|
||||
#endif /* ZIGBEE_WB */
|
||||
|
||||
/******************************************************************************
|
||||
* MEMORY MANAGER
|
||||
******************************************************************************/
|
||||
void HW_IPCC_MM_SendFreeBuf(void (*cb)(void)) {
|
||||
void HW_IPCC_MM_SendFreeBuf(void (*cb)()) {
|
||||
if(LL_C1_IPCC_IsActiveFlag_CHx(IPCC, HW_IPCC_MM_RELEASE_BUFFER_CHANNEL)) {
|
||||
FreeBufCb = cb;
|
||||
LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_MM_RELEASE_BUFFER_CHANNEL);
|
||||
@ -557,37 +143,22 @@ void HW_IPCC_MM_SendFreeBuf(void (*cb)(void)) {
|
||||
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_MM_RELEASE_BUFFER_CHANNEL);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_MM_FreeBufHandler(void) {
|
||||
static void HW_IPCC_MM_FreeBufHandler() {
|
||||
LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_MM_RELEASE_BUFFER_CHANNEL);
|
||||
|
||||
FreeBufCb();
|
||||
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_MM_RELEASE_BUFFER_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* TRACES
|
||||
******************************************************************************/
|
||||
void HW_IPCC_TRACES_Init(void) {
|
||||
void HW_IPCC_TRACES_Init() {
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_TRACES_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_TRACES_EvtHandler(void) {
|
||||
static void HW_IPCC_TRACES_EvtHandler() {
|
||||
HW_IPCC_TRACES_EvtNot();
|
||||
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_TRACES_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
__weak void HW_IPCC_TRACES_EvtNot(void){};
|
||||
|
||||
/******************* (C) COPYRIGHT 2019 STMicroelectronics *****END OF FILE****/
|
||||
|
||||
@ -1,25 +1,4 @@
|
||||
/*****************************************************************************
|
||||
* @file osal.h
|
||||
* @author MDG
|
||||
* @brief This header file defines the OS abstraction layer used by
|
||||
* the BLE stack. OSAL defines the set of functions which needs to be
|
||||
* ported to target operating system and target platform.
|
||||
* Actually, only memset, memcpy and memcmp wrappers are defined.
|
||||
*****************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2018-2022 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef OSAL_H__
|
||||
#define OSAL_H__
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* This function copies size number of bytes from a
|
||||
@ -59,5 +38,3 @@ extern void* Osal_MemSet(void* ptr, int value, unsigned int size);
|
||||
* @return 0 if the two buffers are equal, 1 otherwise
|
||||
*/
|
||||
extern int Osal_MemCmp(const void* s1, const void* s2, unsigned int size);
|
||||
|
||||
#endif /* OSAL_H__ */
|
||||
|
||||
@ -1,39 +1,12 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : App/tl_dbg_conf.h
|
||||
* Description : Debug configuration file for stm32wpan transport layer interface.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
#pragma once
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __TL_DBG_CONF_H
|
||||
#define __TL_DBG_CONF_H
|
||||
#include "app_conf.h" /* required as some configuration used in dbg_trace.h are set there */
|
||||
#include "dbg_trace.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* USER CODE BEGIN Tl_Conf */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "app_conf.h" /* required as some configuration used in dbg_trace.h are set there */
|
||||
#include "dbg_trace.h"
|
||||
#include "hw_if.h"
|
||||
|
||||
/**
|
||||
* Enable or Disable traces
|
||||
* The raw data output is the hci binary packet format as specified by the BT specification *
|
||||
@ -124,12 +97,6 @@ extern "C" {
|
||||
#define TL_MM_DBG_MSG(...)
|
||||
#endif
|
||||
|
||||
/* USER CODE END Tl_Conf */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__TL_DBG_CONF_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
@ -1,68 +0,0 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : utilities_conf.h
|
||||
* Description : Configuration file for STM32 Utilities.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2019 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under BSD 3-Clause license,
|
||||
* the "License"; You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef UTILITIES_CONF_H
|
||||
#define UTILITIES_CONF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "cmsis_compiler.h"
|
||||
#include "string.h"
|
||||
#include <furi.h>
|
||||
|
||||
/******************************************************************************
|
||||
* common
|
||||
******************************************************************************/
|
||||
#define UTILS_ENTER_CRITICAL_SECTION() FURI_CRITICAL_ENTER()
|
||||
|
||||
#define UTILS_EXIT_CRITICAL_SECTION() FURI_CRITICAL_EXIT()
|
||||
|
||||
#define UTILS_MEMSET8(dest, value, size) memset(dest, value, size);
|
||||
|
||||
/******************************************************************************
|
||||
* tiny low power manager
|
||||
* (any macro that does not need to be modified can be removed)
|
||||
******************************************************************************/
|
||||
#define UTIL_LPM_INIT_CRITICAL_SECTION()
|
||||
#define UTIL_LPM_ENTER_CRITICAL_SECTION() UTILS_ENTER_CRITICAL_SECTION()
|
||||
#define UTIL_LPM_EXIT_CRITICAL_SECTION() UTILS_EXIT_CRITICAL_SECTION()
|
||||
|
||||
/******************************************************************************
|
||||
* sequencer
|
||||
* (any macro that does not need to be modified can be removed)
|
||||
******************************************************************************/
|
||||
#define UTIL_SEQ_INIT_CRITICAL_SECTION()
|
||||
#define UTIL_SEQ_ENTER_CRITICAL_SECTION() UTILS_ENTER_CRITICAL_SECTION()
|
||||
#define UTIL_SEQ_EXIT_CRITICAL_SECTION() UTILS_EXIT_CRITICAL_SECTION()
|
||||
#define UTIL_SEQ_CONF_TASK_NBR (32)
|
||||
#define UTIL_SEQ_CONF_PRIO_NBR (2)
|
||||
#define UTIL_SEQ_MEMSET8(dest, value, size) UTILS_MEMSET8(dest, value, size)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*UTILITIES_CONF_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
@ -2,7 +2,11 @@
|
||||
|
||||
#include <ble/ble.h>
|
||||
#include <interface/patterns/ble_thread/shci/shci.h>
|
||||
|
||||
#include <stm32wbxx.h>
|
||||
#include <stm32wbxx_ll_hsem.h>
|
||||
|
||||
#include <hsem_map.h>
|
||||
|
||||
#include <furi_hal_version.h>
|
||||
#include <furi_hal_bt_hid.h>
|
||||
|
||||
@ -4,19 +4,26 @@
|
||||
|
||||
#include <stm32wbxx_ll_pwr.h>
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <stm32wbxx_ll_hsem.h>
|
||||
#include <stm32wbxx_ll_utils.h>
|
||||
#include <stm32wbxx_ll_cortex.h>
|
||||
|
||||
#include <hsem_map.h>
|
||||
#include <interface/patterns/ble_thread/shci/shci.h>
|
||||
|
||||
#define TAG "FuriHalClock"
|
||||
|
||||
#define CPU_CLOCK_HZ_EARLY 4000000
|
||||
#define CPU_CLOCK_HZ_MAIN 64000000
|
||||
#define CPU_CLOCK_EARLY_HZ 4000000
|
||||
#define CPU_CLOCK_HSI16_HZ 16000000
|
||||
#define CPU_CLOCK_HSE_HZ 32000000
|
||||
#define CPU_CLOCK_PLL_HZ 64000000
|
||||
|
||||
#define TICK_INT_PRIORITY 15U
|
||||
#define HS_CLOCK_IS_READY() (LL_RCC_HSE_IsReady() && LL_RCC_HSI_IsReady())
|
||||
#define LS_CLOCK_IS_READY() (LL_RCC_LSE_IsReady() && LL_RCC_LSI1_IsReady())
|
||||
|
||||
void furi_hal_clock_init_early() {
|
||||
LL_SetSystemCoreClock(CPU_CLOCK_HZ_EARLY);
|
||||
LL_SetSystemCoreClock(CPU_CLOCK_EARLY_HZ);
|
||||
LL_Init1msTick(SystemCoreClock);
|
||||
}
|
||||
|
||||
@ -24,11 +31,6 @@ void furi_hal_clock_deinit_early() {
|
||||
}
|
||||
|
||||
void furi_hal_clock_init() {
|
||||
/* Prepare Flash memory for 64MHz system clock */
|
||||
LL_FLASH_SetLatency(LL_FLASH_LATENCY_3);
|
||||
while(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_3)
|
||||
;
|
||||
|
||||
/* HSE and HSI configuration and activation */
|
||||
LL_RCC_HSE_SetCapacitorTuning(0x26);
|
||||
LL_RCC_HSE_Enable();
|
||||
@ -49,9 +51,6 @@ void furi_hal_clock_init() {
|
||||
while(!LS_CLOCK_IS_READY())
|
||||
;
|
||||
|
||||
/* RF wakeup */
|
||||
LL_RCC_SetRFWKPClockSource(LL_RCC_RFWKP_CLKSOURCE_LSE);
|
||||
|
||||
LL_EXTI_EnableIT_0_31(
|
||||
LL_EXTI_LINE_18); /* Why? Because that's why. See RM0434, Table 61. CPU1 vector table. */
|
||||
LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINE_18);
|
||||
@ -79,12 +78,17 @@ void furi_hal_clock_init() {
|
||||
;
|
||||
|
||||
/* Sysclk activation on the main PLL */
|
||||
/* Set CPU1 prescaler*/
|
||||
/* Set CPU1 prescaler */
|
||||
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
|
||||
|
||||
/* Set CPU2 prescaler*/
|
||||
/* Set CPU2 prescaler, from this point we are not allowed to touch it. */
|
||||
LL_C2_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2);
|
||||
|
||||
/* Prepare Flash memory for work on 64MHz system clock */
|
||||
LL_FLASH_SetLatency(LL_FLASH_LATENCY_3);
|
||||
while(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_3)
|
||||
;
|
||||
|
||||
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
|
||||
while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
|
||||
;
|
||||
@ -104,7 +108,7 @@ void furi_hal_clock_init() {
|
||||
;
|
||||
|
||||
/* Update CMSIS variable (which can be updated also through SystemCoreClockUpdate function) */
|
||||
LL_SetSystemCoreClock(CPU_CLOCK_HZ_MAIN);
|
||||
LL_SetSystemCoreClock(CPU_CLOCK_PLL_HZ);
|
||||
|
||||
/* Update the time base */
|
||||
LL_Init1msTick(SystemCoreClock);
|
||||
@ -122,7 +126,7 @@ void furi_hal_clock_init() {
|
||||
FURI_LOG_I(TAG, "Init OK");
|
||||
}
|
||||
|
||||
void furi_hal_clock_switch_to_hsi() {
|
||||
void furi_hal_clock_switch_hse2hsi() {
|
||||
LL_RCC_HSI_Enable();
|
||||
|
||||
while(!LL_RCC_HSI_IsReady())
|
||||
@ -134,38 +138,27 @@ void furi_hal_clock_switch_to_hsi() {
|
||||
while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI)
|
||||
;
|
||||
|
||||
LL_C2_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
|
||||
|
||||
LL_FLASH_SetLatency(LL_FLASH_LATENCY_0);
|
||||
while(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0)
|
||||
;
|
||||
}
|
||||
|
||||
void furi_hal_clock_switch_to_pll() {
|
||||
void furi_hal_clock_switch_hsi2hse() {
|
||||
#ifdef FURI_HAL_CLOCK_TRACK_STARTUP
|
||||
uint32_t clock_start_time = DWT->CYCCNT;
|
||||
#endif
|
||||
|
||||
LL_RCC_HSE_Enable();
|
||||
LL_RCC_PLL_Enable();
|
||||
LL_RCC_PLLSAI1_Enable();
|
||||
|
||||
while(!LL_RCC_HSE_IsReady())
|
||||
;
|
||||
while(!LL_RCC_PLL_IsReady())
|
||||
;
|
||||
while(!LL_RCC_PLLSAI1_IsReady())
|
||||
|
||||
LL_FLASH_SetLatency(LL_FLASH_LATENCY_1);
|
||||
while(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_1)
|
||||
;
|
||||
|
||||
LL_C2_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2);
|
||||
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE);
|
||||
|
||||
LL_FLASH_SetLatency(LL_FLASH_LATENCY_3);
|
||||
while(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_3)
|
||||
;
|
||||
|
||||
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
|
||||
|
||||
while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
|
||||
while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE)
|
||||
;
|
||||
|
||||
#ifdef FURI_HAL_CLOCK_TRACK_STARTUP
|
||||
@ -176,6 +169,48 @@ void furi_hal_clock_switch_to_pll() {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool furi_hal_clock_switch_hse2pll() {
|
||||
furi_assert(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_HSE);
|
||||
|
||||
LL_RCC_PLL_Enable();
|
||||
LL_RCC_PLLSAI1_Enable();
|
||||
|
||||
while(!LL_RCC_PLL_IsReady())
|
||||
;
|
||||
while(!LL_RCC_PLLSAI1_IsReady())
|
||||
;
|
||||
|
||||
if(SHCI_C2_SetSystemClock(SET_SYSTEM_CLOCK_HSE_TO_PLL) != SHCI_Success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
furi_check(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL);
|
||||
|
||||
LL_SetSystemCoreClock(CPU_CLOCK_PLL_HZ);
|
||||
SysTick->LOAD = (uint32_t)((SystemCoreClock / 1000) - 1UL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool furi_hal_clock_switch_pll2hse() {
|
||||
furi_assert(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL);
|
||||
|
||||
LL_RCC_HSE_Enable();
|
||||
while(!LL_RCC_HSE_IsReady())
|
||||
;
|
||||
|
||||
if(SHCI_C2_SetSystemClock(SET_SYSTEM_CLOCK_PLL_ON_TO_HSE) != SHCI_Success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
furi_check(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_HSE);
|
||||
|
||||
LL_SetSystemCoreClock(CPU_CLOCK_HSE_HZ);
|
||||
SysTick->LOAD = (uint32_t)((SystemCoreClock / 1000) - 1UL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void furi_hal_clock_suspend_tick() {
|
||||
CLEAR_BIT(SysTick->CTRL, SysTick_CTRL_ENABLE_Msk);
|
||||
}
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
|
||||
typedef enum {
|
||||
FuriHalClockMcoLse,
|
||||
FuriHalClockMcoSysclk,
|
||||
@ -40,11 +41,23 @@ void furi_hal_clock_deinit_early();
|
||||
/** Initialize clocks */
|
||||
void furi_hal_clock_init();
|
||||
|
||||
/** Switch to HSI clock */
|
||||
void furi_hal_clock_switch_to_hsi();
|
||||
/** Switch clock from HSE to HSI */
|
||||
void furi_hal_clock_switch_hse2hsi();
|
||||
|
||||
/** Switch to PLL clock */
|
||||
void furi_hal_clock_switch_to_pll();
|
||||
/** Switch clock from HSI to HSE */
|
||||
void furi_hal_clock_switch_hsi2hse();
|
||||
|
||||
/** Switch clock from HSE to PLL
|
||||
*
|
||||
* @return true if changed, false if failed or not possible at this moment
|
||||
*/
|
||||
bool furi_hal_clock_switch_hse2pll();
|
||||
|
||||
/** Switch clock from PLL to HSE
|
||||
*
|
||||
* @return true if changed, false if failed or not possible at this moment
|
||||
*/
|
||||
bool furi_hal_clock_switch_pll2hse();
|
||||
|
||||
/** Stop SysTick counter without resetting */
|
||||
void furi_hal_clock_suspend_tick();
|
||||
|
||||
@ -5,8 +5,6 @@
|
||||
#include <stm32wbxx_ll_gpio.h>
|
||||
#include <stm32wbxx_ll_usart.h>
|
||||
|
||||
#include <utilities_conf.h>
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "FuriHalConsole"
|
||||
|
||||
@ -15,8 +15,11 @@ void furi_hal_cortex_init_early() {
|
||||
}
|
||||
|
||||
void furi_hal_cortex_delay_us(uint32_t microseconds) {
|
||||
furi_check(microseconds < (UINT32_MAX / FURI_HAL_CORTEX_INSTRUCTIONS_PER_MICROSECOND));
|
||||
|
||||
uint32_t start = DWT->CYCCNT;
|
||||
uint32_t time_ticks = FURI_HAL_CORTEX_INSTRUCTIONS_PER_MICROSECOND * microseconds;
|
||||
|
||||
while((DWT->CYCCNT - start) < time_ticks) {
|
||||
};
|
||||
}
|
||||
@ -26,6 +29,8 @@ uint32_t furi_hal_cortex_instructions_per_microsecond() {
|
||||
}
|
||||
|
||||
FuriHalCortexTimer furi_hal_cortex_timer_get(uint32_t timeout_us) {
|
||||
furi_check(timeout_us < (UINT32_MAX / FURI_HAL_CORTEX_INSTRUCTIONS_PER_MICROSECOND));
|
||||
|
||||
FuriHalCortexTimer cortex_timer = {0};
|
||||
cortex_timer.start = DWT->CYCCNT;
|
||||
cortex_timer.value = FURI_HAL_CORTEX_INSTRUCTIONS_PER_MICROSECOND * timeout_us;
|
||||
|
||||
@ -7,6 +7,9 @@
|
||||
#include <interface/patterns/ble_thread/shci/shci.h>
|
||||
|
||||
#include <stm32wbxx.h>
|
||||
#include <stm32wbxx_ll_hsem.h>
|
||||
|
||||
#include <hsem_map.h>
|
||||
|
||||
#define TAG "FuriHalFlash"
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
|
||||
#include <stm32wbxx_ll_i2c.h>
|
||||
#include <stm32wbxx_ll_gpio.h>
|
||||
#include <stm32wbxx_ll_cortex.h>
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "FuriHalI2c"
|
||||
@ -27,7 +26,7 @@ void furi_hal_i2c_acquire(FuriHalI2cBusHandle* handle) {
|
||||
furi_hal_power_insomnia_enter();
|
||||
// Lock bus access
|
||||
handle->bus->callback(handle->bus, FuriHalI2cBusEventLock);
|
||||
// Ensuree that no active handle set
|
||||
// Ensure that no active handle set
|
||||
furi_check(handle->bus->current_handle == NULL);
|
||||
// Set current handle
|
||||
handle->bus->current_handle = handle;
|
||||
@ -51,177 +50,265 @@ void furi_hal_i2c_release(FuriHalI2cBusHandle* handle) {
|
||||
furi_hal_power_insomnia_exit();
|
||||
}
|
||||
|
||||
static bool
|
||||
furi_hal_i2c_wait_for_idle(I2C_TypeDef* i2c, FuriHalI2cBegin begin, FuriHalCortexTimer timer) {
|
||||
do {
|
||||
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||
return false;
|
||||
}
|
||||
} while(begin == FuriHalI2cBeginStart && LL_I2C_IsActiveFlag_BUSY(i2c));
|
||||
// Only check if the bus is busy if starting a new transaction, if not we already control the bus
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
furi_hal_i2c_wait_for_end(I2C_TypeDef* i2c, FuriHalI2cEnd end, FuriHalCortexTimer timer) {
|
||||
// If ending the transaction with a stop condition, wait for it to be detected, otherwise wait for a transfer complete flag
|
||||
bool wait_for_stop = end == FuriHalI2cEndStop;
|
||||
uint32_t end_mask = (wait_for_stop) ? I2C_ISR_STOPF : (I2C_ISR_TC | I2C_ISR_TCR);
|
||||
|
||||
while((i2c->ISR & end_mask) == 0) {
|
||||
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
furi_hal_i2c_get_start_signal(FuriHalI2cBegin begin, bool ten_bit_address, bool read) {
|
||||
switch(begin) {
|
||||
case FuriHalI2cBeginRestart:
|
||||
if(read) {
|
||||
return ten_bit_address ? LL_I2C_GENERATE_RESTART_10BIT_READ :
|
||||
LL_I2C_GENERATE_RESTART_7BIT_READ;
|
||||
} else {
|
||||
return ten_bit_address ? LL_I2C_GENERATE_RESTART_10BIT_WRITE :
|
||||
LL_I2C_GENERATE_RESTART_7BIT_WRITE;
|
||||
}
|
||||
case FuriHalI2cBeginResume:
|
||||
return LL_I2C_GENERATE_NOSTARTSTOP;
|
||||
case FuriHalI2cBeginStart:
|
||||
default:
|
||||
return read ? LL_I2C_GENERATE_START_READ : LL_I2C_GENERATE_START_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t furi_hal_i2c_get_end_signal(FuriHalI2cEnd end) {
|
||||
switch(end) {
|
||||
case FuriHalI2cEndAwaitRestart:
|
||||
return LL_I2C_MODE_SOFTEND;
|
||||
case FuriHalI2cEndPause:
|
||||
return LL_I2C_MODE_RELOAD;
|
||||
case FuriHalI2cEndStop:
|
||||
default:
|
||||
return LL_I2C_MODE_AUTOEND;
|
||||
}
|
||||
}
|
||||
|
||||
static bool furi_hal_i2c_transfer_is_aborted(I2C_TypeDef* i2c) {
|
||||
return LL_I2C_IsActiveFlag_STOP(i2c) &&
|
||||
!(LL_I2C_IsActiveFlag_TC(i2c) || LL_I2C_IsActiveFlag_TCR(i2c));
|
||||
}
|
||||
|
||||
static bool furi_hal_i2c_transfer(
|
||||
I2C_TypeDef* i2c,
|
||||
uint8_t* data,
|
||||
uint32_t size,
|
||||
FuriHalI2cEnd end,
|
||||
bool read,
|
||||
FuriHalCortexTimer timer) {
|
||||
bool ret = true;
|
||||
|
||||
while(size > 0) {
|
||||
bool should_stop = furi_hal_cortex_timer_is_expired(timer) ||
|
||||
furi_hal_i2c_transfer_is_aborted(i2c);
|
||||
|
||||
// Modifying the data pointer's data is UB if read is true
|
||||
if(read && LL_I2C_IsActiveFlag_RXNE(i2c)) {
|
||||
*data = LL_I2C_ReceiveData8(i2c);
|
||||
data++;
|
||||
size--;
|
||||
} else if(!read && LL_I2C_IsActiveFlag_TXIS(i2c)) {
|
||||
LL_I2C_TransmitData8(i2c, *data);
|
||||
data++;
|
||||
size--;
|
||||
}
|
||||
|
||||
// Exit on timeout or premature stop, probably caused by a nacked address or byte
|
||||
if(should_stop) {
|
||||
ret = size == 0; // If the transfer was over, still a success
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ret) {
|
||||
ret = furi_hal_i2c_wait_for_end(i2c, end, timer);
|
||||
}
|
||||
|
||||
LL_I2C_ClearFlag_STOP(i2c);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool furi_hal_i2c_transaction(
|
||||
I2C_TypeDef* i2c,
|
||||
uint16_t address,
|
||||
bool ten_bit,
|
||||
uint8_t* data,
|
||||
size_t size,
|
||||
FuriHalI2cBegin begin,
|
||||
FuriHalI2cEnd end,
|
||||
bool read,
|
||||
FuriHalCortexTimer timer) {
|
||||
uint32_t addr_size = ten_bit ? LL_I2C_ADDRSLAVE_10BIT : LL_I2C_ADDRSLAVE_7BIT;
|
||||
uint32_t start_signal = furi_hal_i2c_get_start_signal(begin, ten_bit, read);
|
||||
|
||||
if(!furi_hal_i2c_wait_for_idle(i2c, begin, timer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
do {
|
||||
uint8_t transfer_size = size;
|
||||
FuriHalI2cEnd transfer_end = end;
|
||||
|
||||
if(size > 255) {
|
||||
transfer_size = 255;
|
||||
transfer_end = FuriHalI2cEndPause;
|
||||
}
|
||||
|
||||
uint32_t end_signal = furi_hal_i2c_get_end_signal(transfer_end);
|
||||
|
||||
LL_I2C_HandleTransfer(i2c, address, addr_size, transfer_size, end_signal, start_signal);
|
||||
|
||||
if(!furi_hal_i2c_transfer(i2c, data, transfer_size, transfer_end, read, timer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size -= transfer_size;
|
||||
data += transfer_size;
|
||||
start_signal = LL_I2C_GENERATE_NOSTARTSTOP;
|
||||
} while(size > 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool furi_hal_i2c_rx_ext(
|
||||
FuriHalI2cBusHandle* handle,
|
||||
uint16_t address,
|
||||
bool ten_bit,
|
||||
uint8_t* data,
|
||||
size_t size,
|
||||
FuriHalI2cBegin begin,
|
||||
FuriHalI2cEnd end,
|
||||
uint32_t timeout) {
|
||||
furi_check(handle->bus->current_handle == handle);
|
||||
|
||||
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(timeout * 1000);
|
||||
|
||||
return furi_hal_i2c_transaction(
|
||||
handle->bus->i2c, address, ten_bit, data, size, begin, end, true, timer);
|
||||
}
|
||||
|
||||
bool furi_hal_i2c_tx_ext(
|
||||
FuriHalI2cBusHandle* handle,
|
||||
uint16_t address,
|
||||
bool ten_bit,
|
||||
const uint8_t* data,
|
||||
size_t size,
|
||||
FuriHalI2cBegin begin,
|
||||
FuriHalI2cEnd end,
|
||||
uint32_t timeout) {
|
||||
furi_check(handle->bus->current_handle == handle);
|
||||
|
||||
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(timeout * 1000);
|
||||
|
||||
return furi_hal_i2c_transaction(
|
||||
handle->bus->i2c, address, ten_bit, (uint8_t*)data, size, begin, end, false, timer);
|
||||
}
|
||||
|
||||
bool furi_hal_i2c_tx(
|
||||
FuriHalI2cBusHandle* handle,
|
||||
uint8_t address,
|
||||
const uint8_t* data,
|
||||
uint8_t size,
|
||||
size_t size,
|
||||
uint32_t timeout) {
|
||||
furi_check(handle->bus->current_handle == handle);
|
||||
furi_assert(timeout > 0);
|
||||
|
||||
bool ret = true;
|
||||
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(timeout * 1000);
|
||||
|
||||
do {
|
||||
while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c)) {
|
||||
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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(furi_hal_cortex_timer_is_expired(timer)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LL_I2C_ClearFlag_STOP(handle->bus->i2c);
|
||||
} while(0);
|
||||
|
||||
return ret;
|
||||
return furi_hal_i2c_tx_ext(
|
||||
handle, address, false, data, size, FuriHalI2cBeginStart, FuriHalI2cEndStop, timeout);
|
||||
}
|
||||
|
||||
bool furi_hal_i2c_rx(
|
||||
FuriHalI2cBusHandle* handle,
|
||||
uint8_t address,
|
||||
uint8_t* data,
|
||||
uint8_t size,
|
||||
size_t size,
|
||||
uint32_t timeout) {
|
||||
furi_check(handle->bus->current_handle == handle);
|
||||
furi_assert(timeout > 0);
|
||||
|
||||
bool ret = true;
|
||||
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(timeout * 1000);
|
||||
|
||||
do {
|
||||
while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c)) {
|
||||
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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(furi_hal_cortex_timer_is_expired(timer)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LL_I2C_ClearFlag_STOP(handle->bus->i2c);
|
||||
} while(0);
|
||||
|
||||
return ret;
|
||||
return furi_hal_i2c_rx_ext(
|
||||
handle, address, false, data, size, FuriHalI2cBeginStart, FuriHalI2cEndStop, timeout);
|
||||
}
|
||||
|
||||
bool furi_hal_i2c_trx(
|
||||
FuriHalI2cBusHandle* handle,
|
||||
uint8_t address,
|
||||
const uint8_t* tx_data,
|
||||
uint8_t tx_size,
|
||||
size_t tx_size,
|
||||
uint8_t* rx_data,
|
||||
uint8_t rx_size,
|
||||
size_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;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return furi_hal_i2c_tx_ext(
|
||||
handle,
|
||||
address,
|
||||
false,
|
||||
tx_data,
|
||||
tx_size,
|
||||
FuriHalI2cBeginStart,
|
||||
FuriHalI2cEndStop,
|
||||
timeout) &&
|
||||
furi_hal_i2c_rx_ext(
|
||||
handle,
|
||||
address,
|
||||
false,
|
||||
rx_data,
|
||||
rx_size,
|
||||
FuriHalI2cBeginStart,
|
||||
FuriHalI2cEndStop,
|
||||
timeout);
|
||||
}
|
||||
|
||||
bool furi_hal_i2c_is_device_ready(FuriHalI2cBusHandle* handle, uint8_t i2c_addr, uint32_t timeout) {
|
||||
furi_check(handle);
|
||||
|
||||
furi_check(handle->bus->current_handle == handle);
|
||||
furi_assert(timeout > 0);
|
||||
|
||||
bool ret = true;
|
||||
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(timeout * 1000);
|
||||
|
||||
do {
|
||||
while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c)) {
|
||||
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!furi_hal_i2c_wait_for_idle(handle->bus->i2c, FuriHalI2cBeginStart, timer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
handle->bus->i2c->CR2 =
|
||||
((((uint32_t)(i2c_addr) & (I2C_CR2_SADD)) | (I2C_CR2_START) | (I2C_CR2_AUTOEND)) &
|
||||
(~I2C_CR2_RD_WRN));
|
||||
LL_I2C_HandleTransfer(
|
||||
handle->bus->i2c,
|
||||
i2c_addr,
|
||||
LL_I2C_ADDRSLAVE_7BIT,
|
||||
0,
|
||||
LL_I2C_MODE_AUTOEND,
|
||||
LL_I2C_GENERATE_START_WRITE);
|
||||
|
||||
while((!LL_I2C_IsActiveFlag_NACK(handle->bus->i2c)) &&
|
||||
(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c))) {
|
||||
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!furi_hal_i2c_wait_for_end(handle->bus->i2c, FuriHalI2cEndStop, timer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(LL_I2C_IsActiveFlag_NACK(handle->bus->i2c)) {
|
||||
while(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c)) {
|
||||
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ret = !LL_I2C_IsActiveFlag_NACK(handle->bus->i2c);
|
||||
|
||||
LL_I2C_ClearFlag_NACK(handle->bus->i2c);
|
||||
|
||||
// Clear STOP Flag generated by autoend
|
||||
LL_I2C_ClearFlag_STOP(handle->bus->i2c);
|
||||
|
||||
// Generate actual STOP
|
||||
LL_I2C_GenerateStopCondition(handle->bus->i2c);
|
||||
|
||||
ret = false;
|
||||
}
|
||||
|
||||
while(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c)) {
|
||||
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LL_I2C_ClearFlag_STOP(handle->bus->i2c);
|
||||
} while(0);
|
||||
LL_I2C_ClearFlag_NACK(handle->bus->i2c);
|
||||
LL_I2C_ClearFlag_STOP(handle->bus->i2c);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -257,7 +344,7 @@ bool furi_hal_i2c_read_mem(
|
||||
uint8_t i2c_addr,
|
||||
uint8_t mem_addr,
|
||||
uint8_t* data,
|
||||
uint8_t len,
|
||||
size_t len,
|
||||
uint32_t timeout) {
|
||||
furi_check(handle);
|
||||
|
||||
@ -272,11 +359,12 @@ bool furi_hal_i2c_write_reg_8(
|
||||
uint32_t timeout) {
|
||||
furi_check(handle);
|
||||
|
||||
uint8_t tx_data[2];
|
||||
tx_data[0] = reg_addr;
|
||||
tx_data[1] = data;
|
||||
const uint8_t tx_data[2] = {
|
||||
reg_addr,
|
||||
data,
|
||||
};
|
||||
|
||||
return furi_hal_i2c_tx(handle, i2c_addr, (const uint8_t*)&tx_data, 2, timeout);
|
||||
return furi_hal_i2c_tx(handle, i2c_addr, tx_data, 2, timeout);
|
||||
}
|
||||
|
||||
bool furi_hal_i2c_write_reg_16(
|
||||
@ -287,69 +375,42 @@ bool furi_hal_i2c_write_reg_16(
|
||||
uint32_t timeout) {
|
||||
furi_check(handle);
|
||||
|
||||
uint8_t tx_data[3];
|
||||
tx_data[0] = reg_addr;
|
||||
tx_data[1] = (data >> 8) & 0xFF;
|
||||
tx_data[2] = data & 0xFF;
|
||||
const uint8_t tx_data[3] = {
|
||||
reg_addr,
|
||||
(data >> 8) & 0xFF,
|
||||
data & 0xFF,
|
||||
};
|
||||
|
||||
return furi_hal_i2c_tx(handle, i2c_addr, (const uint8_t*)&tx_data, 3, timeout);
|
||||
return furi_hal_i2c_tx(handle, i2c_addr, tx_data, 3, timeout);
|
||||
}
|
||||
|
||||
bool furi_hal_i2c_write_mem(
|
||||
FuriHalI2cBusHandle* handle,
|
||||
uint8_t i2c_addr,
|
||||
uint8_t mem_addr,
|
||||
uint8_t* data,
|
||||
uint8_t len,
|
||||
const uint8_t* data,
|
||||
size_t len,
|
||||
uint32_t timeout) {
|
||||
furi_check(handle);
|
||||
|
||||
furi_check(handle->bus->current_handle == handle);
|
||||
furi_assert(timeout > 0);
|
||||
|
||||
bool ret = true;
|
||||
uint8_t size = len + 1;
|
||||
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(timeout * 1000);
|
||||
|
||||
do {
|
||||
while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c)) {
|
||||
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!ret) {
|
||||
break;
|
||||
}
|
||||
|
||||
LL_I2C_HandleTransfer(
|
||||
handle->bus->i2c,
|
||||
i2c_addr,
|
||||
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)) {
|
||||
if(size == len + 1) {
|
||||
LL_I2C_TransmitData8(handle->bus->i2c, mem_addr);
|
||||
} else {
|
||||
LL_I2C_TransmitData8(handle->bus->i2c, (*data));
|
||||
data++;
|
||||
}
|
||||
size--;
|
||||
}
|
||||
|
||||
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LL_I2C_ClearFlag_STOP(handle->bus->i2c);
|
||||
} while(0);
|
||||
|
||||
return ret;
|
||||
return furi_hal_i2c_tx_ext(
|
||||
handle,
|
||||
i2c_addr,
|
||||
false,
|
||||
&mem_addr,
|
||||
1,
|
||||
FuriHalI2cBeginStart,
|
||||
FuriHalI2cEndPause,
|
||||
timeout) &&
|
||||
furi_hal_i2c_tx_ext(
|
||||
handle,
|
||||
i2c_addr,
|
||||
false,
|
||||
data,
|
||||
len,
|
||||
FuriHalI2cBeginResume,
|
||||
FuriHalI2cEndStop,
|
||||
timeout);
|
||||
}
|
||||
|
||||
@ -4,9 +4,6 @@
|
||||
|
||||
#define TAG "FuriHalMemory"
|
||||
|
||||
// STM(TM) Copro(TM) bug(TM) workaround size
|
||||
#define RAM2B_COPRO_GAP_SIZE_KB 2
|
||||
|
||||
typedef enum {
|
||||
SRAM_A,
|
||||
SRAM_B,
|
||||
@ -38,13 +35,20 @@ void furi_hal_memory_init() {
|
||||
uint32_t sbrsa = (FLASH->SRRVR & FLASH_SRRVR_SBRSA_Msk) >> FLASH_SRRVR_SBRSA_Pos;
|
||||
uint32_t snbrsa = (FLASH->SRRVR & FLASH_SRRVR_SNBRSA_Msk) >> FLASH_SRRVR_SNBRSA_Pos;
|
||||
|
||||
// STM(TM) Copro(TM) bug(TM): SNBRSA is incorrect if stack version is higher than 1.13 and lower than 1.17.2+
|
||||
// Radio core started, but not yet ready, so we'll try to guess
|
||||
// This will be true only if BLE light radio stack used,
|
||||
// 0x0D is known to be incorrect, 0x0B is known to be correct since 1.17.2+
|
||||
// Lower value by 2 pages to match real memory layout
|
||||
if(snbrsa > 0x0B) {
|
||||
FURI_LOG_E(TAG, "SNBRSA workaround");
|
||||
snbrsa -= 2;
|
||||
}
|
||||
|
||||
uint32_t sram2a_busy_size = (uint32_t)&__sram2a_free__ - (uint32_t)&__sram2a_start__;
|
||||
uint32_t sram2a_unprotected_size = (sbrsa)*1024;
|
||||
uint32_t sram2b_unprotected_size = (snbrsa)*1024;
|
||||
|
||||
// STM(TM) Copro(TM) bug(TM) workaround
|
||||
sram2b_unprotected_size -= 1024 * RAM2B_COPRO_GAP_SIZE_KB;
|
||||
|
||||
memory->region[SRAM_A].start = (uint8_t*)&__sram2a_free__;
|
||||
memory->region[SRAM_B].start = (uint8_t*)&__sram2b_start__;
|
||||
|
||||
|
||||
@ -170,27 +170,35 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Core2 shenanigans takes extra time, so we want to compensate tick skew by reducing sleep duration by 1 tick
|
||||
TickType_t unexpected_idle_ticks = expected_idle_ticks - 1;
|
||||
|
||||
// Limit amount of ticks to maximum that timer can count
|
||||
if(expected_idle_ticks > FURI_HAL_OS_MAX_SLEEP) {
|
||||
expected_idle_ticks = FURI_HAL_OS_MAX_SLEEP;
|
||||
if(unexpected_idle_ticks > FURI_HAL_OS_MAX_SLEEP) {
|
||||
unexpected_idle_ticks = FURI_HAL_OS_MAX_SLEEP;
|
||||
}
|
||||
|
||||
// Stop IRQ handling, no one should disturb us till we finish
|
||||
__disable_irq();
|
||||
do {
|
||||
// Confirm OS that sleep is still possible
|
||||
if(eTaskConfirmSleepModeStatus() == eAbortSleep || furi_hal_os_is_pending_irq()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Confirm OS that sleep is still possible
|
||||
if(eTaskConfirmSleepModeStatus() == eAbortSleep || furi_hal_os_is_pending_irq()) {
|
||||
__enable_irq();
|
||||
return;
|
||||
}
|
||||
|
||||
// Sleep and track how much ticks we spent sleeping
|
||||
uint32_t completed_ticks = furi_hal_os_sleep(expected_idle_ticks);
|
||||
// Notify system about time spent in sleep
|
||||
if(completed_ticks > 0) {
|
||||
vTaskStepTick(MIN(completed_ticks, expected_idle_ticks));
|
||||
}
|
||||
|
||||
// Sleep and track how much ticks we spent sleeping
|
||||
uint32_t completed_ticks = furi_hal_os_sleep(unexpected_idle_ticks);
|
||||
// Notify system about time spent in sleep
|
||||
if(completed_ticks > 0) {
|
||||
if(completed_ticks > expected_idle_ticks) {
|
||||
#ifdef FURI_HAL_OS_DEBUG
|
||||
furi_hal_console_printf(">%lu\r\n", completed_ticks - expected_idle_ticks);
|
||||
#endif
|
||||
completed_ticks = expected_idle_ticks;
|
||||
}
|
||||
vTaskStepTick(completed_ticks);
|
||||
}
|
||||
} while(0);
|
||||
// Reenable IRQ
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
#include <stm32wbxx_ll_cortex.h>
|
||||
#include <stm32wbxx_ll_gpio.h>
|
||||
|
||||
#include <hw_conf.h>
|
||||
#include <hsem_map.h>
|
||||
#include <bq27220.h>
|
||||
#include <bq27220_data_memory.h>
|
||||
#include <bq25896.h>
|
||||
@ -162,6 +162,11 @@ static inline void furi_hal_power_resume_aux_periphs() {
|
||||
static inline void furi_hal_power_deep_sleep() {
|
||||
furi_hal_power_suspend_aux_periphs();
|
||||
|
||||
if(!furi_hal_clock_switch_pll2hse()) {
|
||||
// Hello core2 my old friend
|
||||
return;
|
||||
}
|
||||
|
||||
while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID))
|
||||
;
|
||||
|
||||
@ -171,13 +176,13 @@ static inline void furi_hal_power_deep_sleep() {
|
||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0);
|
||||
|
||||
// The switch on HSI before entering Stop Mode is required
|
||||
furi_hal_clock_switch_to_hsi();
|
||||
furi_hal_clock_switch_hse2hsi();
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* The switch on HSI before entering Stop Mode is required
|
||||
*/
|
||||
furi_hal_clock_switch_to_hsi();
|
||||
furi_hal_clock_switch_hse2hsi();
|
||||
}
|
||||
|
||||
/* Release RCC semaphore */
|
||||
@ -201,12 +206,14 @@ static inline void furi_hal_power_deep_sleep() {
|
||||
while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID))
|
||||
;
|
||||
|
||||
if(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {
|
||||
furi_hal_clock_switch_to_pll();
|
||||
if(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE) {
|
||||
furi_hal_clock_switch_hsi2hse();
|
||||
}
|
||||
|
||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0);
|
||||
|
||||
furi_check(furi_hal_clock_switch_hse2pll());
|
||||
|
||||
furi_hal_power_resume_aux_periphs();
|
||||
furi_hal_rtc_sync_shadow();
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <stm32wbxx_ll_hsem.h>
|
||||
|
||||
#include <hw_conf.h>
|
||||
#include <hsem_map.h>
|
||||
|
||||
#define TAG "FuriHalRandom"
|
||||
|
||||
|
||||
498
firmware/targets/f7/furi_hal/furi_hal_usb_ccid.c
Normal file
498
firmware/targets/f7/furi_hal/furi_hal_usb_ccid.c
Normal file
@ -0,0 +1,498 @@
|
||||
#include <furi_hal_version.h>
|
||||
#include <furi_hal_usb_i.h>
|
||||
#include <furi_hal_usb.h>
|
||||
#include <furi_hal_usb_ccid.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include "usb.h"
|
||||
#include "usb_ccid.h"
|
||||
|
||||
static const uint8_t USB_DEVICE_NO_CLASS = 0x0;
|
||||
static const uint8_t USB_DEVICE_NO_SUBCLASS = 0x0;
|
||||
static const uint8_t USB_DEVICE_NO_PROTOCOL = 0x0;
|
||||
|
||||
#define FIXED_CONTROL_ENDPOINT_SIZE 8
|
||||
#define IF_NUM_MAX 1
|
||||
|
||||
#define CCID_VID_DEFAULT 0x1234
|
||||
#define CCID_PID_DEFAULT 0xABCD
|
||||
#define CCID_TOTAL_SLOTS 1
|
||||
#define CCID_SLOT_INDEX 0
|
||||
|
||||
#define CCID_DATABLOCK_SIZE 256
|
||||
|
||||
#define ENDPOINT_DIR_IN 0x80
|
||||
#define ENDPOINT_DIR_OUT 0x00
|
||||
|
||||
#define INTERFACE_ID_CCID 0
|
||||
|
||||
#define CCID_IN_EPADDR (ENDPOINT_DIR_IN | 2)
|
||||
|
||||
/** Endpoint address of the CCID data OUT endpoint, for host-to-device data transfers. */
|
||||
#define CCID_OUT_EPADDR (ENDPOINT_DIR_OUT | 1)
|
||||
|
||||
/** Endpoint size in bytes of the CCID data being sent between IN and OUT endpoints. */
|
||||
#define CCID_EPSIZE 64
|
||||
|
||||
struct CcidIntfDescriptor {
|
||||
struct usb_interface_descriptor ccid;
|
||||
struct usb_ccid_descriptor ccid_desc;
|
||||
struct usb_endpoint_descriptor ccid_bulk_in;
|
||||
struct usb_endpoint_descriptor ccid_bulk_out;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct CcidConfigDescriptor {
|
||||
struct usb_config_descriptor config;
|
||||
struct CcidIntfDescriptor intf_0;
|
||||
} __attribute__((packed));
|
||||
|
||||
enum CCID_Features_Auto_t {
|
||||
CCID_Features_Auto_None = 0x0,
|
||||
CCID_Features_Auto_ParameterConfiguration = 0x2,
|
||||
CCID_Features_Auto_ICCActivation = 0x4,
|
||||
CCID_Features_Auto_VoltageSelection = 0x8,
|
||||
|
||||
CCID_Features_Auto_ICCClockFrequencyChange = 0x10,
|
||||
CCID_Features_Auto_ICCBaudRateChange = 0x20,
|
||||
CCID_Features_Auto_ParameterNegotiation = 0x40,
|
||||
CCID_Features_Auto_PPS = 0x80,
|
||||
};
|
||||
|
||||
enum CCID_Features_ExchangeLevel_t {
|
||||
CCID_Features_ExchangeLevel_TPDU = 0x00010000,
|
||||
CCID_Features_ExchangeLevel_ShortAPDU = 0x00020000,
|
||||
CCID_Features_ExchangeLevel_ShortExtendedAPDU = 0x00040000
|
||||
};
|
||||
|
||||
/* Device descriptor */
|
||||
static struct usb_device_descriptor ccid_device_desc = {
|
||||
.bLength = sizeof(struct usb_device_descriptor),
|
||||
.bDescriptorType = USB_DTYPE_DEVICE,
|
||||
.bcdUSB = VERSION_BCD(2, 0, 0),
|
||||
.bDeviceClass = USB_DEVICE_NO_CLASS,
|
||||
.bDeviceSubClass = USB_DEVICE_NO_SUBCLASS,
|
||||
.bDeviceProtocol = USB_DEVICE_NO_PROTOCOL,
|
||||
.bMaxPacketSize0 = FIXED_CONTROL_ENDPOINT_SIZE,
|
||||
.idVendor = CCID_VID_DEFAULT,
|
||||
.idProduct = CCID_PID_DEFAULT,
|
||||
.bcdDevice = VERSION_BCD(1, 0, 0),
|
||||
.iManufacturer = UsbDevManuf,
|
||||
.iProduct = UsbDevProduct,
|
||||
.iSerialNumber = UsbDevSerial,
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
/* Device configuration descriptor*/
|
||||
static const struct CcidConfigDescriptor ccid_cfg_desc = {
|
||||
.config =
|
||||
{
|
||||
.bLength = sizeof(struct usb_config_descriptor),
|
||||
.bDescriptorType = USB_DTYPE_CONFIGURATION,
|
||||
.wTotalLength = sizeof(struct CcidConfigDescriptor),
|
||||
.bNumInterfaces = 1,
|
||||
|
||||
.bConfigurationValue = 1,
|
||||
.iConfiguration = NO_DESCRIPTOR,
|
||||
.bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
|
||||
.bMaxPower = USB_CFG_POWER_MA(100),
|
||||
},
|
||||
.intf_0 =
|
||||
{
|
||||
.ccid =
|
||||
{.bLength = sizeof(struct usb_interface_descriptor),
|
||||
.bDescriptorType = USB_DTYPE_INTERFACE,
|
||||
|
||||
.bInterfaceNumber = INTERFACE_ID_CCID,
|
||||
.bAlternateSetting = 0x00,
|
||||
.bNumEndpoints = 2,
|
||||
|
||||
.bInterfaceClass = USB_CLASS_CCID,
|
||||
.bInterfaceSubClass = 0,
|
||||
.bInterfaceProtocol = 0,
|
||||
|
||||
.iInterface = NO_DESCRIPTOR
|
||||
|
||||
},
|
||||
.ccid_desc =
|
||||
{.bLength = sizeof(struct usb_ccid_descriptor),
|
||||
.bDescriptorType = USB_DTYPE_CCID_FUNCTIONAL,
|
||||
.bcdCCID = CCID_CURRENT_SPEC_RELEASE_NUMBER,
|
||||
.bMaxSlotIndex = 0x00,
|
||||
.bVoltageSupport = CCID_VOLTAGESUPPORT_5V,
|
||||
.dwProtocols = 0x01, //T0
|
||||
.dwDefaultClock = 16000, //16MHz
|
||||
.dwMaximumClock = 16000, //16MHz
|
||||
.bNumClockSupported = 0,
|
||||
.dwDataRate = 307200,
|
||||
.dwMaxDataRate = 307200,
|
||||
.bNumDataRatesSupported = 0,
|
||||
.dwMaxIFSD = 2038,
|
||||
.dwSynchProtocols = 0,
|
||||
.dwMechanical = 0,
|
||||
.dwFeatures = CCID_Features_ExchangeLevel_ShortAPDU |
|
||||
CCID_Features_Auto_ParameterConfiguration |
|
||||
CCID_Features_Auto_ICCActivation |
|
||||
CCID_Features_Auto_VoltageSelection,
|
||||
.dwMaxCCIDMessageLength = 0x0c00,
|
||||
.bClassGetResponse = 0xff,
|
||||
.bClassEnvelope = 0xff,
|
||||
.wLcdLayout = 0,
|
||||
.bPINSupport = 0,
|
||||
.bMaxCCIDBusySlots = 1},
|
||||
.ccid_bulk_in =
|
||||
{.bLength = sizeof(struct usb_endpoint_descriptor),
|
||||
.bDescriptorType = USB_DTYPE_ENDPOINT,
|
||||
.bEndpointAddress = CCID_IN_EPADDR,
|
||||
.bmAttributes = USB_EPTYPE_BULK,
|
||||
.wMaxPacketSize = CCID_EPSIZE,
|
||||
.bInterval = 0x05
|
||||
|
||||
},
|
||||
.ccid_bulk_out =
|
||||
{.bLength = sizeof(struct usb_endpoint_descriptor),
|
||||
.bDescriptorType = USB_DTYPE_ENDPOINT,
|
||||
.bEndpointAddress = CCID_OUT_EPADDR,
|
||||
.bmAttributes = USB_EPTYPE_BULK,
|
||||
.wMaxPacketSize = CCID_EPSIZE,
|
||||
.bInterval = 0x05},
|
||||
},
|
||||
};
|
||||
|
||||
static void ccid_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx);
|
||||
static void ccid_deinit(usbd_device* dev);
|
||||
static void ccid_on_wakeup(usbd_device* dev);
|
||||
static void ccid_on_suspend(usbd_device* dev);
|
||||
|
||||
FuriHalUsbInterface usb_ccid = {
|
||||
.init = ccid_init,
|
||||
.deinit = ccid_deinit,
|
||||
.wakeup = ccid_on_wakeup,
|
||||
.suspend = ccid_on_suspend,
|
||||
|
||||
.dev_descr = (struct usb_device_descriptor*)&ccid_device_desc,
|
||||
|
||||
.str_manuf_descr = NULL,
|
||||
.str_prod_descr = NULL,
|
||||
.str_serial_descr = NULL,
|
||||
|
||||
.cfg_descr = (void*)&ccid_cfg_desc,
|
||||
};
|
||||
|
||||
static usbd_respond ccid_ep_config(usbd_device* dev, uint8_t cfg);
|
||||
static usbd_respond ccid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback);
|
||||
static usbd_device* usb_dev;
|
||||
static bool connected = false;
|
||||
static bool smartcard_inserted = true;
|
||||
static CcidCallbacks* callbacks[CCID_TOTAL_SLOTS] = {NULL};
|
||||
|
||||
static void* ccid_set_string_descr(char* str) {
|
||||
furi_assert(str);
|
||||
|
||||
size_t len = strlen(str);
|
||||
struct usb_string_descriptor* dev_str_desc = malloc(len * 2 + 2);
|
||||
dev_str_desc->bLength = len * 2 + 2;
|
||||
dev_str_desc->bDescriptorType = USB_DTYPE_STRING;
|
||||
for(size_t i = 0; i < len; i++) dev_str_desc->wString[i] = str[i];
|
||||
|
||||
return dev_str_desc;
|
||||
}
|
||||
|
||||
static void ccid_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) {
|
||||
UNUSED(intf);
|
||||
|
||||
FuriHalUsbCcidConfig* cfg = (FuriHalUsbCcidConfig*)ctx;
|
||||
|
||||
usb_dev = dev;
|
||||
|
||||
usb_ccid.dev_descr->iManufacturer = 0;
|
||||
usb_ccid.dev_descr->iProduct = 0;
|
||||
usb_ccid.str_manuf_descr = NULL;
|
||||
usb_ccid.str_prod_descr = NULL;
|
||||
usb_ccid.dev_descr->idVendor = CCID_VID_DEFAULT;
|
||||
usb_ccid.dev_descr->idProduct = CCID_PID_DEFAULT;
|
||||
|
||||
if(cfg != NULL) {
|
||||
usb_ccid.dev_descr->idVendor = cfg->vid;
|
||||
usb_ccid.dev_descr->idProduct = cfg->pid;
|
||||
|
||||
if(cfg->manuf[0] != '\0') {
|
||||
usb_ccid.str_manuf_descr = ccid_set_string_descr(cfg->manuf);
|
||||
usb_ccid.dev_descr->iManufacturer = UsbDevManuf;
|
||||
}
|
||||
|
||||
if(cfg->product[0] != '\0') {
|
||||
usb_ccid.str_prod_descr = ccid_set_string_descr(cfg->product);
|
||||
usb_ccid.dev_descr->iProduct = UsbDevProduct;
|
||||
}
|
||||
}
|
||||
|
||||
usbd_reg_config(dev, ccid_ep_config);
|
||||
usbd_reg_control(dev, ccid_control);
|
||||
|
||||
usbd_connect(dev, true);
|
||||
}
|
||||
|
||||
static void ccid_deinit(usbd_device* dev) {
|
||||
usbd_reg_config(dev, NULL);
|
||||
usbd_reg_control(dev, NULL);
|
||||
|
||||
free(usb_ccid.str_prod_descr);
|
||||
free(usb_ccid.str_serial_descr);
|
||||
}
|
||||
|
||||
static void ccid_on_wakeup(usbd_device* dev) {
|
||||
UNUSED(dev);
|
||||
connected = true;
|
||||
}
|
||||
|
||||
static void ccid_on_suspend(usbd_device* dev) {
|
||||
UNUSED(dev);
|
||||
connected = false;
|
||||
}
|
||||
|
||||
struct ccid_bulk_message_header {
|
||||
uint8_t bMessageType;
|
||||
uint32_t dwLength;
|
||||
uint8_t bSlot;
|
||||
uint8_t bSeq;
|
||||
} __attribute__((packed));
|
||||
|
||||
static struct rdr_to_pc_slot_status responseSlotStatus;
|
||||
static struct rdr_to_pc_data_block responseDataBlock;
|
||||
static struct rdr_to_pc_parameters_t0 responseParameters;
|
||||
uint8_t SendDataBlock[CCID_DATABLOCK_SIZE];
|
||||
|
||||
uint8_t CALLBACK_CCID_GetSlotStatus(uint8_t slot, uint8_t* error) {
|
||||
if(slot == CCID_SLOT_INDEX) {
|
||||
*error = CCID_ERROR_NOERROR;
|
||||
if(smartcard_inserted) {
|
||||
return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
|
||||
} else {
|
||||
return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_NOICCPRESENT;
|
||||
}
|
||||
} else {
|
||||
*error = CCID_ERROR_SLOTNOTFOUND;
|
||||
return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
CALLBACK_CCID_IccPowerOn(uint8_t slot, uint8_t* atrBuffer, uint32_t* atrlen, uint8_t* error) {
|
||||
if(slot == CCID_SLOT_INDEX) {
|
||||
*error = CCID_ERROR_NOERROR;
|
||||
if(smartcard_inserted) {
|
||||
if(callbacks[CCID_SLOT_INDEX] != NULL) {
|
||||
callbacks[CCID_SLOT_INDEX]->icc_power_on_callback(atrBuffer, atrlen, NULL);
|
||||
} else {
|
||||
return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR |
|
||||
CCID_ICCSTATUS_PRESENTANDINACTIVE;
|
||||
}
|
||||
|
||||
return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
|
||||
} else {
|
||||
return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_NOICCPRESENT;
|
||||
}
|
||||
} else {
|
||||
*error = CCID_ERROR_SLOTNOTFOUND;
|
||||
return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CALLBACK_CCID_XfrBlock(
|
||||
uint8_t slot,
|
||||
uint8_t* dataBlock,
|
||||
uint32_t* dataBlockLen,
|
||||
uint8_t* error) {
|
||||
if(slot == CCID_SLOT_INDEX) {
|
||||
*error = CCID_ERROR_NOERROR;
|
||||
if(smartcard_inserted) {
|
||||
if(callbacks[CCID_SLOT_INDEX] != NULL) {
|
||||
callbacks[CCID_SLOT_INDEX]->xfr_datablock_callback(dataBlock, dataBlockLen, NULL);
|
||||
} else {
|
||||
return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR |
|
||||
CCID_ICCSTATUS_PRESENTANDINACTIVE;
|
||||
}
|
||||
|
||||
return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
|
||||
} else {
|
||||
return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_NOICCPRESENT;
|
||||
}
|
||||
} else {
|
||||
*error = CCID_ERROR_SLOTNOTFOUND;
|
||||
return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_ccid_ccid_insert_smartcard() {
|
||||
smartcard_inserted = true;
|
||||
}
|
||||
|
||||
void furi_hal_ccid_ccid_remove_smartcard() {
|
||||
smartcard_inserted = false;
|
||||
}
|
||||
|
||||
void furi_hal_ccid_set_callbacks(CcidCallbacks* cb) {
|
||||
callbacks[CCID_SLOT_INDEX] = cb;
|
||||
}
|
||||
|
||||
static void ccid_rx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
|
||||
UNUSED(dev);
|
||||
UNUSED(event);
|
||||
UNUSED(ep);
|
||||
}
|
||||
|
||||
static void ccid_tx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
|
||||
UNUSED(dev);
|
||||
|
||||
if(event == usbd_evt_eprx) {
|
||||
if(connected == false) return;
|
||||
|
||||
struct ccid_bulk_message_header message;
|
||||
usbd_ep_read(usb_dev, ep, &message, sizeof(message));
|
||||
|
||||
uint8_t Status;
|
||||
uint8_t Error = CCID_ERROR_NOERROR;
|
||||
|
||||
uint32_t dataBlockLen = 0;
|
||||
uint8_t* dataBlockBuffer = NULL;
|
||||
|
||||
if(message.bMessageType == PC_TO_RDR_GETSLOTSTATUS) {
|
||||
responseSlotStatus.bMessageType = RDR_TO_PC_SLOTSTATUS;
|
||||
responseSlotStatus.dwLength = 0;
|
||||
responseSlotStatus.bSlot = message.bSlot;
|
||||
responseSlotStatus.bSeq = message.bSeq;
|
||||
|
||||
responseSlotStatus.bClockStatus = 0;
|
||||
|
||||
Status = CALLBACK_CCID_GetSlotStatus(message.bSlot, &Error);
|
||||
|
||||
responseSlotStatus.bStatus = Status;
|
||||
responseSlotStatus.bError = Error;
|
||||
|
||||
usbd_ep_write(
|
||||
usb_dev, CCID_IN_EPADDR, &responseSlotStatus, sizeof(responseSlotStatus));
|
||||
} else if(message.bMessageType == PC_TO_RDR_ICCPOWERON) {
|
||||
responseDataBlock.bMessageType = RDR_TO_PC_DATABLOCK;
|
||||
responseDataBlock.bSlot = message.bSlot;
|
||||
responseDataBlock.bSeq = message.bSeq;
|
||||
responseDataBlock.bChainParameter = 0;
|
||||
|
||||
dataBlockLen = 0;
|
||||
dataBlockBuffer = (uint8_t*)SendDataBlock;
|
||||
Status = CALLBACK_CCID_IccPowerOn(
|
||||
message.bSlot, (uint8_t*)dataBlockBuffer, &dataBlockLen, &Error);
|
||||
|
||||
furi_assert(dataBlockLen < CCID_DATABLOCK_SIZE);
|
||||
responseDataBlock.dwLength = dataBlockLen;
|
||||
|
||||
responseSlotStatus.bStatus = Status;
|
||||
responseSlotStatus.bError = Error;
|
||||
|
||||
memcpy(responseDataBlock.abData, SendDataBlock, dataBlockLen);
|
||||
usbd_ep_write(
|
||||
usb_dev,
|
||||
CCID_IN_EPADDR,
|
||||
&responseDataBlock,
|
||||
sizeof(struct rdr_to_pc_data_block) + (sizeof(uint8_t) * dataBlockLen));
|
||||
} else if(message.bMessageType == PC_TO_RDR_ICCPOWEROFF) {
|
||||
responseSlotStatus.bMessageType = RDR_TO_PC_SLOTSTATUS;
|
||||
responseSlotStatus.dwLength = 0;
|
||||
responseSlotStatus.bSlot = message.bSlot;
|
||||
responseSlotStatus.bSeq = message.bSeq;
|
||||
|
||||
responseSlotStatus.bClockStatus = 0;
|
||||
|
||||
uint8_t Status;
|
||||
uint8_t Error = CCID_ERROR_NOERROR;
|
||||
Status = CALLBACK_CCID_GetSlotStatus(message.bSlot, &Error);
|
||||
|
||||
responseSlotStatus.bStatus = Status;
|
||||
responseSlotStatus.bError = Error;
|
||||
|
||||
usbd_ep_write(
|
||||
usb_dev, CCID_IN_EPADDR, &responseSlotStatus, sizeof(responseSlotStatus));
|
||||
} else if(message.bMessageType == PC_TO_RDR_SETPARAMETERS) {
|
||||
responseParameters.bMessageType = RDR_TO_PC_PARAMETERS;
|
||||
responseParameters.bSlot = message.bSlot;
|
||||
responseParameters.bSeq = message.bSeq;
|
||||
responseParameters.bProtocolNum = 0; //T0
|
||||
|
||||
uint8_t Status = CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR;
|
||||
uint8_t Error = CCID_ERROR_NOERROR;
|
||||
|
||||
responseParameters.bStatus = Status;
|
||||
responseParameters.bError = Error;
|
||||
|
||||
responseParameters.dwLength = sizeof(struct rdr_to_pc_parameters_t0);
|
||||
|
||||
usbd_ep_write(
|
||||
usb_dev, CCID_IN_EPADDR, &responseParameters, sizeof(responseParameters));
|
||||
} else if(message.bMessageType == PC_TO_RDR_XFRBLOCK) {
|
||||
responseDataBlock.bMessageType = RDR_TO_PC_DATABLOCK;
|
||||
responseDataBlock.bSlot = message.bSlot;
|
||||
responseDataBlock.bSeq = message.bSeq;
|
||||
responseDataBlock.bChainParameter = 0;
|
||||
|
||||
dataBlockLen = 0;
|
||||
dataBlockBuffer = (uint8_t*)SendDataBlock;
|
||||
Status = CALLBACK_CCID_XfrBlock(
|
||||
message.bSlot, (uint8_t*)dataBlockBuffer, &dataBlockLen, &Error);
|
||||
|
||||
furi_assert(dataBlockLen < CCID_DATABLOCK_SIZE);
|
||||
responseDataBlock.dwLength = dataBlockLen;
|
||||
|
||||
responseSlotStatus.bStatus = Status;
|
||||
responseSlotStatus.bError = Error;
|
||||
|
||||
memcpy(responseDataBlock.abData, SendDataBlock, dataBlockLen);
|
||||
usbd_ep_write(
|
||||
usb_dev,
|
||||
CCID_IN_EPADDR,
|
||||
&responseDataBlock,
|
||||
sizeof(struct rdr_to_pc_data_block) + (sizeof(uint8_t) * dataBlockLen));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure endpoints */
|
||||
static usbd_respond ccid_ep_config(usbd_device* dev, uint8_t cfg) {
|
||||
switch(cfg) {
|
||||
case 0:
|
||||
/* deconfiguring device */
|
||||
usbd_ep_deconfig(dev, CCID_IN_EPADDR);
|
||||
usbd_ep_deconfig(dev, CCID_OUT_EPADDR);
|
||||
usbd_reg_endpoint(dev, CCID_IN_EPADDR, 0);
|
||||
usbd_reg_endpoint(dev, CCID_OUT_EPADDR, 0);
|
||||
return usbd_ack;
|
||||
case 1:
|
||||
/* configuring device */
|
||||
usbd_ep_config(dev, CCID_IN_EPADDR, USB_EPTYPE_BULK, CCID_EPSIZE);
|
||||
usbd_ep_config(dev, CCID_OUT_EPADDR, USB_EPTYPE_BULK, CCID_EPSIZE);
|
||||
usbd_reg_endpoint(dev, CCID_IN_EPADDR, ccid_rx_ep_callback);
|
||||
usbd_reg_endpoint(dev, CCID_OUT_EPADDR, ccid_tx_ep_callback);
|
||||
return usbd_ack;
|
||||
default:
|
||||
return usbd_fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Control requests handler */
|
||||
static usbd_respond ccid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) {
|
||||
UNUSED(callback);
|
||||
/* CDC control requests */
|
||||
if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
|
||||
(USB_REQ_INTERFACE | USB_REQ_CLASS) &&
|
||||
(req->wIndex == 0 || req->wIndex == 2)) {
|
||||
switch(req->bRequest) {
|
||||
case CCID_ABORT:
|
||||
return usbd_fail;
|
||||
case CCID_GET_CLOCK_FREQUENCIES:
|
||||
dev->status.data_ptr = (void*)&(ccid_cfg_desc.intf_0.ccid_desc.dwDefaultClock);
|
||||
dev->status.data_count = sizeof(ccid_cfg_desc.intf_0.ccid_desc.dwDefaultClock);
|
||||
return usbd_ack;
|
||||
default:
|
||||
return usbd_fail;
|
||||
}
|
||||
}
|
||||
return usbd_fail;
|
||||
}
|
||||
@ -35,6 +35,7 @@ struct STOP_EXTERNING_ME {};
|
||||
#include <furi_hal_vibro.h>
|
||||
#include <furi_hal_usb.h>
|
||||
#include <furi_hal_usb_hid.h>
|
||||
#include <furi_hal_usb_ccid.h>
|
||||
#include <furi_hal_uart.h>
|
||||
#include <furi_hal_info.h>
|
||||
#include <furi_hal_random.h>
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
/**
|
||||
* @file furi_hal_i2c.h
|
||||
* I2C HAL API
|
||||
* @file furi_hal_i2c.h I2C HAL API
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <furi_hal_i2c_config.h>
|
||||
|
||||
@ -13,6 +13,35 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Transaction beginning signal */
|
||||
typedef enum {
|
||||
/*!Begin the transaction by sending a START condition followed by the
|
||||
* address */
|
||||
FuriHalI2cBeginStart,
|
||||
/*!Begin the transaction by sending a RESTART condition followed by the
|
||||
* address
|
||||
* @note Must follow a transaction ended with
|
||||
* FuriHalI2cEndAwaitRestart */
|
||||
FuriHalI2cBeginRestart,
|
||||
/*!Continue the previous transaction with new data
|
||||
* @note Must follow a transaction ended with FuriHalI2cEndPause and
|
||||
* be of the same type (RX/TX) */
|
||||
FuriHalI2cBeginResume,
|
||||
} FuriHalI2cBegin;
|
||||
|
||||
/** Transaction end signal */
|
||||
typedef enum {
|
||||
/*!End the transaction by sending a STOP condition */
|
||||
FuriHalI2cEndStop,
|
||||
/*!End the transaction by clock stretching
|
||||
* @note Must be followed by a transaction using
|
||||
* FuriHalI2cBeginRestart */
|
||||
FuriHalI2cEndAwaitRestart,
|
||||
/*!Pauses the transaction by clock stretching
|
||||
* @note Must be followed by a transaction using FuriHalI2cBeginResume */
|
||||
FuriHalI2cEndPause,
|
||||
} FuriHalI2cEnd;
|
||||
|
||||
/** Early Init I2C */
|
||||
void furi_hal_i2c_init_early();
|
||||
|
||||
@ -22,78 +51,126 @@ void furi_hal_i2c_deinit_early();
|
||||
/** Init I2C */
|
||||
void furi_hal_i2c_init();
|
||||
|
||||
/** Acquire i2c bus handle
|
||||
/** Acquire I2C bus handle
|
||||
*
|
||||
* @return Instance of FuriHalI2cBus
|
||||
* @param handle Pointer to FuriHalI2cBusHandle instance
|
||||
*/
|
||||
void furi_hal_i2c_acquire(FuriHalI2cBusHandle* handle);
|
||||
|
||||
/** Release i2c bus handle
|
||||
*
|
||||
* @param bus instance of FuriHalI2cBus aquired in `furi_hal_i2c_acquire`
|
||||
/** Release I2C bus handle
|
||||
*
|
||||
* @param handle Pointer to FuriHalI2cBusHandle instance acquired in
|
||||
* `furi_hal_i2c_acquire`
|
||||
*/
|
||||
void furi_hal_i2c_release(FuriHalI2cBusHandle* handle);
|
||||
|
||||
/** Perform I2C tx transfer
|
||||
/** Perform I2C TX transfer
|
||||
*
|
||||
* @param handle pointer to FuriHalI2cBusHandle instance
|
||||
* @param handle Pointer to FuriHalI2cBusHandle instance
|
||||
* @param address I2C slave address
|
||||
* @param data pointer to data buffer
|
||||
* @param size size of data buffer
|
||||
* @param timeout timeout in ticks
|
||||
* @param data Pointer to data buffer
|
||||
* @param size Size of data buffer
|
||||
* @param timeout Timeout in milliseconds
|
||||
*
|
||||
* @return true on successful transfer, false otherwise
|
||||
*/
|
||||
bool furi_hal_i2c_tx(
|
||||
FuriHalI2cBusHandle* handle,
|
||||
const uint8_t address,
|
||||
uint8_t address,
|
||||
const uint8_t* data,
|
||||
const uint8_t size,
|
||||
size_t size,
|
||||
uint32_t timeout);
|
||||
|
||||
/** Perform I2C rx transfer
|
||||
/**
|
||||
* Perform I2C TX transfer, with additional settings.
|
||||
*
|
||||
* @param handle pointer to FuriHalI2cBusHandle instance
|
||||
* @param handle Pointer to FuriHalI2cBusHandle instance
|
||||
* @param address I2C slave address
|
||||
* @param data pointer to data buffer
|
||||
* @param size size of data buffer
|
||||
* @param timeout timeout in ticks
|
||||
* @param ten_bit Whether the address is 10 bits wide
|
||||
* @param data Pointer to data buffer
|
||||
* @param size Size of data buffer
|
||||
* @param begin How to begin the transaction
|
||||
* @param end How to end the transaction
|
||||
* @param timer Timeout timer
|
||||
*
|
||||
* @return true on successful transfer, false otherwise
|
||||
*/
|
||||
bool furi_hal_i2c_tx_ext(
|
||||
FuriHalI2cBusHandle* handle,
|
||||
uint16_t address,
|
||||
bool ten_bit,
|
||||
const uint8_t* data,
|
||||
size_t size,
|
||||
FuriHalI2cBegin begin,
|
||||
FuriHalI2cEnd end,
|
||||
uint32_t timeout);
|
||||
|
||||
/** Perform I2C RX transfer
|
||||
*
|
||||
* @param handle Pointer to FuriHalI2cBusHandle instance
|
||||
* @param address I2C slave address
|
||||
* @param data Pointer to data buffer
|
||||
* @param size Size of data buffer
|
||||
* @param timeout Timeout in milliseconds
|
||||
*
|
||||
* @return true on successful transfer, false otherwise
|
||||
*/
|
||||
bool furi_hal_i2c_rx(
|
||||
FuriHalI2cBusHandle* handle,
|
||||
const uint8_t address,
|
||||
uint8_t address,
|
||||
uint8_t* data,
|
||||
const uint8_t size,
|
||||
size_t size,
|
||||
uint32_t timeout);
|
||||
|
||||
/** Perform I2C tx and rx transfers
|
||||
/** Perform I2C RX transfer, with additional settings.
|
||||
*
|
||||
* @param handle pointer to FuriHalI2cBusHandle instance
|
||||
* @param handle Pointer to FuriHalI2cBusHandle instance
|
||||
* @param address I2C slave address
|
||||
* @param tx_data pointer to tx data buffer
|
||||
* @param tx_size size of tx data buffer
|
||||
* @param rx_data pointer to rx data buffer
|
||||
* @param rx_size size of rx data buffer
|
||||
* @param timeout timeout in ticks
|
||||
* @param ten_bit Whether the address is 10 bits wide
|
||||
* @param data Pointer to data buffer
|
||||
* @param size Size of data buffer
|
||||
* @param begin How to begin the transaction
|
||||
* @param end How to end the transaction
|
||||
* @param timer Timeout timer
|
||||
*
|
||||
* @return true on successful transfer, false otherwise
|
||||
*/
|
||||
bool furi_hal_i2c_rx_ext(
|
||||
FuriHalI2cBusHandle* handle,
|
||||
uint16_t address,
|
||||
bool ten_bit,
|
||||
uint8_t* data,
|
||||
size_t size,
|
||||
FuriHalI2cBegin begin,
|
||||
FuriHalI2cEnd end,
|
||||
uint32_t timeout);
|
||||
|
||||
/** Perform I2C TX and RX transfers
|
||||
*
|
||||
* @param handle Pointer to FuriHalI2cBusHandle instance
|
||||
* @param address I2C slave address
|
||||
* @param tx_data Pointer to TX data buffer
|
||||
* @param tx_size Size of TX data buffer
|
||||
* @param rx_data Pointer to RX data buffer
|
||||
* @param rx_size Size of RX data buffer
|
||||
* @param timeout Timeout in milliseconds
|
||||
*
|
||||
* @return true on successful transfer, false otherwise
|
||||
*/
|
||||
bool furi_hal_i2c_trx(
|
||||
FuriHalI2cBusHandle* handle,
|
||||
const uint8_t address,
|
||||
uint8_t address,
|
||||
const uint8_t* tx_data,
|
||||
const uint8_t tx_size,
|
||||
size_t tx_size,
|
||||
uint8_t* rx_data,
|
||||
const uint8_t rx_size,
|
||||
size_t rx_size,
|
||||
uint32_t timeout);
|
||||
|
||||
/** Check if I2C device presents on bus
|
||||
*
|
||||
* @param handle pointer to FuriHalI2cBusHandle instance
|
||||
* @param i2c_addr I2C slave address
|
||||
* @param timeout timeout in ticks
|
||||
* @param handle Pointer to FuriHalI2cBusHandle instance
|
||||
* @param i2c_addr I2C slave address
|
||||
* @param timeout Timeout in milliseconds
|
||||
*
|
||||
* @return true if device present and is ready, false otherwise
|
||||
*/
|
||||
@ -101,11 +178,11 @@ bool furi_hal_i2c_is_device_ready(FuriHalI2cBusHandle* handle, uint8_t i2c_addr,
|
||||
|
||||
/** Perform I2C device register read (8-bit)
|
||||
*
|
||||
* @param handle pointer to FuriHalI2cBusHandle instance
|
||||
* @param i2c_addr I2C slave address
|
||||
* @param reg_addr register address
|
||||
* @param data pointer to register value
|
||||
* @param timeout timeout in ticks
|
||||
* @param handle Pointer to FuriHalI2cBusHandle instance
|
||||
* @param i2c_addr I2C slave address
|
||||
* @param reg_addr Register address
|
||||
* @param data Pointer to register value
|
||||
* @param timeout Timeout in milliseconds
|
||||
*
|
||||
* @return true on successful transfer, false otherwise
|
||||
*/
|
||||
@ -118,11 +195,11 @@ bool furi_hal_i2c_read_reg_8(
|
||||
|
||||
/** Perform I2C device register read (16-bit)
|
||||
*
|
||||
* @param handle pointer to FuriHalI2cBusHandle instance
|
||||
* @param i2c_addr I2C slave address
|
||||
* @param reg_addr register address
|
||||
* @param data pointer to register value
|
||||
* @param timeout timeout in ticks
|
||||
* @param handle Pointer to FuriHalI2cBusHandle instance
|
||||
* @param i2c_addr I2C slave address
|
||||
* @param reg_addr Register address
|
||||
* @param data Pointer to register value
|
||||
* @param timeout Timeout in milliseconds
|
||||
*
|
||||
* @return true on successful transfer, false otherwise
|
||||
*/
|
||||
@ -135,12 +212,12 @@ bool furi_hal_i2c_read_reg_16(
|
||||
|
||||
/** Perform I2C device memory read
|
||||
*
|
||||
* @param handle pointer to FuriHalI2cBusHandle instance
|
||||
* @param i2c_addr I2C slave address
|
||||
* @param mem_addr memory start address
|
||||
* @param data pointer to data buffer
|
||||
* @param len size of data buffer
|
||||
* @param timeout timeout in ticks
|
||||
* @param handle Pointer to FuriHalI2cBusHandle instance
|
||||
* @param i2c_addr I2C slave address
|
||||
* @param mem_addr Memory start address
|
||||
* @param data Pointer to data buffer
|
||||
* @param len Size of data buffer
|
||||
* @param timeout Timeout in milliseconds
|
||||
*
|
||||
* @return true on successful transfer, false otherwise
|
||||
*/
|
||||
@ -149,16 +226,16 @@ bool furi_hal_i2c_read_mem(
|
||||
uint8_t i2c_addr,
|
||||
uint8_t mem_addr,
|
||||
uint8_t* data,
|
||||
uint8_t len,
|
||||
size_t len,
|
||||
uint32_t timeout);
|
||||
|
||||
/** Perform I2C device register write (8-bit)
|
||||
*
|
||||
* @param handle pointer to FuriHalI2cBusHandle instance
|
||||
* @param i2c_addr I2C slave address
|
||||
* @param reg_addr register address
|
||||
* @param data register value
|
||||
* @param timeout timeout in ticks
|
||||
* @param handle Pointer to FuriHalI2cBusHandle instance
|
||||
* @param i2c_addr I2C slave address
|
||||
* @param reg_addr Register address
|
||||
* @param data Register value
|
||||
* @param timeout Timeout in milliseconds
|
||||
*
|
||||
* @return true on successful transfer, false otherwise
|
||||
*/
|
||||
@ -171,11 +248,11 @@ bool furi_hal_i2c_write_reg_8(
|
||||
|
||||
/** Perform I2C device register write (16-bit)
|
||||
*
|
||||
* @param handle pointer to FuriHalI2cBusHandle instance
|
||||
* @param i2c_addr I2C slave address
|
||||
* @param reg_addr register address
|
||||
* @param data register value
|
||||
* @param timeout timeout in ticks
|
||||
* @param handle Pointer to FuriHalI2cBusHandle instance
|
||||
* @param i2c_addr I2C slave address
|
||||
* @param reg_addr Register address
|
||||
* @param data Register value
|
||||
* @param timeout Timeout in milliseconds
|
||||
*
|
||||
* @return true on successful transfer, false otherwise
|
||||
*/
|
||||
@ -188,12 +265,12 @@ bool furi_hal_i2c_write_reg_16(
|
||||
|
||||
/** Perform I2C device memory
|
||||
*
|
||||
* @param handle pointer to FuriHalI2cBusHandle instance
|
||||
* @param i2c_addr I2C slave address
|
||||
* @param mem_addr memory start address
|
||||
* @param data pointer to data buffer
|
||||
* @param len size of data buffer
|
||||
* @param timeout timeout in ticks
|
||||
* @param handle Pointer to FuriHalI2cBusHandle instance
|
||||
* @param i2c_addr I2C slave address
|
||||
* @param mem_addr Memory start address
|
||||
* @param data Pointer to data buffer
|
||||
* @param len Size of data buffer
|
||||
* @param timeout Timeout in milliseconds
|
||||
*
|
||||
* @return true on successful transfer, false otherwise
|
||||
*/
|
||||
@ -201,8 +278,8 @@ bool furi_hal_i2c_write_mem(
|
||||
FuriHalI2cBusHandle* handle,
|
||||
uint8_t i2c_addr,
|
||||
uint8_t mem_addr,
|
||||
uint8_t* data,
|
||||
uint8_t len,
|
||||
const uint8_t* data,
|
||||
size_t len,
|
||||
uint32_t timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -28,6 +28,7 @@ extern FuriHalUsbInterface usb_cdc_single;
|
||||
extern FuriHalUsbInterface usb_cdc_dual;
|
||||
extern FuriHalUsbInterface usb_hid;
|
||||
extern FuriHalUsbInterface usb_hid_u2f;
|
||||
extern FuriHalUsbInterface usb_ccid;
|
||||
|
||||
typedef enum {
|
||||
FuriHalUsbStateEventReset,
|
||||
|
||||
31
firmware/targets/furi_hal_include/furi_hal_usb_ccid.h
Normal file
31
firmware/targets/furi_hal_include/furi_hal_usb_ccid.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include "hid_usage_desktop.h"
|
||||
#include "hid_usage_button.h"
|
||||
#include "hid_usage_keyboard.h"
|
||||
#include "hid_usage_consumer.h"
|
||||
#include "hid_usage_led.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint16_t vid;
|
||||
uint16_t pid;
|
||||
char manuf[32];
|
||||
char product[32];
|
||||
} FuriHalUsbCcidConfig;
|
||||
|
||||
typedef struct {
|
||||
void (*icc_power_on_callback)(uint8_t* dataBlock, uint32_t* dataBlockLen, void* context);
|
||||
void (*xfr_datablock_callback)(uint8_t* dataBlock, uint32_t* dataBlockLen, void* context);
|
||||
} CcidCallbacks;
|
||||
|
||||
void furi_hal_ccid_set_callbacks(CcidCallbacks* cb);
|
||||
|
||||
void furi_hal_ccid_ccid_insert_smartcard();
|
||||
void furi_hal_ccid_ccid_remove_smartcard();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -1 +1 @@
|
||||
Subproject commit 9168e2a31db946326fb84016a74ea2ab5bf87f54
|
||||
Subproject commit 6ca2857519f996244f7b324dd227fdf0a075fffb
|
||||
@ -64,7 +64,6 @@ sources += [
|
||||
"stm32wb_copro/wpan/ble/core/auto/ble_l2cap_aci.c",
|
||||
"stm32wb_copro/wpan/ble/core/template/osal.c",
|
||||
"stm32wb_copro/wpan/utilities/dbg_trace.c",
|
||||
"stm32wb_copro/wpan/utilities/otp.c",
|
||||
"stm32wb_copro/wpan/utilities/stm_list.c",
|
||||
]
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit 6c9c54f05669b2c4d436df58bb691d3b0d7c86df
|
||||
Subproject commit bbccbefae26a2301b8a4b58e57ebdeb93c08269b
|
||||
@ -79,11 +79,19 @@ class FlipperApplication:
|
||||
fap_extbuild: List[ExternallyBuiltFile] = field(default_factory=list)
|
||||
fap_private_libs: List[Library] = field(default_factory=list)
|
||||
fap_file_assets: Optional[str] = None
|
||||
fal_embedded: bool = False
|
||||
# Internally used by fbt
|
||||
_appmanager: Optional["AppManager"] = None
|
||||
_appdir: Optional[object] = None
|
||||
_apppath: Optional[str] = None
|
||||
_plugins: List["FlipperApplication"] = field(default_factory=list)
|
||||
_assets_dirs: List[object] = field(default_factory=list)
|
||||
_section_fapmeta: Optional[object] = None
|
||||
_section_fapfileassets: Optional[object] = None
|
||||
|
||||
@property
|
||||
def embeds_plugins(self):
|
||||
return any(plugin.fal_embedded for plugin in self._plugins)
|
||||
|
||||
def supports_hardware_target(self, target: str):
|
||||
return target in self.targets or "all" in self.targets
|
||||
@ -137,6 +145,11 @@ class AppManager:
|
||||
raise FlipperManifestException(
|
||||
f"Plugin {kw.get('appid')} must have 'requires' in manifest"
|
||||
)
|
||||
else:
|
||||
if kw.get("fal_embedded"):
|
||||
raise FlipperManifestException(
|
||||
f"App {kw.get('appid')} cannot have fal_embedded set"
|
||||
)
|
||||
# Harmless - cdefines for external apps are meaningless
|
||||
# if apptype == FlipperAppType.EXTERNAL and kw.get("cdefines"):
|
||||
# raise FlipperManifestException(
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import hashlib
|
||||
import os
|
||||
import struct
|
||||
from typing import TypedDict
|
||||
from typing import TypedDict, List
|
||||
|
||||
|
||||
class File(TypedDict):
|
||||
@ -32,20 +32,19 @@ class FileBundler:
|
||||
u8[] file_content
|
||||
"""
|
||||
|
||||
def __init__(self, directory_path: str):
|
||||
self.directory_path = directory_path
|
||||
self.file_list: list[File] = []
|
||||
self.directory_list: list[Dir] = []
|
||||
self._gather()
|
||||
def __init__(self, assets_dirs: List[object]):
|
||||
self.src_dirs = list(assets_dirs)
|
||||
|
||||
def _gather(self):
|
||||
for root, dirs, files in os.walk(self.directory_path):
|
||||
def _gather(self, directory_path: str):
|
||||
if not os.path.isdir(directory_path):
|
||||
raise Exception(f"Assets directory {directory_path} does not exist")
|
||||
for root, dirs, files in os.walk(directory_path):
|
||||
for file_info in files:
|
||||
file_path = os.path.join(root, file_info)
|
||||
file_size = os.path.getsize(file_path)
|
||||
self.file_list.append(
|
||||
{
|
||||
"path": os.path.relpath(file_path, self.directory_path),
|
||||
"path": os.path.relpath(file_path, directory_path),
|
||||
"size": file_size,
|
||||
"content_path": file_path,
|
||||
}
|
||||
@ -57,15 +56,20 @@ class FileBundler:
|
||||
# os.path.getsize(os.path.join(dir_path, f)) for f in os.listdir(dir_path)
|
||||
# )
|
||||
self.directory_list.append(
|
||||
{
|
||||
"path": os.path.relpath(dir_path, self.directory_path),
|
||||
}
|
||||
{"path": os.path.relpath(dir_path, directory_path)}
|
||||
)
|
||||
|
||||
self.file_list.sort(key=lambda f: f["path"])
|
||||
self.directory_list.sort(key=lambda d: d["path"])
|
||||
|
||||
def _process_src_dirs(self):
|
||||
self.file_list: list[File] = []
|
||||
self.directory_list: list[Dir] = []
|
||||
for directory_path in self.src_dirs:
|
||||
self._gather(directory_path)
|
||||
|
||||
def export(self, target_path: str):
|
||||
self._process_src_dirs()
|
||||
self._md5_hash = hashlib.md5()
|
||||
with open(target_path, "wb") as f:
|
||||
# Write header magic and version
|
||||
|
||||
@ -3,7 +3,7 @@ import os
|
||||
import pathlib
|
||||
import shutil
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional, Dict, List
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
import SCons.Warnings
|
||||
from ansi.color import fg
|
||||
@ -32,11 +32,15 @@ class FlipperExternalAppInfo:
|
||||
|
||||
|
||||
class AppBuilder:
|
||||
@staticmethod
|
||||
def get_app_work_dir(env, app):
|
||||
return env["EXT_APPS_WORK_DIR"].Dir(app.appid)
|
||||
|
||||
def __init__(self, env, app):
|
||||
self.fw_env = env
|
||||
self.app = app
|
||||
self.ext_apps_work_dir = env.subst("$EXT_APPS_WORK_DIR")
|
||||
self.app_work_dir = os.path.join(self.ext_apps_work_dir, self.app.appid)
|
||||
self.ext_apps_work_dir = env["EXT_APPS_WORK_DIR"]
|
||||
self.app_work_dir = self.get_app_work_dir(env, app)
|
||||
self.app_alias = f"fap_{self.app.appid}"
|
||||
self.externally_built_files = []
|
||||
self.private_libs = []
|
||||
@ -83,9 +87,9 @@ class AppBuilder:
|
||||
return
|
||||
|
||||
fap_icons = self.app_env.CompileIcons(
|
||||
self.app_env.Dir(self.app_work_dir),
|
||||
self.app_work_dir,
|
||||
self.app._appdir.Dir(self.app.fap_icon_assets),
|
||||
icon_bundle_name=f"{self.app.fap_icon_assets_symbol if self.app.fap_icon_assets_symbol else self.app.appid }_icons",
|
||||
icon_bundle_name=f"{self.app.fap_icon_assets_symbol or self.app.appid }_icons",
|
||||
)
|
||||
self.app_env.Alias("_fap_icons", fap_icons)
|
||||
self.fw_env.Append(_APP_ICONS=[fap_icons])
|
||||
@ -95,7 +99,7 @@ class AppBuilder:
|
||||
self.private_libs.append(self._build_private_lib(lib_def))
|
||||
|
||||
def _build_private_lib(self, lib_def):
|
||||
lib_src_root_path = os.path.join(self.app_work_dir, "lib", lib_def.name)
|
||||
lib_src_root_path = self.app_work_dir.Dir("lib").Dir(lib_def.name)
|
||||
self.app_env.AppendUnique(
|
||||
CPPPATH=list(
|
||||
self.app_env.Dir(lib_src_root_path)
|
||||
@ -119,9 +123,7 @@ class AppBuilder:
|
||||
|
||||
private_lib_env = self.app_env.Clone()
|
||||
private_lib_env.AppendUnique(
|
||||
CCFLAGS=[
|
||||
*lib_def.cflags,
|
||||
],
|
||||
CCFLAGS=lib_def.cflags,
|
||||
CPPDEFINES=lib_def.cdefines,
|
||||
CPPPATH=list(
|
||||
map(
|
||||
@ -132,14 +134,17 @@ class AppBuilder:
|
||||
)
|
||||
|
||||
return private_lib_env.StaticLibrary(
|
||||
os.path.join(self.app_work_dir, lib_def.name),
|
||||
self.app_work_dir.File(lib_def.name),
|
||||
lib_sources,
|
||||
)
|
||||
|
||||
def _build_app(self):
|
||||
if self.app.fap_file_assets:
|
||||
self.app._assets_dirs = [self.app._appdir.Dir(self.app.fap_file_assets)]
|
||||
|
||||
self.app_env.Append(
|
||||
LIBS=[*self.app.fap_libs, *self.private_libs],
|
||||
CPPPATH=[self.app_env.Dir(self.app_work_dir), self.app._appdir],
|
||||
CPPPATH=[self.app_work_dir, self.app._appdir],
|
||||
)
|
||||
|
||||
app_sources = list(
|
||||
@ -155,32 +160,46 @@ class AppBuilder:
|
||||
|
||||
app_artifacts = FlipperExternalAppInfo(self.app)
|
||||
app_artifacts.debug = self.app_env.Program(
|
||||
os.path.join(self.ext_apps_work_dir, f"{self.app.appid}_d"),
|
||||
self.ext_apps_work_dir.File(f"{self.app.appid}_d.elf"),
|
||||
app_sources,
|
||||
APP_ENTRY=self.app.entry_point,
|
||||
)[0]
|
||||
|
||||
app_artifacts.compact = self.app_env.EmbedAppMetadata(
|
||||
os.path.join(self.ext_apps_work_dir, self.app.appid),
|
||||
self.ext_apps_work_dir.File(f"{self.app.appid}.fap"),
|
||||
app_artifacts.debug,
|
||||
APP=self.app,
|
||||
)[0]
|
||||
|
||||
if self.app.embeds_plugins:
|
||||
self.app._assets_dirs.append(self.app_work_dir.Dir("assets"))
|
||||
|
||||
app_artifacts.validator = self.app_env.ValidateAppImports(
|
||||
app_artifacts.compact
|
||||
)[0]
|
||||
|
||||
if self.app.apptype == FlipperAppType.PLUGIN:
|
||||
for parent_app_id in self.app.requires:
|
||||
fal_path = (
|
||||
f"apps_data/{parent_app_id}/plugins/{app_artifacts.compact.name}"
|
||||
)
|
||||
deployable = True
|
||||
# If it's a plugin for a non-deployable app, don't include it in the resources
|
||||
if parent_app := self.app._appmanager.get(parent_app_id):
|
||||
if not parent_app.is_default_deployable:
|
||||
deployable = False
|
||||
app_artifacts.dist_entries.append((deployable, fal_path))
|
||||
if self.app.fal_embedded:
|
||||
parent_app = self.app._appmanager.get(parent_app_id)
|
||||
if not parent_app:
|
||||
raise UserError(
|
||||
f"Embedded plugin {self.app.appid} requires unknown app {parent_app_id}"
|
||||
)
|
||||
self.app_env.Install(
|
||||
target=self.get_app_work_dir(self.app_env, parent_app)
|
||||
.Dir("assets")
|
||||
.Dir("plugins"),
|
||||
source=app_artifacts.compact,
|
||||
)
|
||||
else:
|
||||
fal_path = f"apps_data/{parent_app_id}/plugins/{app_artifacts.compact.name}"
|
||||
deployable = True
|
||||
# If it's a plugin for a non-deployable app, don't include it in the resources
|
||||
if parent_app := self.app._appmanager.get(parent_app_id):
|
||||
if not parent_app.is_default_deployable:
|
||||
deployable = False
|
||||
app_artifacts.dist_entries.append((deployable, fal_path))
|
||||
else:
|
||||
fap_path = f"apps/{self.app.fap_category}/{app_artifacts.compact.name}"
|
||||
app_artifacts.dist_entries.append(
|
||||
@ -194,7 +213,7 @@ class AppBuilder:
|
||||
# Extra things to clean up along with the app
|
||||
self.app_env.Clean(
|
||||
app_artifacts.debug,
|
||||
[*self.externally_built_files, self.app_env.Dir(self.app_work_dir)],
|
||||
[*self.externally_built_files, self.app_work_dir],
|
||||
)
|
||||
|
||||
# Create listing of the app
|
||||
@ -219,13 +238,10 @@ class AppBuilder:
|
||||
)
|
||||
|
||||
# Add dependencies on file assets
|
||||
if self.app.fap_file_assets:
|
||||
for assets_dir in self.app._assets_dirs:
|
||||
self.app_env.Depends(
|
||||
app_artifacts.compact,
|
||||
self.app_env.GlobRecursive(
|
||||
"*",
|
||||
self.app._appdir.Dir(self.app.fap_file_assets),
|
||||
),
|
||||
(assets_dir, self.app_env.GlobRecursive("*", assets_dir)),
|
||||
)
|
||||
|
||||
# Always run the validator for the app's binary when building the app
|
||||
@ -344,25 +360,26 @@ def embed_app_metadata_emitter(target, source, env):
|
||||
if app.apptype == FlipperAppType.PLUGIN:
|
||||
target[0].name = target[0].name.replace(".fap", ".fal")
|
||||
|
||||
target.append(env.File(source[0].abspath + _FAP_META_SECTION))
|
||||
app_work_dir = AppBuilder.get_app_work_dir(env, app)
|
||||
app._section_fapmeta = app_work_dir.File(_FAP_META_SECTION)
|
||||
target.append(app._section_fapmeta)
|
||||
|
||||
if app.fap_file_assets:
|
||||
target.append(env.File(source[0].abspath + _FAP_FILEASSETS_SECTION))
|
||||
# At this point, we haven't added dir with embedded plugins to _assets_dirs yet
|
||||
if app._assets_dirs or app.embeds_plugins:
|
||||
app._section_fapfileassets = app_work_dir.File(_FAP_FILEASSETS_SECTION)
|
||||
target.append(app._section_fapfileassets)
|
||||
|
||||
return (target, source)
|
||||
|
||||
|
||||
def prepare_app_files(target, source, env):
|
||||
def prepare_app_file_assets(target, source, env):
|
||||
files_section_node = next(
|
||||
filter(lambda t: t.name.endswith(_FAP_FILEASSETS_SECTION), target)
|
||||
)
|
||||
|
||||
app = env["APP"]
|
||||
directory = env.Dir(app._apppath).Dir(app.fap_file_assets)
|
||||
if not directory.exists():
|
||||
raise UserError(f"File asset directory {directory} does not exist")
|
||||
|
||||
bundler = FileBundler(directory.abspath)
|
||||
bundler = FileBundler(
|
||||
list(env.Dir(asset_dir).abspath for asset_dir in env["APP"]._assets_dirs)
|
||||
)
|
||||
bundler.export(files_section_node.abspath)
|
||||
|
||||
|
||||
@ -376,12 +393,14 @@ def generate_embed_app_metadata_actions(source, target, env, for_signature):
|
||||
objcopy_str = (
|
||||
"${OBJCOPY} "
|
||||
"--remove-section .ARM.attributes "
|
||||
"--add-section ${_FAP_META_SECTION}=${SOURCE}${_FAP_META_SECTION} "
|
||||
"--add-section ${_FAP_META_SECTION}=${APP._section_fapmeta} "
|
||||
)
|
||||
|
||||
if app.fap_file_assets:
|
||||
actions.append(Action(prepare_app_files, "$APPFILE_COMSTR"))
|
||||
objcopy_str += "--add-section ${_FAP_FILEASSETS_SECTION}=${SOURCE}${_FAP_FILEASSETS_SECTION} "
|
||||
if app._section_fapfileassets:
|
||||
actions.append(Action(prepare_app_file_assets, "$APPFILE_COMSTR"))
|
||||
objcopy_str += (
|
||||
"--add-section ${_FAP_FILEASSETS_SECTION}=${APP._section_fapfileassets} "
|
||||
)
|
||||
|
||||
objcopy_str += (
|
||||
"--set-section-flags ${_FAP_META_SECTION}=contents,noload,readonly,data "
|
||||
@ -470,7 +489,7 @@ def AddAppBuildTarget(env, appname, build_target_name):
|
||||
|
||||
def generate(env, **kw):
|
||||
env.SetDefault(
|
||||
EXT_APPS_WORK_DIR="${FBT_FAP_DEBUG_ELF_ROOT}",
|
||||
EXT_APPS_WORK_DIR=env.Dir(env["FBT_FAP_DEBUG_ELF_ROOT"]),
|
||||
APP_RUN_SCRIPT="${FBT_SCRIPT_DIR}/runfap.py",
|
||||
)
|
||||
if not env["VERBOSE"]:
|
||||
|
||||
@ -14,15 +14,15 @@ IWDGSTOP:0x1:rw
|
||||
IWDGSW:0x1:rw
|
||||
IPCCDBA:0x0:rw
|
||||
ESE:0x1:r
|
||||
SFSA:0xD5:r
|
||||
SFSA:0xD7:r
|
||||
FSD:0x0:r
|
||||
DDS:0x1:r
|
||||
C2OPT:0x1:r
|
||||
NBRSD:0x0:r
|
||||
SNBRSA:0xD:r
|
||||
SNBRSA:0xB:r
|
||||
BRSD:0x0:r
|
||||
SBRSA:0x12:r
|
||||
SBRV:0x35400:r
|
||||
SBRV:0x35C00:r
|
||||
PCROP1A_STRT:0x1FF:r
|
||||
PCROP1A_END:0x0:r
|
||||
PCROP_RDP:0x1:rw
|
||||
|
||||
@ -73,6 +73,9 @@ class Main(App):
|
||||
self.parser_generate.add_argument(
|
||||
"--I-understand-what-I-am-doing", dest="disclaimer", required=False
|
||||
)
|
||||
self.parser_generate.add_argument(
|
||||
"--stackversion", dest="stack_version", required=False, default=""
|
||||
)
|
||||
|
||||
self.parser_generate.set_defaults(func=self.generate)
|
||||
|
||||
@ -93,6 +96,13 @@ class Main(App):
|
||||
if not self.args.radiotype:
|
||||
raise ValueError("Missing --radiotype")
|
||||
radio_meta = CoproBinary(self.args.radiobin)
|
||||
if self.args.stack_version:
|
||||
actual_stack_version_str = f"{radio_meta.img_sig.version_major}.{radio_meta.img_sig.version_minor}.{radio_meta.img_sig.version_sub}"
|
||||
if actual_stack_version_str != self.args.stack_version:
|
||||
self.logger.error(
|
||||
f"Stack version mismatch: expected {self.args.stack_version}, actual {actual_stack_version_str}"
|
||||
)
|
||||
return 1
|
||||
radio_version = self.copro_version_as_int(radio_meta, self.args.radiotype)
|
||||
if (
|
||||
get_stack_type(self.args.radiotype) not in self.WHITELISTED_STACK_TYPES
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user