Jump to content

    

Salamander

Участник*
  • Content Count

    568
  • Joined

  • Last visited

Community Reputation

0 Обычный

About Salamander

  • Rank
    Знающий

Recent Profile Visitors

2249 profile views
  1. СТранная проблема... Использую DWT для микросекундных задержек и прочих шалостей. Инициализирую вот так uint32_t DWT_Delay_Init(void) { /* Disable TRC */ CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk; // ~0x01000000; /* Enable TRC */ CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // 0x01000000; DWT->LAR = 0xC5ACCE55; /* Disable clock cycle counter */ DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk; //~0x00000001; /* Enable clock cycle counter */ DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; //0x00000001; /* Reset the clock cycle counter value */ DWT->CYCCNT = 0; /* 3 NO OPERATION instructions */ __ASM volatile ("NOP"); __ASM volatile ("NOP"); __ASM volatile ("NOP"); /* Check if clock cycle counter has started */ if(DWT->CYCCNT) { return 0; /*clock cycle counter started*/ } else { return 1; /*clock cycle counter not started*/ } } Когда устройство под отладчиком - все работает. Стоит отсоединиться или просто стартовать без отладчика - в тех местах где программа ждет определенного значения счетчика, она зависает. Такое ощущение, что счетчик не считает. В чем может быть проблема? У меня проц STM32H743, на других процах такого не было. Точнее было на F746, но там это вылечилось добавлением в код DWT->LAR = 0xC5ACCE55; Тут же не прокатило. Что скажете?
  2. Сделал как в статье по ссылке char *strdup(const char *src) { size_t len = strlen(src) + 1; char *s = malloc(len); if (s == NULL) return NULL; return (char *)memcpy(s, src, len); } Схавал компилятор это. Дальше применяю: char months[] = "JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC"; char** tokens; tokens = str_split(months, ','); if (tokens) { int i; for (i = 0; *(tokens + i); i++) { printf("month=[%s]\n", *(tokens + i)); free(*(tokens + i)); } printf("\n"); free(tokens); } смотрю опосля в отладчике переменную tokens. В ней только один элемент - нулевой, он правильный. Хотя в цикле if (result) { size_t idx = 0; char* token = strtok(a_str, delim); while (token) { assert(idx < count); *(result + idx++) = strdup(token); token = strtok(0, delim); // ставлю брейкпоинт, token всегда правильный } assert(idx == count - 1); *(result + idx) = 0; } ставлю брейкоинт - token всегда правильный. Где косяк? Блин... не умею просто пользоваться отладчиком. Все нормально, все разбивается по разделителю, все читается.
  3. Эээ... Ммм... Если нетрудно, можно поподробнее, для тупых?
  4. Хм.. Вы указали на функцию, которая вызывается в той функции, что я привёл. Что скажете?
  5. Друзья еще вопрос. Нашел готовую функцию разбиения строки на подстроки по разделителю #include "stdio.h" #include "stdlib.h" #include "string.h" #include <assert.h> char** str_split(char* a_str, const char a_delim) { char** result = 0; size_t count = 0; char* tmp = a_str; char* last_comma = 0; char delim[2]; delim[0] = a_delim; delim[1] = 0; /* Count how many elements will be extracted. */ while (*tmp) { if (a_delim == *tmp) { count++; last_comma = tmp; } tmp++; } /* Add space for trailing token. */ count += last_comma < (a_str + strlen(a_str) - 1); /* Add space for terminating null string so caller knows where the list of returned strings ends. */ count++; result = malloc(sizeof(char*) * count); if (result) { size_t idx = 0; char* token = strtok(a_str, delim); while (token) { assert(idx < count); *(result + idx++) = strdup(token); token = strtok(0, delim); } assert(idx == count - 1); *(result + idx) = 0; } return result; } Проект с этой функцией компилируется, то есть никаких неизвестных функций в коде нет. Но вот при линковке получаю "Error: L6218E: Undefined symbol strdup (referred from main.o)." Блин... почему так? Стандартные же библиотеки, include прописаны, чего еще не хватает? у меня KEIL, если что. в string.h прототип strdup не описан. Я понимаю, что код писался под навороченные компиляторы и библиотеки к ним, а в KEIL они урезанные что ли.... но чем заменить эту функцию тогда?
  6. Решил костылем. Просто понял, что проблема действительно не имеет чисто математического решения. Заполнял экран, сверху вниз, а опосля включал скроллинг.
  7. Действительно, обнуляется. Ваш код (я уменьшил число строк до 15 для удобства) for(int i = 0; i<100; i++) { int j = i + str_buffer_write_position; if( j > 14) j -= 15; printf(&TERMINAL_TEXT[j][0]); } работает отлично. Если понаблюдать отладчиком то имеем полноценный кольцевой буфер. Но.... блин, вроде задача простая, а я что-то мозг весь сломал. Проблемы начинаются при чтении этого буфера. Хочу чтобы выглядело так - получили первую строку - она вывелась первой, получили вторую строку - на экране ниже первой появилась вторая, ну как при печати. А когда экран заполнен (15 строк) начинается скроллинг. По факту имеем следующее - получаем нулевую строку - она появляется в последней строке экрана, получаем следующую строку - нулевая перескакивает выше, внизу появляется новая. Если непонятно - я хочу, чтобы выглядело как при печати текста, а выглядит как финальные титры фильма. Почему так получается? Смотрите, получена первая строка, str_buffer_write_position=1. Начинаем выводить, заполняем первую строку дисплея. i=0, тогда j = i + str_buffer_write_position дает нам "1". И программа читает строку не из нулевого элемента массива, а из первого, а там пусто. И так дальше. И лишь когда мы выводим последнюю строку, у нас срабатывает if( j > 14) j -= 15; и мы получаем "указатель" на нулевой элемент массива. Логичная попытка сделать j = i + str_buffer_write_position -1 (уменьшили на единицу) - это работает только на первой строке. Как только появляется следующая строка, str_buffer_write_position увеличивается до 2 и тогда уже нужно отнимать 2. По сути - до того как экран заполнится полностью, j = i + str_buffer_write_position нужно заменить на j=i. И тогда работает. Но после заполнения экрана скроллинга нет по понятным причинам. Я конечно могу сделать проверку, поставить некий флажок после заполнения экрана, по срабатыванию которого меняется алгоритм, но мне это кажется "костылем". Хочется сделать изящно.... И не дает покоя мысль, что где-то ошибка, которую можно без костыля решить. ЧТо думаете?
  8. А зачем тут то остаток получать? Str_buffer_write_position на данном этапе гарантированно будет обнуляться после ста, за счёт предшествующего кода.
  9. Я понял в чем ваша идея. Я, по глупости, переписывался содержимое всего массива. Нулевой элемент затирал первыпэм, первый затирал вторым... последний - новым. И так 100 раз. Вы же предлагаете затирать новым элементом самый старый элемент. А чтобы не переписывать все остальные, просто сдвигать фокус чтения и нумероватт элементы от этого самого фокуса. То есть, скажем, получили мы 103 строку, она запишется в третий элемент массива. А чтобы вывести список строк, нам нужно читать с четвёртого по сотый, а дельше нулевой, первый и второй. И так далее. Я правильно понял?
  10. Идея не совсем понятна. Точнее понятна задцэумка - делать скроллинг не строк по 256 байт, а только указателей на них. Но дальше что? Сам исходный буфер тоже надо обновлять... А.. Погодите, кажется понял. Исходгэный буфер сделать кольцевым, а массивом указателей по нему как бы скользить. Чтобы последний элемент массива указателей всегда указывал на только что обновлённый элемент исходного буфера? Ещё есть сопутствующие вопрос. Скажите а что происходит, если при возникновении прерывания по приёму UART, оно успевает обработаться аппаратно, но не успевает программно? У меня пока что код скроллинг а находится в обработчике прерывания. Знаю, это не рационально, но скорость позволяла, между входящими посылка и времени достаточно. Но иногда бывает, что приходит две посылки подряд. Чтение из регистров UART я успеваю сделать, строку тоже успеваю, а вот когда идёт скроллинг - приходит следующая посылка. Выносить скроллинг за пределы обработчик прерывания? Хм... В принципе, с описанным вами вариантом кольцевого буфера это несложно.
  11. В общем я сделал вот так: #define RX_BUFFER_SIZE 256 uint8_t rx_buffer[RX_BUFFER_SIZE]; char TERMINAL_TEXT[100][256]; for(uint8_t i=0;i<255;i++) TERMINAL_TEXT[str_buffer_write_position][i]=rx_buffer[i]; Работает. Дальше мне понадобился скроллинг. То есть, есть 100 строк, появляется 101-я, я в цикле переписываю содержимое строки n+1 в строку n, и лишь потом пишу 101ю строку в ячейку №100. Сделал переписывание грубо, топорно, чтобы хотя бы посмотреть на текст на экране for(uint8_t i=0;i<100;i++) { for(uint8_t j=0;j<256;j++) TERMINAL_TEXT[i][j]=TERMINAL_TEXT[i+1][j] } Вопрос такой - сопряжен ли такой способ копирования с существенным замедлением быстродействия? Есть более быстрые способы?
  12. Господа, ситуация такая. Есть массив из 100 строк char* strings_buffer[10]={"1","2","3","4","5","6","7","8","9","10"}; Есть массив из обычных байт, в который принимаются данные по UART uint8_t rx_buffer[RX_BUFFER_SIZE] = {0,}; Когда ловится символ конца строки, то все содержимое rx_buffer с нулевого символа до того, где был пойман конец строки, должно копироваться в массив строк, точнее в один из его элементов под номером str_buffer_write_position. Я не стал заморачиваться с классическим кольцевым буфером, так как длина принимаемых строк гарантированно не превышает RX_BUFFER_SIZE, после захвата последовательности r\n индекс записи просто переносится на нулевой элемент rx_buffer for (uint8_t i=0;i<rx_write_buffer_position;i++) *strings_buffer[str_buffer_write_position]++=rx_buffer[i]; не работает, вылетает в хард (контроллер STM32) Что я делаю не так?
  13. Поковырялся - заработала вторая микросхема, но все равно какая-то лажа. Пишет нормально. А вот при чтении данные одной микросхемы смещены относительно данных другой. На один байт. Иными словами, DummyCycles в норме должен быть 8. Тогда нормально читается первая микросхема. Если поставить 6, то вторая микросхема начинает выдавать данные несмещенные, но при этом смещение возникает в первой микросхеме.....
  14. Друзья, вчитайтесь в описание ситуации: Контроллер STM32H743, на контроллере установлена QSPI W25Q128 - работает как одна микросхема, так и в режиме DualFlash. Меняю память на MT25QL128. Микросхемы разные, но я настроил параметры так, чтобы они были универсальны - то есть, без изменений в коде меняешь W25Q на MT25Q - все работает. Но почему-то это прокатывает только для режима одной микросхемы. В режиме DualFlash работает только W25Q, если меняю на MT25Q - вторая микросхема работать отказывается, выдает 0x88. Думал, что неисправна микросхема - менял местами первую и вторую, как выяснилось - сбоит не конкретная микросхема, а конкретное место, то есть Flash_ID 2. Грешил на проблемы в контроллере или плате - повторюсь, стоит снять обе микросхемы Mt25Q и поставить w25q - все работает. В чем может быть проблема?