ГОСТ шифр
В данной статье решается задача создания защищённого соединения с сервером госзакупок с минимизацией необходимости дальнейшей поддержки решения.
Читать далее →В данной статье решается задача создания защищённого соединения с сервером госзакупок с минимизацией необходимости дальнейшей поддержки решения.
Читать далее →В этой заметке я буду собирать ссылки на полезные и интересные материалы, обязательные к прочтению каждому использующему язык Си разработчику.
Различные нюансы:
Вводная: виртуальная машина с одним диском и корневой фс в lvm.
Задача: расширить корневую фс без остановки предоставляемого сервиса.
Решение:
qm resize 100 virtio0 +5Gpartprobe. Но начиная с RHEL6 она покажет шиш и откажется что-либо делать пока мы всё не остановим и не отмонтируем. Однако есть и обходной путь: создаём на этом же диске ещё один раздел с PhysicalVolume чтобы затем расширить нашу VolumeGroup на неё:
parted /dev/vda mkpart primary ext2 НАЧАЛО_РАЗДЕЛА -1
parted set НОМЕР_РАЗДЕЛА lvm on
Затем выполняем потенциально опасную операцию - обновляем наживую таблицу разделов. Существующие разделы при этом остаются на месте (даже если были изменены/удалены), новые же добавляются:
partx -a /dev/vdavgextend VolGroup /dev/vda3lvextend -l +100%FREE VolGroup/lv_rootresize2fs /dev/VolGroup/lv_rootГотово.
При разработке для встраиваемых систем зачастую приходится писать свои реализации printf и подобных функций. Однако для самописных функций не работает опция “-Wformat”: проверка вызовов на корректность аргументов (сверка количества и типов аргументов со строкой форматирования). Для решения этой проблемы в GCC существует специальный атрибут функции “format”. Пример применения:
int fmt( void (*put)(char,void**), void *putarg, const char *fmt, ... )
__attribute__ ((format (__printf__, 3, 4)));
Первым аргументом атрибута идёт тип проверки (printf, scanf, strftime, strfmon), второй - номер аргумента с форматом (нумерация с 1), третий - номер аргумента с которого начинается список аргументов (…).
Есть два пути получения лямбд в Си:
Использовать дополнительный препроцессор cmacro. Идея очень интересная, но, к сожалению, реализация подводит. У меня этот препроцессор не только спотыкался на простейших конструкциях (например, лямбда, возвращающая указатель), но и умудрялся портить совершенно сторонний код (“return -1” чудесным образом превращается в “return- 1”). Проект по всей видимости заброшен.
Использовать расширения компилятора GCC. Это простой и безболезненный путь если нет необходимости сохранять совместимость с другими компиляторами. Для этого варианта достаточно объявить макрос:
#define lambda(l_ret_type, l_arguments, l_body) \
({ \
l_ret_type l_anonymous_functions_name l_arguments \
l_body \
&l_anonymous_functions_name; \
})
Пример создания и использования лямбды:
printf("%s world\n", lambda(char*, (void), { return "Hello"; } )() );
Обратите внимание: GCC волен размещать код вложенных функций (и, как следствие, лямбд) в стеке!
Часто возникает необходимость зафиксировать состояние МК во время сбоя (деление на 0, разыменование нулевого указателя, обращение к невыровненному адресу и тысяча других возможностей прострелить себе ногу). И часто при этом нет возможности держать устройство с подключенным отладчиком.
В таких случаев поможет связка ПО CrashDebug и CrashCatcher. CrashCatcher - библиотека подключающаяся к прошивке МК. Она берёт на себя обработку исключения HardFault и вывод содержимого регистров и памяти на последовательный порт (либо любым другим реализованным программистом способом). Полученный по последовательному порту дамп сохраняется в файл и передаётся утилите CrashDebug, выступающей в роли target для GDB. Дальше уже можно работать любыми привычными средствами - консольным arm-none-eabi-gdb, ddd, либо даже Eclipse (через тип конфигурации “GDB Hardware Debug”).
Оба проекта имеют исчерпывающую документацию и достаточно легко интегрируются в существующий проект.
… то не забывайте перед калибровкой отключать DMA (ADC1->CFGR1 &= ~ADC_CFGR1_DMAEN) и сбрасывать значение счётчика DMA1_ChannelN->CNDTR.
static void adc_recalibrate( void )
{
ADC1->CR |= ADC_CR_ADSTP; // Stop current conversion
while( ADC1->CR & ADC_CR_ADSTP ); // .. and wait
ADC1->CFGR1 &= ~ADC_CFGR1_DMAEN; // Disable DMA req
ADC1->CR |= ADC_CR_ADDIS; // Disable ADC
while( ADC1->CR & ADC_CR_ADEN ); // .. and wait
DMA1_Channel1->CCR &= ~DMA_CCR_EN; // Stop DMA transfer
while( DMA1_Channel1->CCR & DMA_CCR_EN ); // .. and wait
ADC1->CR |= ADC_CR_ADCAL; // Start ADC calibration
while( ADC1->CR & ADC_CR_ADCAL ); // .. and wait
ADC1->CR |= ADC_CR_ADEN; // Enable ADC
while( !(ADC1->ISR & ADC_ISR_ADRDY) ); // .. and wait
ADC1->CFGR1 |= ADC_CFGR1_DMAEN; // Enable DMA req
ADC1->CR |= ADC_CR_ADSTART; // Start ADC conversion
DMA1_Channel1->CNDTR = ADC_CHAN_COUNT * ADC_FILTER_SIZE; // Set cycle size
DMA1_Channel1->CCR |= DMA_CCR_EN; // Start DMA transfer
}
Пример кода для STM32F030C8
Полдня убил на это - после повторного запуска АЦП (в режиме непрерывной оцифровки нескольких каналов) каналы путались местами. Из документации совершенно не очевидно что нужно не просто выключить канал DMA, но и выключить формирование DMA-запроса в самом АЦП.
Такие дела.
Для отладки RTOS помимо плагинов IDE можно использовать встроенные средства OpenOCD. На данный момент поддерживаются FreeRTOS, ChibiOS, eCos и другие.
Для использования этой функциональности нужно в параметры запуска openocd добавить следующую строку (для openocd 0.9 и stm32f4):
-c "stm32f4x.cpu configure -rtos auto"
В случае FreeRTOS версий старше 7.5.3 нужно выполнить дополнительные движения:
const volatile int __attribute__((used)) uxTopUsedPriority = configMAX_PRIORITIES;
-Wl,--undefined=uxTopUsedPriority
Быстрофикс зависших серверов:
/etc/init.d/ntp stop; date; date `date +"%m%d%H%M%C%y.%S"`; date; /etc/init.d/ntp start