в c файлах переменные являются глобальными (тоже что и static внутри объекта). Поэтому работать с большим числом структур conn чем 1 вряд-ли получится.
Чтобы этого избежать, нужно вносить все переменные внутрь структур. Придется изобретать полиморфизм в СИ. Но зачем?
В с++ происходит в точности тоже самое, но более красиво
полиморфизм в Си
// headers
struct conn {
void ( *connect ) ( const char *url );
char *( *read ) ( void );
};
struct conn_http {
// анонимная структура позволяет обращаться к ее полям, какбудто они есть в родительской структуре.
struct conn;
int sockfd;
};
struct conn_https {
struct conn;
int sockfd;
SSL *ssl;
};
// http.c
struct conn_http* init_http () {
struct conn_http* self = zalloc(sizeof(struct conn_http));
if (self)
{
conn->connect = connect_http;
conn->read = read_http;
}
return self;
}
// https.c
struct conn_https* init_https () {
struct conn_https* self = zalloc(sizeof(struct conn_https));
if (self)
{
conn->connect = connect_https;
conn->read = read_https;
}
return self;
}
// main.c
struct conn* conn;
int main ( int argc, char **argv ) {
// кастовать к "базовой структуре" не противозаконно, ее смещение внутри наследника равно 0
switch ( get_protocol ( ) ) {
case HTTP_PROTOCOL: conn = (struct conn*)init_http (); break;
case HTTPS_PROTOCOL: conn = (struct conn*)init_https (); break;
case ERROR_PROTOCOL: return -1;
}
conn->connect ( "www.google.com" );
char *data = conn->read ( );
free(conn);
}
Извините, время редактирования истекло, а сразу не увидел сломавшееся форматирование
Заголовок спойлера
#include <iostream>
#include <ctime>
uint32_t getHighBit_32(uint32_t x)
{
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x - (x >> 1);
}
uint32_t getBitCount_32(uint32_t x)
{
x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
return (x & 0x0000FFFF) + (x >> 16);
}
uint32_t getLog2_32(uint32_t x)
{
return getBitCount_32(getHighBit_32(x) - 1);
}
int getLog2Loop_32(uint32_t x)
{
int result = -1;
while (x)
{
x >>=1;
result++;
}
return result;
}
int main()
{
volatile int iterations = 2000000000;
volatile int value = 0x8;
int volatile temp;
unsigned int start_Log2 = clock(); // начальное время
for (int i = 0; i < iterations; i++)
{
temp = getLog2_32(value);
}
unsigned int end_Log2 = clock(); // начальное время
unsigned int start_Log2Loop = clock(); // начальное время
for (int i = 0; i < iterations; i++)
{
temp = getLog2Loop_32(value);
}
unsigned int end_Log2Loop = clock(); // начальное время
std::cout << "first algo time: " << end_Log2 - start_Log2 << "\n";
std::cout << "second algo time:" << end_Log2Loop - start_Log2Loop << "\n";
}
итоге простой цикл быстрее в 2 раза на меленьких значениях и в 4 раза медленнее при максимальном значении аргумента
, но не уверен насчет адекватности измерений
int getLog2Loop_32(uint32_t x)
{
int result = -1;
while (x)
{
x >>=1;
result++;
}
return result;
}
int main()
{
volatile int iterations = 2000000000;
volatile int value = 0x8;
int volatile temp;
unsigned int start_Log2 = clock(); // начальное время
for (int i = 0; i < iterations; i++)
{
temp = getLog2_32(value);
}
unsigned int end_Log2 = clock(); // начальное время
unsigned int start_Log2Loop = clock(); // начальное время
for (int i = 0; i < iterations; i++)
{
temp = getLog2Loop_32(value);
}
unsigned int end_Log2Loop = clock(); // начальное время
std::cout << "first algo time: " << end_Log2 - start_Log2 << "\n";
std::cout << "second algo time:" << end_Log2Loop - start_Log2Loop << "\n";
}
Вывод программы такой:
first algo time: 8179
second algo time:3771
В итоге простой цикл быстрее в 2 раза, но не уверен насчет адекватности измерений
в F4 серии нету встроенного операционника.
Способ, который вы предложили создаст сигнал на выходе, больше похожий на ШИМ. Тогда лучше используя 3 потока DMA и 2 таймера получить полноценный ШИМ сигнал на выходе MCO.
Первый таймер синхронизирован со вторым. По переполнению первого, через DMA в регистр CCR второго загружается новое значение ШИМ. По переполнению второго таймера в GPIO загружается выключение MCO, по событию сравнения одного из каналов загружается включение MCO.
Нет, сигнал генерируется непрерывно. Частота кадров если быть точным у меня равна 49,126Гц и не меняется.
Моменты когда на видео экран темнеет видны только на камеру. Это из-за того что кинескоп сильно мерцает и в 1 кадр видео может не попасть целый кадр телевизора.
На этом видео чуваки сняли телевизор на высокоскоростную камеру, где видно что в каждый момент времени светится только маленькая часть экрана
Весь смысл в том чтобы генерировать радиосигнал только средствами микроконтроллера без внешних генераторов.
Просто композитный сигнал — не интересно, его даже на pic16 можно сгенерировать
Надо попробовать
Ато в ДМВ диапазоне штук 5 гармоник можно принять крутя ручку настройки.
Еще есть странность: ЖК телевизор ни в какую не принимает этот сигнал ни в каком диапазоне
А вот если оставлять только DebugMon_Handler включенным, работает. При выходе из обработчика он выполняет одну инструкцию и возвращается обратно.
Т.е. команду пошагового выполнения реализовать удалось
Моя идеология модуля отладки — минимум затрачиваемых ресурсов и влияния на поведение отлаживаемой прошивки. Поэтому усложнять алгоритм не стоит.
Но не вижу ничего плохого в использовании таких алгоритмов в рабочих проектах.
Для эскейп-кодирования отправляемого сообщения мне в худшем случае нужен буфер удвоенного размера, ведь я заранее не знаю, сколько байт нужно будет эскапировать.
Вы читали мой код, в частности функцию tx_cb? Всё кодирование при отправке реализуется средствами конечного автомата, при этом его алгоритм проще некуда. Так-же и при приеме. В буфере лежат только полезные данные.
Да и в чем сложность? Crc не сошлось — цикл для поиска старта, сдвиг массива (один вызов std::rotate), запускаем основной автомат набора пакета.
Сложность в объеме и скорости выполнения кода. На стороне ПК это рабочий вариант, но не в МК.
В некоторых МК у модуля UART есть прерывание IDLE, наступает когда обнаружена пауза в потоке данных. Можно было бы использовать его и не использовать Esc-кодирование, но в STM32F7 нет такого прерывания у UARTа.
Можно вместо брейкпойнта и поллинг окончания операции сделать.
Поллинг будет забирать часть времени, что увеличит время заливки.
А в чем возникла проблема сделать шаг?
Тогда нужно реализовать определение текущей инструкции средствами МК. Ато вдруг это инструкция перехода?
Но есть другой способ: В регистре DEMCR есть бит MON_STEP. Но тут возникли проблемы. Если не выключить прерывания, программа всегда останавливается на первой инструкции любого из наступивших прерываний. А если их выключить, он больше не попадает в DebugMon_Handler
Единственно кажущийся рабочий вариант — эмулировать эту команду на стороне GDB сервера
Контрольная сумма — хорошая идея, нужно будет добавить.
Не представляю как можно используя CRC избавиться от escape-кодирования при условии что пакеты переменной длинны
Реверсил обмен в WireShark между IAR и openOCD. Но в моей конфигурации breakpoint окончания операции не срабатывает по какой-то причине.
Что-то похожее видел в PIC24 Programming Manual. Там можно либо вручную программатором писать флеш. Либо зашить загрузчик и работать с ним.
В той папке загрузчики внешней памяти, но никто же не мешает написать такой-же для внутренней.
Есть возможность загружать прошивки через GDB. IAR к примеру сперва загружает командами записи памяти boot в ОЗУ. Далее его алгоритм загружает куски прошивки в ОЗУ, устанавливает PC на адрес boot и ждет breakpointа окончания операции. В папке st-link utility есть примеры таких бутов с исходниками.
Отдельный протокол нет смысла придумывать, когда он уже есть в openOCD.
Если каждый раз перезаливать прошивку вместе с отладчиком, то не зачем.
А если отладчик будет работать еще и как booloader, могут возникнуть пересечения адресов переменных. Да и проще в настройках линкера убрать немного озу, чем еще и выделить отдельную секцию для отладчика.
Теперь они называются совсем по другому, "НЕХТА"
в c файлах переменные являются глобальными (тоже что и static внутри объекта). Поэтому работать с большим числом структур conn чем 1 вряд-ли получится.
Чтобы этого избежать, нужно вносить все переменные внутрь структур. Придется изобретать полиморфизм в СИ. Но зачем?
В с++ происходит в точности тоже самое, но более красиво
Извините, время редактирования истекло, а сразу не увидел сломавшееся форматирование
итоге простой цикл быстрее в 2 раза на меленьких значениях и в 4 раза медленнее при максимальном значении аргумента
, но не уверен насчет адекватности измерений
Насколько этот алгоритм быстрее простого цикла?
Написал код, измеряющий время
include
uint32_t getHighBit_32(uint32_t x)
{
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x — (x >> 1);
}
uint32_t getBitCount_32(uint32_t x)
{
x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
return (x & 0x0000FFFF) + (x >> 16);
}
uint32_t getLog2_32(uint32_t x)
{
return getBitCount_32(getHighBit_32(x) — 1);
}
int getLog2Loop_32(uint32_t x)
{
int result = -1;
while (x)
{
x >>=1;
result++;
}
return result;
}
int main()
{
volatile int iterations = 2000000000;
volatile int value = 0x8;
int volatile temp;
unsigned int start_Log2 = clock(); // начальное время
for (int i = 0; i < iterations; i++)
{
temp = getLog2_32(value);
}
unsigned int end_Log2 = clock(); // начальное время
}
Вывод программы такой:
first algo time: 8179
second algo time:3771
В итоге простой цикл быстрее в 2 раза, но не уверен насчет адекватности измерений
Да, вы правы, действительно модулирует
схема на falstad
в F4 серии нету встроенного операционника.
Способ, который вы предложили создаст сигнал на выходе, больше похожий на ШИМ. Тогда лучше используя 3 потока DMA и 2 таймера получить полноценный ШИМ сигнал на выходе MCO.
Первый таймер синхронизирован со вторым. По переполнению первого, через DMA в регистр CCR второго загружается новое значение ШИМ. По переполнению второго таймера в GPIO загружается выключение MCO, по событию сравнения одного из каналов загружается включение MCO.
Нет, сигнал генерируется непрерывно. Частота кадров если быть точным у меня равна 49,126Гц и не меняется.
Моменты когда на видео экран темнеет видны только на камеру. Это из-за того что кинескоп сильно мерцает и в 1 кадр видео может не попасть целый кадр телевизора.
На этом видео чуваки сняли телевизор на высокоскоростную камеру, где видно что в каждый момент времени светится только маленькая часть экрана
Весь смысл в том чтобы генерировать радиосигнал только средствами микроконтроллера без внешних генераторов.
Просто композитный сигнал — не интересно, его даже на pic16 можно сгенерировать
Возможно дело в том что я не генерирую уравнивающие импульсы в области кадрового синхроимпульса. В этой статье лучше описано как их формировать
Надо попробовать
Ато в ДМВ диапазоне штук 5 гармоник можно принять крутя ручку настройки.
Еще есть странность: ЖК телевизор ни в какую не принимает этот сигнал ни в каком диапазоне
А если сделать объединение букв в группы по типу кнопочных телефонов?
быстро набросал код, получилось вполне удобно управлять джойстиком
Т.е. команду пошагового выполнения реализовать удалось
Но не вижу ничего плохого в использовании таких алгоритмов в рабочих проектах.
Вы читали мой код, в частности функцию tx_cb? Всё кодирование при отправке реализуется средствами конечного автомата, при этом его алгоритм проще некуда. Так-же и при приеме. В буфере лежат только полезные данные.
Сложность в объеме и скорости выполнения кода. На стороне ПК это рабочий вариант, но не в МК.
В некоторых МК у модуля UART есть прерывание IDLE, наступает когда обнаружена пауза в потоке данных. Можно было бы использовать его и не использовать Esc-кодирование, но в STM32F7 нет такого прерывания у UARTа.
Поллинг будет забирать часть времени, что увеличит время заливки.
Тогда нужно реализовать определение текущей инструкции средствами МК. Ато вдруг это инструкция перехода?
Но есть другой способ: В регистре DEMCR есть бит MON_STEP. Но тут возникли проблемы. Если не выключить прерывания, программа всегда останавливается на первой инструкции любого из наступивших прерываний. А если их выключить, он больше не попадает в DebugMon_Handler
Единственно кажущийся рабочий вариант — эмулировать эту команду на стороне GDB сервера
Не представляю как можно используя CRC избавиться от escape-кодирования при условии что пакеты переменной длинны
Что-то похожее видел в PIC24 Programming Manual. Там можно либо вручную программатором писать флеш. Либо зашить загрузчик и работать с ним.
В той папке загрузчики внешней памяти, но никто же не мешает написать такой-же для внутренней.
Отдельный протокол нет смысла придумывать, когда он уже есть в openOCD.
А если отладчик будет работать еще и как booloader, могут возникнуть пересечения адресов переменных. Да и проще в настройках линкера убрать немного озу, чем еще и выделить отдельную секцию для отладчика.