Как стать автором
Обновить
48
0
Дмитрий @rus084

Программист микроконтроллеров

Отправить сообщение

в 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 раза медленнее при максимальном значении аргумента
, но не уверен насчет адекватности измерений

Насколько этот алгоритм быстрее простого цикла?


Написал код, измеряющий время


Код
include
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(); // начальное время


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 раза, но не уверен насчет адекватности измерений

Да, вы правы, действительно модулирует
схема на falstad


скрин схемы

в 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, могут возникнуть пересечения адресов переменных. Да и проще в настройках линкера убрать немного озу, чем еще и выделить отдельную секцию для отладчика.

Информация

В рейтинге
Не участвует
Откуда
Ставрополь, Ставропольский край, Россия
Дата рождения
Зарегистрирован
Активность