Выбросите. И поставьте хотя бы Keil. Бесплатная версия может отлаживать приложение размером до 32кБ. Зато в нём можно подсмотреть содержимое регистров, пройтись по памяти, заглянуть в значения переменных, пройтись по программе в пошаговом режиме, чтобы понять, что делает код, который ВЫ написали.
Вообще, я начинал с ассемблера под AVR. Ну так получилось. И моим первым проектом была отладочная плата для контроллера. Кусок текстолита, ZIF сокет, куча светодиодов на портах, и гнёзда для подключения, затем... затем прошло много времени и я взялся за более продвинутый чип ATMega1284p, который по началу тоже был замучан на ассемблере. Уже после я взялся за Си. Так что мне страшно смотреть на Ваш код.
Отладочная плата тогда выглядела как-то так: Спойлер
Вложение:
Комментарий к файлу: Дичь, но работало. Сама печатная плата - готовая. 20140106_160528.jpg [103.75 KiB]
Скачиваний: 50
Building RAM: ./Build/KeyBrain.elf text data bss dec hex filename 41740 20 85052 126812 1ef5c ./Build/KeyBrain.elf
Включая работу с сетью, DHCP, UART, сканер отпечатка пальцев, NTP, Telnet (хотя реализация топорная, но работает), FATFS + SDIO, FreeRTOS, и некоторое количество массивов с данными. Так что расслабьтесь, небольшой проект 32кБ не займёт.
Другой проект:
Код:
:~/MCU_Proj/STM32F030-EEPROM$ make Compiling: startup_stm32f030x8.s Compiling: system_stm32f0xx.c Compiling: main.c Compiling: diskio.c Compiling: ff.c Compiling: uSD_SPI.c Building: ./debug/ee_rw.elf text data bss dec hex filename 21568 1260 2776 25604 6404 ./debug/ee_rw.elf
LCD + FatFS + SPI uSD + Кнопки + чтение-запись внешней EEPROM, парсер/экспортер Intel HEX. Меню на обратных вызовах (кое-где крайне костыльная реализация, но работает). Чуть меньше 22кБ.
И это компилируется не Keil'овским компилятором, а обычным arm-none-eabi-gcc, хотя и с оптимизацией -Os.
[offtop]Я бы порекомендовал скачать eclipse, но его нужно настраивать под контроллер, искать .svd файлы, настраивать отладчик... муторно. У меня вообще make + gcc + gdb и в некоторых случаях отладка в том самом тормозном eclipse.[/offtop]
За основу был взят код передачи AlanDrakes с не большой переделкой, что бы действительно можно было использовать произвольный размер буфераСпойлерсам код
Код:
volatile uint8_t DMA_STATE=0; // Флаг работы DMA volatile uint32_t tty0_TX_POS=0; // Указатель позиции записи в буфер volatile uint32_t tty0_WR_POS=0; // Указатель позиции чтения из буфера (DMA) volatile uint8_t tty0_TX_BUF[32]={0}; // Размер буфера равным степени двойки, минимум 2
DMA1_Channel4->CNDTR = DataToSend; USART1->SR = ~(USART_SR_TC); // И только ПОСЛЕ этого включаем его. Да, странность. Но иначе он уходит в ошибку. DMA1_Channel4->CCR |= DMA_CCR1_EN; DMA_STATE |= DMA_tty0_TX_ACTIVE; }; }; // Если активен - сработает при вызове события завершения обмена. };
// Принимаем СТРОКУ символов с нуль-терминатором. void console_put(const char *text) { while(*text) { // Пока не нуль-терминатор while(tty0_TX_BUF[tty0_WR_POS & BUF_MASK]) { }; // цикл ожидания с проверкой на \0 tty0_TX_BUF[tty0_WR_POS & BUF_MASK] = *text; // Копируем данные в буфер text++; // Сдвигаем указатель текста. tty0_WR_POS++; // Сдвигаем указатель на 1 байт дальше. if((tty0_WR_POS & BUF_MASK) == 0) tty0_ActivateDMA(); }; // Запускаем. tty0_ActivateDMA(); };
Кому надо, можете оптимизироватьНу а теперь тестыСпойлерсам тестовый код
картинка В коде AlanDrakes при размере буфера в 256, было выведено последние 256 символов 627 символьной строки. Всего отправлено до моего теста 857 символов.
В моем тесте отправляется 2596 символов, вот код моего теста
В коде AlanDrakes при размере буфера в 256, было выведено последние 256 символов 627 символьной строки.
Собственно, об этом переполнении буфера я и предупреждал. Фактически, в буфер данные были положены, но их затёрло свежими. И это нормально для кольцевого буфера. Ещё можно извернуться, ускорив вывод в буфер другими методами, но игра не стоит свеч. В любом случае время передачи не станет меньше того, что требуется периферии, чтобы отправить данные в линию.
А у меня в проектах используется минимум 2к буфер под передачу, поскольку время от времени запись в него происходит крайне интенсивно. В частности, лог первичной инициализации может занимать почти весь буфер. В железке с кристаллом по больше - буфер передачи уже 4к.
Правда, рядом с буфером экрана в ~38кБ он смотрится мелковато.
void USART1_IRQHandler(){ if (USART1->SR & USART_SR_IDLE) { (void)USART1->DR; // Очистка флага IDLE. Мне лично кажется такой подход странным. static uint32_t DMA_BUF_START_LAST = 0; // Устранен Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement if ((sizeof(BoxCon_RX_BUF) - DMA1_Channel5->CNDTR) != DMA_BUF_START_LAST) { DMA_BUF_START[DMA_CURR_WR_BUF] = DMA_BUF_START_LAST; DMA_BUF_START_LAST = (sizeof(BoxCon_RX_BUF) - DMA1_Channel5->CNDTR); DMA_BUF_END[DMA_CURR_WR_BUF] = DMA_BUF_START_LAST; DMA_CURR_WR_BUF++; if (DMA_CURR_WR_BUF >= (MAX_DMA_BUFFERS_COUNT-1)) { DMA_CURR_WR_BUF = 0; }; }; } }
Код:
while(1) { static uint8_t DMA_CURR_RD_BUF = 0; // Устранен Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement while (DMA_CURR_RD_BUF != DMA_CURR_WR_BUF) { uint8_t b_start = DMA_BUF_START[DMA_CURR_RD_BUF]; // Копируем позиции начала uint8_t b_end = DMA_BUF_END[DMA_CURR_RD_BUF]; // И конца буфера // Переводим на следующий (но не проверяем его данные) DMA_CURR_RD_BUF++; if (DMA_CURR_RD_BUF >= (MAX_DMA_BUFFERS_COUNT-1)) DMA_CURR_RD_BUF = 0;
// сборка команды uint8_t len_buff = strlen(buff); // определяем длину
// если BkSp - сдвигаем назад if((buff[len_buff] == 0x08)|| (buff[len_buff] == 0x7f)){ // стираем символ // но не левее начала буфера if(len_buff > 0) buff[len_buff-1]=0; else buff[len_buff]=0; }
// если Enter - ввод закончен if(((buff[len_buff] == '\n') || (buff[len_buff] == '\r'))) { flag=1; buff[len_buff]=0; // стираем символ Enter, заменяем концом строки \0 } }
библиотека microrl оказалась слишком заумной свою написал
Что в итоге имеем: -прерывание по IDLE -поддерживается как по символьсный ввод, так и отправка строки по нажатию клавиши "Ввод" -примитивное редактирование при помощи клавиши backspace Длина команды ограничена 64 символами, учитывая нажатие клавиши backspace
Можете оптимизировать, или предлагать свои варианты.
Фактически, в буфер данные были положены, но их затёрло свежими. И это нормально для кольцевого буфера.
Нет, это не нормально, только представьте, что было бы с жестким диском компа или еще с чем.
Ну так если не следить за свободным местом - то нормально =] Где-то в другой версии кода, была проверка на наползание указателей друг на друга. Там в цикле записи процессор отправлялся в сон до следующего прерывания. Собственно, костыль.
Опять же подходим к тому условию - если есть куча свободной оперативки. Вот f030 мне не хватило оперативки, а хочется не большой выигрыш, пусть и маленький, но выигрыш. И опять же, с этим костылем 100% гарантия что все выведется, а не затрется часть.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 17
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения