Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into portasynthinca3/3958-s…
Browse files Browse the repository at this point in the history
…tdio-api-improvements
  • Loading branch information
skotopes committed Feb 21, 2025
2 parents 2848765 + 404764b commit 97ed625
Show file tree
Hide file tree
Showing 99 changed files with 2,461 additions and 692 deletions.
1 change: 1 addition & 0 deletions .vscode/example/settings.json.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"SConstruct": "python",
"*.fam": "python"
},
"clangd.checkUpdates": false,
"clangd.path": "${workspaceFolder}/toolchain/current/bin/clangd@FBT_PLATFORM_EXECUTABLE_EXT@",
"clangd.arguments": [
"--query-driver=**/arm-none-eabi-*",
Expand Down
7 changes: 5 additions & 2 deletions applications/debug/accessor/accessor_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <furi.h>
#include <furi_hal.h>
#include <stdarg.h>
#include <power/power_service/power.h>

void AccessorApp::run(void) {
AccessorEvent event;
Expand Down Expand Up @@ -35,16 +36,18 @@ AccessorApp::AccessorApp()
: text_store{0} {
notification = static_cast<NotificationApp*>(furi_record_open(RECORD_NOTIFICATION));
expansion = static_cast<Expansion*>(furi_record_open(RECORD_EXPANSION));
power = static_cast<Power*>(furi_record_open(RECORD_POWER));
onewire_host = onewire_host_alloc(&gpio_ibutton);
expansion_disable(expansion);
furi_hal_power_enable_otg();
power_enable_otg(power, true);
}

AccessorApp::~AccessorApp() {
furi_hal_power_disable_otg();
power_enable_otg(power, false);
expansion_enable(expansion);
furi_record_close(RECORD_EXPANSION);
furi_record_close(RECORD_NOTIFICATION);
furi_record_close(RECORD_POWER);
onewire_host_free(onewire_host);
}

Expand Down
2 changes: 2 additions & 0 deletions applications/debug/accessor/accessor_app.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <one_wire/one_wire_host.h>
#include <notification/notification_messages.h>
#include <expansion/expansion.h>
#include <power/power_service/power.h>

class AccessorApp {
public:
Expand Down Expand Up @@ -53,4 +54,5 @@ class AccessorApp {

NotificationApp* notification;
Expansion* expansion;
Power* power;
};
59 changes: 59 additions & 0 deletions applications/debug/crash_test/crash_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,49 @@ typedef enum {
CrashTestSubmenuAssertMessage,
CrashTestSubmenuCrash,
CrashTestSubmenuHalt,
CrashTestSubmenuHeapUnderflow,
CrashTestSubmenuHeapOverflow,
} CrashTestSubmenu;

static void crash_test_corrupt_heap_underflow(void) {
const size_t block_size = 1000;
const size_t underflow_size = 123;
uint8_t* block = malloc(block_size);

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow" // that's what we want!
memset(block - underflow_size, 0xDD, underflow_size); // -V769
#pragma GCC diagnostic pop

free(block); // should crash here (if compiled with DEBUG=1)

// If we got here, the heap wasn't able to detect our corruption and crash
furi_crash("Test failed, should've crashed with \"FreeRTOS Assert\" error");
}

static void crash_test_corrupt_heap_overflow(void) {
const size_t block_size = 1000;
const size_t overflow_size = 123;
uint8_t* block1 = malloc(block_size);
uint8_t* block2 = malloc(block_size);
memset(block2, 12, 34); // simulate use to avoid optimization // -V597 // -V1086

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow" // that's what we want!
memset(block1 + block_size, 0xDD, overflow_size); // -V769 // -V512
#pragma GCC diagnostic pop

uint8_t* block3 = malloc(block_size);
memset(block3, 12, 34); // simulate use to avoid optimization // -V597 // -V1086

free(block3); // should crash here (if compiled with DEBUG=1)
free(block2);
free(block1);

// If we got here, the heap wasn't able to detect our corruption and crash
furi_crash("Test failed, should've crashed with \"FreeRTOS Assert\" error");
}

static void crash_test_submenu_callback(void* context, uint32_t index) {
CrashTest* instance = (CrashTest*)context;
UNUSED(instance);
Expand All @@ -49,6 +90,12 @@ static void crash_test_submenu_callback(void* context, uint32_t index) {
case CrashTestSubmenuHalt:
furi_halt("Crash test: furi_halt");
break;
case CrashTestSubmenuHeapUnderflow:
crash_test_corrupt_heap_underflow();
break;
case CrashTestSubmenuHeapOverflow:
crash_test_corrupt_heap_overflow();
break;
default:
furi_crash();
}
Expand Down Expand Up @@ -94,6 +141,18 @@ CrashTest* crash_test_alloc(void) {
instance->submenu, "Crash", CrashTestSubmenuCrash, crash_test_submenu_callback, instance);
submenu_add_item(
instance->submenu, "Halt", CrashTestSubmenuHalt, crash_test_submenu_callback, instance);
submenu_add_item(
instance->submenu,
"Heap underflow",
CrashTestSubmenuHeapUnderflow,
crash_test_submenu_callback,
instance);
submenu_add_item(
instance->submenu,
"Heap overflow",
CrashTestSubmenuHeapOverflow,
crash_test_submenu_callback,
instance);

return instance;
}
Expand Down
98 changes: 89 additions & 9 deletions applications/debug/uart_echo/uart_echo.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
#define LINES_ON_SCREEN 6
#define COLUMNS_ON_SCREEN 21
#define DEFAULT_BAUD_RATE 230400
#define DEFAULT_DATA_BITS FuriHalSerialDataBits8
#define DEFAULT_PARITY FuriHalSerialParityNone
#define DEFAULT_STOP_BITS FuriHalSerialStopBits1

typedef struct UartDumpModel UartDumpModel;

Expand Down Expand Up @@ -49,11 +52,12 @@ typedef enum {
WorkerEventRxOverrunError = (1 << 4),
WorkerEventRxFramingError = (1 << 5),
WorkerEventRxNoiseError = (1 << 6),
WorkerEventRxParityError = (1 << 7),
} WorkerEventFlags;

#define WORKER_EVENTS_MASK \
(WorkerEventStop | WorkerEventRxData | WorkerEventRxIdle | WorkerEventRxOverrunError | \
WorkerEventRxFramingError | WorkerEventRxNoiseError)
WorkerEventRxFramingError | WorkerEventRxNoiseError | WorkerEventRxParityError)

const NotificationSequence sequence_notification = {
&message_display_backlight_on,
Expand All @@ -62,6 +66,13 @@ const NotificationSequence sequence_notification = {
NULL,
};

const NotificationSequence sequence_error = {
&message_display_backlight_on,
&message_red_255,
&message_delay_10,
NULL,
};

static void uart_echo_view_draw_callback(Canvas* canvas, void* _model) {
UartDumpModel* model = _model;

Expand Down Expand Up @@ -133,6 +144,9 @@ static void
if(event & FuriHalSerialRxEventOverrunError) {
flag |= WorkerEventRxOverrunError;
}
if(event & FuriHalSerialRxEventParityError) {
flag |= WorkerEventRxParityError;
}

furi_thread_flags_set(furi_thread_get_id(app->worker_thread), flag);
}
Expand Down Expand Up @@ -227,13 +241,21 @@ static int32_t uart_echo_worker(void* context) {
if(events & WorkerEventRxNoiseError) {
furi_hal_serial_tx(app->serial_handle, (uint8_t*)"\r\nDetect NE\r\n", 13);
}
if(events & WorkerEventRxParityError) {
furi_hal_serial_tx(app->serial_handle, (uint8_t*)"\r\nDetect PE\r\n", 13);
}
notification_message(app->notification, &sequence_error);
}
}

return 0;
}

static UartEchoApp* uart_echo_app_alloc(uint32_t baudrate) {
static UartEchoApp* uart_echo_app_alloc(
uint32_t baudrate,
FuriHalSerialDataBits data_bits,
FuriHalSerialParity parity,
FuriHalSerialStopBits stop_bits) {
UartEchoApp* app = malloc(sizeof(UartEchoApp));

app->rx_stream = furi_stream_buffer_alloc(2048, 1);
Expand Down Expand Up @@ -275,6 +297,7 @@ static UartEchoApp* uart_echo_app_alloc(uint32_t baudrate) {
app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
furi_check(app->serial_handle);
furi_hal_serial_init(app->serial_handle, baudrate);
furi_hal_serial_configure_framing(app->serial_handle, data_bits, parity, stop_bits);

furi_hal_serial_async_rx_start(app->serial_handle, uart_echo_on_irq_cb, app, true);

Expand Down Expand Up @@ -318,19 +341,76 @@ static void uart_echo_app_free(UartEchoApp* app) {
free(app);
}

// silences "same-assignment" false positives in the arg parser below
// -V::1048

int32_t uart_echo_app(void* p) {
uint32_t baudrate = DEFAULT_BAUD_RATE;
FuriHalSerialDataBits data_bits = DEFAULT_DATA_BITS;
FuriHalSerialParity parity = DEFAULT_PARITY;
FuriHalSerialStopBits stop_bits = DEFAULT_STOP_BITS;

if(p) {
const char* baudrate_str = p;
if(strint_to_uint32(baudrate_str, NULL, &baudrate, 10) != StrintParseNoError) {
FURI_LOG_E(TAG, "Invalid baudrate: %s", baudrate_str);
baudrate = DEFAULT_BAUD_RATE;
// parse argument
char* parse_ptr = p;
bool parse_success = false;

do {
if(strint_to_uint32(parse_ptr, &parse_ptr, &baudrate, 10) != StrintParseNoError) break;

if(*(parse_ptr++) != '_') break;

uint16_t data_bits_int;
if(strint_to_uint16(parse_ptr, &parse_ptr, &data_bits_int, 10) != StrintParseNoError)
break;
if(data_bits_int == 6)
data_bits = FuriHalSerialDataBits6;
else if(data_bits_int == 7)
data_bits = FuriHalSerialDataBits7;
else if(data_bits_int == 8)
data_bits = FuriHalSerialDataBits8;
else if(data_bits_int == 9)
data_bits = FuriHalSerialDataBits9;
else
break;

char parity_char = *(parse_ptr++);
if(parity_char == 'N')
parity = FuriHalSerialParityNone;
else if(parity_char == 'E')
parity = FuriHalSerialParityEven;
else if(parity_char == 'O')
parity = FuriHalSerialParityOdd;
else
break;

uint16_t stop_bits_int;
if(strint_to_uint16(parse_ptr, &parse_ptr, &stop_bits_int, 10) != StrintParseNoError)
break;
if(stop_bits_int == 5)
stop_bits = FuriHalSerialStopBits0_5;
else if(stop_bits_int == 1)
stop_bits = FuriHalSerialStopBits1;
else if(stop_bits_int == 15)
stop_bits = FuriHalSerialStopBits1_5;
else if(stop_bits_int == 2)
stop_bits = FuriHalSerialStopBits2;
else
break;

parse_success = true;
} while(0);

if(!parse_success) {
FURI_LOG_I(
TAG,
"Couldn't parse baud rate and framing (%s). Applying defaults (%d_8N1)",
(const char*)p,
DEFAULT_BAUD_RATE);
}
}

FURI_LOG_I(TAG, "Using baudrate: %lu", baudrate);

UartEchoApp* app = uart_echo_app_alloc(baudrate);
UartEchoApp* app = uart_echo_app_alloc(baudrate, data_bits, parity, stop_bits);
view_dispatcher_run(app->view_dispatcher);
uart_echo_app_free(app);
return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ tests.assert_eq(false, doesSdkSupport(["abobus", "other-nonexistent-feature"]));

tests.assert_eq("flipperdevices", flipper.firmwareVendor);
tests.assert_eq(0, flipper.jsSdkVersion[0]);
tests.assert_eq(2, flipper.jsSdkVersion[1]);
tests.assert_eq(3, flipper.jsSdkVersion[1]);
10 changes: 7 additions & 3 deletions applications/examples/example_thermo/example_thermo.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include <one_wire/maxim_crc.h>
#include <one_wire/one_wire_host.h>

#include <furi_hal_power.h>
#include <power/power_service/power.h>

#define UPDATE_PERIOD_MS 1000UL
#define TEXT_STORE_SIZE 64U
Expand Down Expand Up @@ -76,6 +76,7 @@ typedef struct {
FuriThread* reader_thread;
FuriMessageQueue* event_queue;
OneWireHost* onewire;
Power* power;
float temp_celsius;
bool has_device;
} ExampleThermoContext;
Expand Down Expand Up @@ -273,7 +274,7 @@ static void example_thermo_input_callback(InputEvent* event, void* ctx) {
/* Starts the reader thread and handles the input */
static void example_thermo_run(ExampleThermoContext* context) {
/* Enable power on external pins */
furi_hal_power_enable_otg();
power_enable_otg(context->power, true);

/* Configure the hardware in host mode */
onewire_host_start(context->onewire);
Expand Down Expand Up @@ -309,7 +310,7 @@ static void example_thermo_run(ExampleThermoContext* context) {
onewire_host_stop(context->onewire);

/* Disable power on external pins */
furi_hal_power_disable_otg();
power_enable_otg(context->power, false);
}

/******************** Initialisation & startup *****************************/
Expand All @@ -334,6 +335,8 @@ static ExampleThermoContext* example_thermo_context_alloc(void) {

context->onewire = onewire_host_alloc(&THERMO_GPIO_PIN);

context->power = furi_record_open(RECORD_POWER);

return context;
}

Expand All @@ -348,6 +351,7 @@ static void example_thermo_context_free(ExampleThermoContext* context) {
view_port_free(context->view_port);

furi_record_close(RECORD_GUI);
furi_record_close(RECORD_POWER);
}

/* The application's entry point. Execution starts from here. */
Expand Down
Loading

0 comments on commit 97ed625

Please sign in to comment.