Кризис микроэлектроники во всей красе и на своей шкуре
https://habr.com/ru/company/flipperdevices/blog/567986/
https://habr.com/ru/company/flipperdevices/blog/567986/
Хабр
Flipper Zero — статус доставки и производства
Flipper Zero — проект карманного мультитула для хакеров в формфакторе тамагочи, который мы разрабатываем. Предыдущие посты [ 1 ],[ 2 ],[ 3 ],[ 4 ],[ 5 ],[ 6 ],[ 7 ],[ 8 ],[ 9 ],[ 10 ],[ 11 ],[ 12 ],[...
Мы тут немножко открылись, на пол-шишечки https://github.com/flipperdevices/flipperzero-firmware
GitHub
GitHub - flipperdevices/flipperzero-firmware: Flipper Zero firmware source code
Flipper Zero firmware source code. Contribute to flipperdevices/flipperzero-firmware development by creating an account on GitHub.
Forwarded from Меня заставили создать канал
This media is not supported in your browser
VIEW IN TELEGRAM
Держите небольшое демо работы Флиппера с метками 125 кГц, а также пример записи на Т5577.
Все эксперименты проводятся с капсулой, имплантированной мне в руку.
У капсулы плохая антенна, так что запись происходит не моментально, но есть идеи, как улучшить это со стороны Флиппера.
Все эксперименты проводятся с капсулой, имплантированной мне в руку.
У капсулы плохая антенна, так что запись происходит не моментально, но есть идеи, как улучшить это со стороны Флиппера.
Выкатил тут файловый менеджер для флиппера, не все работает, кнопки снизу не работают, терминал только для логов, не оптимизировано под мелкие дисплеи и в целом код грязноват, но уже можно загружать и скачивать файлы с\на флиппер.
https://drzlo13.github.io/flipper-uwu-fileman/
UwU
https://drzlo13.github.io/flipper-uwu-fileman/
UwU
По мотивам вчерашнего обсуждения в https://news.1rj.ru/str/theyforcedme/2895
Уточню что моя цель - писать код который легко поддерживать, дописывать и менять его логику, и это требование я выношу в основные.
Довольно частая ситуация при написании программы - захват ресурса и освобождение его при выходе из функции. Для примера ресурса возьмем память. (тут и далее я прошу учитывать что я ограничен в объеме текста, и между захватом - освобождением ресурса вполне могут быть страница-две кода)
Чтобы не отвлекать программиста на другие функции мы можем использовать что-то наподобие "анонимной функции", например цикл из одной итерации. Цикл из одной итерации может быть любого вида, while, for, но do {} while (false); это довольно распространенная и понятная идиома, не требующая дополнительных переменных.
Уточню что моя цель - писать код который легко поддерживать, дописывать и менять его логику, и это требование я выношу в основные.
Довольно частая ситуация при написании программы - захват ресурса и освобождение его при выходе из функции. Для примера ресурса возьмем память. (тут и далее я прошу учитывать что я ограничен в объеме текста, и между захватом - освобождением ресурса вполне могут быть страница-две кода)
void foo(){
// выделяем память
DataType* data = malloc(sizeof(Data));
// работаем с памятью
process(data);
// освобождаем память
free(data);
}
Пока что все выглядит ок. Но требования меняются, и теперь нам надо обрабатывать данные в зависимости от того что вернула предыдущая обработка.void foo(){
DataType* data = malloc(sizeof(Data));
if(process_1(data)){
if(process_2(data)){
if(process_3(data)){
process_4(data);
}
}
}
free(data);
}
Цикломатическая сложность растет, и если мы продолжим писать в этом же стиле - рано или поздно мы уйдем ifами за правый край экрана (ну или запутаемся в блоках). Код становится неприятно читать и сложно поддерживать, давайте его перепишем на множественный возврат из функции.void foo(){
DataType* data = malloc(sizeof(Data));
if(!process_1(data)){
free(data);
return;
}
if(!process_2(data)){
free(data);
return;
}
if(!process_3(data)){
free(data);
return;
}
process_4(data);
free(data);
}
Это выглядит и читается приемлимо, но поддерживать этот код стало еще сложнее, например очень легко можно забыть освободить память перед возвратом. Для борьбы с этим человечество придумало блоки finally и идиому "Получение ресурса есть инициализация" (RAII). К сожалению мы любим простреленные ноги и пишем на языке Си, в котором подобное невозможно реализовать не превратив код обмазанный макросами в некрономикоподобный диалект. Что же мы можем сделать?void foo(){
DataType* data = malloc(sizeof(Data));
if(!process_1(data)) goto finally;
if(!process_2(data)) goto finally;
if(!process_3(data)) goto finally;
process_4(data);
finally:
free(data);
}
К сожалению столь лаконичный код получился с использованием goto. Использование оператора goto в целом критикуется, так как программу с его использованием читать на порядки сложнее, как минимум неявны начала и концы переходов, для подробной критики см "Go To Statement Considered Harmful" Эдсгера Дейкстры. Нам нужен блок который бы исполнялся один раз и из которого мы можем выйти оператором отличным от goto, например возьмем отдельную функцию.void process_data(DataType* data){
assert(data);
if(!process_1(data)) return;
if(!process_2(data)) return;
if(!process_3(data)) return;
process_4(data);
}
void foo(){
DataType* data = malloc(sizeof(Data));
process_data(data);
free(data);
}
Приемлимый и поддерживаемый вариант, но требующий передачи ресурса в аргумент (а следовательно проверки аргумента) и требующий от программиста скакать по функциям, плюс загрязняющий область видимости.Чтобы не отвлекать программиста на другие функции мы можем использовать что-то наподобие "анонимной функции", например цикл из одной итерации. Цикл из одной итерации может быть любого вида, while, for, но do {} while (false); это довольно распространенная и понятная идиома, не требующая дополнительных переменных.
void foo(){
DataType* data = malloc(sizeof(Data));
do {
if(!process_1(data)) break;
if(!process_2(data)) break;
if(!process_3(data)) break;
process_4(data);
} while(false);
free(data);
}
В результате мы получили идиому которая явно указывает начало-конец перехода, выделяет блоком код который можно менять не отвлекаясь на освобождение ресурса, и в целом код который довольно лаконично выглядит.Telegram
Меня заставили создать канал
Вы когда-нибудь видели такие конструкции?
Я программировать практически не умею, увидела такое впервые. Высший пилотаж 🤯
Я программировать практически не умею, увидела такое впервые. Высший пилотаж 🤯
🔥6
Сегодня очень простенькое про эмбед. Часто вижу вопросы "Как мне сделать так чтобы функцию прерывания не пришлось определять в моей библиотеке".
У нас в флиппере довольно большая и сложная прошивка, которая требует в разные моменты времени разных функций-обработчиков прерываний. Это устроено следующим образом.
Есть статический указатель на функцию:
Ознакомиться с полным кодом можно тут:
https://github.com/flipperdevices/flipperzero-firmware/blob/dev/firmware/targets/f7/furi-hal/furi-hal-interrupt.c
https://github.com/flipperdevices/flipperzero-firmware/blob/dev/firmware/targets/f7/furi-hal/furi-hal-interrupt.h
У нас в флиппере довольно большая и сложная прошивка, которая требует в разные моменты времени разных функций-обработчиков прерываний. Это устроено следующим образом.
Есть статический указатель на функцию:
typedef void (*FuriHalInterruptISR)();Есть функция которая устанавливает этот указатель:
volatile FuriHalInterruptISR furi_hal_tim_tim1_isr = NULL;
void furi_hal_interrupt_set_timer_isr(TIM_TypeDef* timer, FuriHalInterruptISR isr) {
if (timer == TIM1) {
furi_hal_tim_tim1_isr = isr;
}
}
И в функции прерывания мы просто вызываем этот указатель если он установлен:/* Timer 1 Update */Это позволяет в любом месте программы установить вашу функцию в прерывание, не трогая сам код прерывания:
void TIM1_UP_TIM16_IRQHandler(void) {
if (furi_hal_tim_tim1_isr) {
furi_hal_tim_tim1_isr();
}
}
furi_hal_interrupt_set_timer_isr(TIM1, furi_hal_irda_tim_rx_isr);И даже если нужно, очистить прерывание от выполнения вашей функции:
furi_hal_interrupt_set_timer_isr(TIM1, NULL);ВАЖНО. Этот подход подразумевает что в момент установки\очистки прерывания соответствующая периферия выключена, так как установка указателя не атомарна. Функция которая была бы защищена от этого должна оборачивать код в критическую секцию, запрещая вызов прерываний:
void furi_hal_interrupt_set_timer_isr(TIM_TypeDef* timer, FuriHalInterruptISR isr) {
__disable_irq();
if (timer == TIM1) {
furi_hal_tim_tim1_isr = isr;
}
__enable_irq();
}
Так же этот подход можно расширить на установку нескольких функций в одно прерывание, но тут уже возникают вопросы к быстродействию и организации списка функций. Если интересно — могу расписать примерные подходы в отдельном посте.Ознакомиться с полным кодом можно тут:
https://github.com/flipperdevices/flipperzero-firmware/blob/dev/firmware/targets/f7/furi-hal/furi-hal-interrupt.c
https://github.com/flipperdevices/flipperzero-firmware/blob/dev/firmware/targets/f7/furi-hal/furi-hal-interrupt.h
Today I Learned
Можно увеличить выходной ток линейного регулятор добавлением резистора в параллель, но нагрузка должна кушать какой-то минимальный ток. Что и делали в древних схемах:
https://www.maximintegrated.com/en/design/technical-documents/app-notes/3/3865.html
Можно увеличить выходной ток линейного регулятор добавлением резистора в параллель, но нагрузка должна кушать какой-то минимальный ток. Что и делали в древних схемах:
https://www.maximintegrated.com/en/design/technical-documents/app-notes/3/3865.html