Перейти к содержанию
    

SapegoAL

Свой
  • Постов

    2 807
  • Зарегистрирован

  • Посещение

Весь контент SapegoAL


  1. Ноль с переносом, а можно куда-нибудь положить примеры от st для 746 discovery? Был бы очень благодарен.
  2. STM32 и adesto AT45DB641E.

    Работал и работаю с этой памятью. Правда с 321. DMA не использовал. Надо было писать CRC, все попытки задействовать аппаратный CRC SPI 407 с учётом того, что надо: послать какие-то команды - читать готовность - cбросить CRC - передать блок данных - записать CRC.. Не увенчались успехом. Я уже сути не помню, по-моему там CRC как то лихо автоматически сбрасывается, а команды и готовность с неизвестным числом обращений вычленить не удавалось. Короче - от DMA пришлось отказаться. Остальное всё работало. Были задействованы 2 страницы. Когда чтение-модификация запись - то одна страница использовалась. Когда потоковая запись, то 2 страницы.
  3. Ну я так и задаю. У меня 407 проц. Я календарь веду. То есть я контролирую дни недели. И перехожу (если опция включена) на летнее/ зимнее время согласно принятому. времени перехода. Осуществляется это в диагностической задаче у меня. Сам переход выполняет проц аппаратно, но там тоже надо танцы с бубном делать. То есть в нужный момент включить признак, а потом выключить. Сам проц не переходит. У меня это контролируется в ТУ, поэтому проверяется на приёмочных и периодических испытаниях. В старом приборе записывались даты и время перехода таблично... )) Прикололся. )) Всё равно календарь веду, так я его вывожу одним из меню
  4. Тут ещё накладываются и своя невнимательность, и то, что они свои периферийные модули изменяют-дорабатывают от камня к камню. Так, к примеру RTC у F1 и F4 - небо и земля. А кое где видел такие отличия незаметные.. Переносишь библиотеку - не работает. Читаешь внимательно - диву даёшься.
  5. Я неоднократно наблюдал глюки отладчика Keil с фирменным родным ULINK в оплаченном пакете. (Проц lpc1765). В том числе и при выводе данных в окне периферии. Особенно криво он себя ведёт, ну например, если 2 одинаковых задачи запускаются (RTX). Откуда он при этом выводит данные в окно отладки вообще не понятно. В аналогичной ситуации IAR ведёт себя абсолютно корректно. Даже на сторонней ОСи. По моему это показатель. Объективно, я бы так сказал - периферия как периферия. Есть удачные решения - есть не очень. Но в целом мне она понравилась. С чем можно было бы согласится, что нет общего подхода к разным периферийным модулям. Но это просматривается почти во всех камнях. Единый подход более менее виден у LPC. Но и там есть к чему придраться. Наличие флагов, которые сбрасываются при чтении - это много где. Ситуация с MSP значительно хуже. Там часть прерываний сбрасывается путём чтения регистра источника, часть путём принудительного сброса флага, часть чтением спец регистра... Короче вообще бардак.
  6. Уважаемый Forger. Мы вас уже поняли. Надо проект обязательно переписать на C++. Обязательно использовать синглтоны. И, конечно, тогда никаких ошибок не будет. Потому что у программистов пишущих на С++ не бывает ошибок. Особенно у программистов пишущих на С++ и включающих в проект FreeRTOS и LwIP на Си. Понятно, что надо использовать статическое выделение памяти, так как динамическое это смерть. Хотелось бы спросить, а как быть с LwIP? Вы там тоже статическое выделение используете? Понятно что надо использовать стороннюю библиотеку.. Лучше брать PeriphLib или переключиться на HAL... Мы услышали. Спасибо. Не понятно, с кем вы здесь спорите? Со мной? Так у меня нет таких ошибок. По крайней мере на данном этапе. Надеюсь это понятно? А у топикстартера есть. И я пытаюсь ему помочь. Я не знаю в каком коллективе вы работаете, но иногда проект переписать нельзя. И этому может быть сто причин, как правило, все они лежат вне программирования... Например сроки, финансирование, малая вероятность того, что в новом проекте не будет других ошибок, или как минимум, отсутствие веры в это руководства. И так далее... Я просто не хочу вступать в полемику с вами. Я не всегда писал проекты по 2 года. Например был проект с экспортным автобусом маз. Дисплей 480x272 + светодиодные столбики + стрелки + 2 CAN и два проца в жёсткой связке LPC2478 + stm32f103 был написан за 2 месяца. Потому что законченное решение. А крупный проект - там проблема в том, что сотни параметров исходных, и в зависимости от этого работа прибора полностью меняется. Там объективно много работы. А писал я его в одиночку, попутно занимаясь другой работой. Может не стоит хаить человека, не зная реальной ситуации? Асмом я не пользуюсь. На плюсах пишу, но пока незначительный объём. Но мы сейчас не обо мне говорим. Надеюсь это понятно? Я прекрасно знаю о контроле стека и прочей ерунде... У меня, на лету определяется вылет если он происходит, диагностируется задаче и место откуда это происходит. Всё это запоминается происходит рестарт проца и информация записывается в виде ошибки с точным указанием времени. Поэтому... Давайте по делу. Есть что сказать топикстартеру, пожалуйста скажите. А тему про грамотный переход из С в С++ начните с чистого топика и поделитесь своим опытом построения. Многие с удовольствием это почитают. И я в том числе..
  7. Ну в принципе, здесь возможны 4 ошибки. 1. классическая, то есть глобальная переменная которая модифицируется в разных задачах или прерываниях при этом не предусмотрены средства контроля за этим. 2. неверная работа с указателем. 3. более сложная. Какой либо буфер выходит за пределы и портит указатель или переменную, а эта переменная уже начинает косячить.. 4. стек задачи выходит за пределы. Исходя из того, что порча происходит кратковременно, и потом ситуация восстанавливается, две последних маловероятны. А портится один и тот же участок?
  8. Очень очень давно разрабатывал модем. Появлялись сбои непонятные. Очень редкие... Примерно 1 сбой на 2 Мб передаваемых данных. Отладчика тогда не было как класса. По вероятности вычислил что ошибка возникает если приходит прерывание в каком-то месте головы. Осей тогда тоже не было. Сделал синхронный вывод инфы. Ну и обнаружил переменную. Дальнейшее было делом техники. На вашем месте я попробовал бы 1. добиться повторяемости ошибки 2. Выводил бы отладочную инфу по прерываниям и задачам (для локализации) 3. дальше - глубже залазил.
  9. Из сторонних библиотек только LwIP и FreeRTOS. Больше ничего нет. Я HAL не пользуюсь. Из HAL использовал только инициализацию CPU и шин переписанную и Ethernet подправленный. Строки, естественно считал по своим файлам. Нафига чужое считать. Проект реально большой. Я 2 года писал. Понятно, что попутно куча другой работы была. Поддержка старых приборов, всякие там сертификации, поездки .. )) Насчёт плюсов я так скажу. Это надо бы взять какой-нибудь камень ясный... Ну типа того же AVR. Ну чтобы ассемблер был такой, чтобы читался как роман... )) После чего наваять несколько простых проектов. Компильнуть и посмотреть чё получилось. Поиграться. Ну чтобы ясная картина появилась, во что превращается та хрень, что ты написал. Вот где на это время взять?
  10. На счёт грамотного проектирования - ктож с вами спорит. Только по моему опыту - это приходит с годами. Самые тяжёлые - ошибки в проектировании, так как они обнаруживаются на поздних этапах разработки и влекут за собой значительную переработку проекта... Ну или костыли,которых не любят все. На счёт того, что плюсы дают преимущество в проектировании - возможно. Так как более высокоуровневый язык, проще позволяет описать именно верхний уровень. Но это справедливо будет только при хорошем владении инструментом. Иными словами - вот человек неверно спроектировал проект. И что? При переходе на С++ ошибки исчезнут? Думаю их добавится. На плюсах даже подход меняется..
  11. Посмотрите с чего начиналась тема. Начали гнать на HAL от ST. Что по своей сути это такое? По сути это попытка создания универсальной библиотеки. Более того, в купе с генератором, это попытка создания универсального подхода. С моей точки зрения - он провалился. Хотя куча его использует и счастливы. Что предлагаете вы? Вы пытаетесь создать туже универсальную библиотеку, с универсальным подходом. Только 2 отличия. 1 - на С++. 2 - вы не ST. Простите - я лучше стамеской поработаю. Любая универсальная библиотека будет избыточна. И должна быть избыточна. Потому что универсальность и избыточность это одно и тоже. Меня не напрягает избыточность сама по себе. Камни сейчас обеспечивают - я не парюсь. Но весь мой опыт написания универсальных вещей, говорит что они не нужны. В принципе не нужны. Посмотрите HAL от ST на USART. Пипец. Я даже не представляю приложение куда это можно воткнуть!!! Получается, что для применения этой универсальной вещи потребуется обёртка большая по объёму, чем если бы я с нуля написал неуниверсальный драйвер. Я уже писал по этому поводу. Я делаю 2 уровня дров. Железозависимая часть и железонезависимая. Ну например SPI и ADC. Этот же SPI и DATAFLASH. USART -> MODBUS. Нижняя часть - это десяток строк. Дрова у меня в проекте занимают 2% по объёму и ещё меньше по времени. Отлаживаются на раз и к ним никогда не возвращаешься. А остальная часть проекта это как раз то, что я постоянно меняю. Даже если прибор аналогичный. Я видел несколько попыток создания универсальных платформ. В том числе на плюсах. Ни одна меня не впечатлила. Возможно вы от своей без ума. Но это не значит, что я был бы счастлив ей пользоваться. Или кто-то другой. Теперь по поводу динамической памяти. В том проекте, о котором я писал примерно такое построение было... Поступают данные с внешнего интерфейса. Данные поступают в виде команд. Команды разной длины и разного времени жизни. Устройство выполняет команду и удаляет её. Получается, что одна команда могла выполниться и сразу удалялась, а другая выполнялась в течении длительного времени. В результате память дифрагментировалась. Поток команд был очень интенсивный. Объём памяти тогда на контроллере был 64к всего. Под кучу килобайт 30 было отведено. Уже не помню. Были бы проблемы это бы вылезло достаточно быстро. Устройство не выключалось. Работало круглосуточно. Не скажу что мы их много сделали. Ну несколько десятков было. А вот на плюсах как раз трудноустранимые утечки случаются. Парень писал для нас OPC сервер. На QT4 + VS. Была утечка памяти. Устранил только когда свой QSerialPort написал. Хотя я с той же версией QT+GCC писал прогу удалённого управления прибором и проблем не было. При этом для связи использовали те же классы. Вот такой вот пример.
  12. Стиль написания, конструирование программы и язык всё же параллельны. А стабильность работы вообще к языку никакого отношения не имеет. Не в плане спора, но как известно С++ ни в одном источнике, как ясный прозрачный и без проблемный не рассматривается. Ну это же объективно. Просто почитайте мнение специалистов. В предпоследнем проекте у меня было 411 объектных файлов и более 50 тыс строк текста. Это прибор коммерческого учёта. Я не видел случаев его падения. Там Си + FreeRTOS + LwIP. Драйвера в несколько уровней. Например, обращение к флэшке SPI из различных задач - на ура. Мало того, использовались 2 аппаратных буфера поочерёдно для ускорения. В некоторых случаях заливка производилась потоковым способом. Всё работало как часики. При падении напряжения возникало прерывание, сохранялся контекст, сохранялись указатели архивов... Сделал - положить нельзя прибор. Только контрольный выстрел. )) Меню там экранов штук сто - объектно построено. Вот подумываю один проект замутить на плюсах. Там просто графика будет приличная. Должно окупиться. А что вы так взъелись на динамическое выделение памяти? Тоже пробовал в проектах. В одном проете вообще на нём всё построено было. Причём там у меня дырки появлялись. Так я свой сборщик мусора сделал. Тоже претензий не было. Если всё продумать, то всё работает.
  13. Завидую я вам. А у меня практически каждый проект - новый проект. А идей ещё больше. Заимствуются крохи. Причём то что заимствуется, как то без особых проблем. Я ничего не говорил, по С++. Я им пользуюсь. Какие-то проекты, обслуживания прибора пишу на QT. Но как то всё равно язык не стал своим... Я - убей - не пойму, что мне даёт класс Hardware... Выглядит несколько надуманно. Я не утверждаю, что так и есть. Просто представить себе не очень могу... Типа базовый класс? Далее от него класс SPI? А что вы за ось пользуете?
  14. Сергей, но по сабжу применение синглтонов, явно не то преимущество, согласитесь.
  15. Ещё раз обращаю внимание, что это не конструкция языка... Это не оператор, не тип данных ... Это одна из реализаций задачи средствами языка... Таких куча. И в Си тоже. Вот ребята обсуждали https://electronix.ru/forum/index.php?showtopic=139522 В теме есть законченные, грамотные решения. Причём весьма лаконичные. IAR, например, предлагает typedef i-type sig_atomic_t; в библиотеке <signal.h> . А переходить на другой язык, только потому что не знаешь как решить задачу в рамках этого ... ну извините.
  16. В зависимости от текста... Как правило непредсказуемыми последствиями... Здесь давече была тема про атомарный доступ к таким переменным. Не хочу вступать в полемику, так как в программировании, одну и туже задачу можно десятком способов решить... Я обычно решаю так: Есть задачи А, Б, С. Например задача А выставляет какой то запрос флагом фА. Задачи Б и С могут его прочитать, но не сбросить! Задача Б по флагу фА подтверждает запрос выставив флаг фБ. По флагу фБ задача А сбрасывает флаг фА. То есть Одна задача только читает, вторая только пишет. Найболее яркий пример реализации в протоколе centronix. Если всё же не избежать взаимных колизий, то использую защищённую секцию, либо средства самой ОС. Ну в зависимости, от частоты события... === Ну приведу классическую работу с кольцевым буфером: 1. При поступлении символа либо пакета, в прерывании двигается хвост очереди tail. 2. В задаче, после обработки пакета - двигается голова очереди head. Вроде всё класс. Но вам требуется определить размер доступных данных... Ну типа так.. len = tail - head; if(len <0) len += sizebuf; .... И здесь видно, что во время операции len = tail - head, значение tail может измениться в прерывании (например пришёл пакет, и указатель сдвинулся по кольцу). В результате вы можете получить значение совершенно неверное. Дабы это предотвратить, вы должны например запретить прерывание на эту операцию. Либо приостановить планировщик, если речь не о прерывании, а о задачах. Для FreeRTOS: taskENTER_CRITICAL() — вход в критическую секцию taskEXIT_CRITICAL() — выход из критической секции vTaskSuspendAll() - Приостановка планировщика xTaskResumeAll() - возобновления работы планировщика Если приложение написано верно, то таких мест будет крайне мало... У меня их единицы. Но всё же они есть.
  17. Насколько вы описали проблему, мне кажется, что проблема не в дровах и не в стеке. Ничего там не переполнится. Судя по всему, у вас проблемы с синхронизацией между задачами. Либо второй вариант - где-то используется глобальная переменная, доступная на запись из нескольких задач. Туда ройте.
  18. Возьмите прогу стартеркита. Остановите под отладчиком и посмотрите регистры контроллера памяти и LTDC. Запустите свою, остановите и сравните...
  19. Прерывания запрещены? Операции ПДП? На фирменной прошивке нет таких моментов?
  20. Может ваша прога пишет несанкционированно? А родной пример работает без проблем?
  21. У меня вот такая плата была: http://www.starterkit.ru/html/index.php?na...view&id=128
  22. Слушай, там так увязано... Не очень хочется раскапывать. Попытаюсь конечно... Это ОЗУ #define SDRAM_TIMEOUT ((uint32_t)0xFFFF) // *** Биты контроллера FMC *** // Программирование контроллера #define FMC_ColumnBits_Number_8b ((uint32_t)0x00000000) #define FMC_ColumnBits_Number_9b ((uint32_t)0x00000001) #define FMC_ColumnBits_Number_10b ((uint32_t)0x00000002) #define FMC_ColumnBits_Number_11b ((uint32_t)0x00000003) #define FMC_RowBits_Number_11b ((uint32_t)0x00000000) #define FMC_RowBits_Number_12b ((uint32_t)0x00000004) #define FMC_RowBits_Number_13b ((uint32_t)0x00000008) #define FMC_NORSRAM_MemoryDataWidth_8b ((uint32_t)0x00000000) #define FMC_NORSRAM_MemoryDataWidth_16b ((uint32_t)0x00000010) #define FMC_NORSRAM_MemoryDataWidth_32b ((uint32_t)0x00000020) #define FMC_InternalBank_Number_2 ((uint32_t)0x00000000) #define FMC_InternalBank_Number_4 ((uint32_t)0x00000040) #define FMC_CAS_Latency_1 ((uint32_t)0x00000080) #define FMC_CAS_Latency_2 ((uint32_t)0x00000100) #define FMC_CAS_Latency_3 ((uint32_t)0x00000180) #define FMC_Write_Protection_Disable ((uint32_t)0x00000000) #define FMC_Write_Protection_Enable ((uint32_t)0x00000200) #define FMC_SDClock_Disable ((uint32_t)0x00000000) #define FMC_SDClock_Period_2 ((uint32_t)0x00000800) #define FMC_SDClock_Period_3 ((uint32_t)0x00000C00) #define FMC_Read_Burst_Disable ((uint32_t)0x00000000) #define FMC_Read_Burst_Enable ((uint32_t)0x00001000) #define FMC_ReadPipe_Delay_0 ((uint32_t)0x00000000) #define FMC_ReadPipe_Delay_1 ((uint32_t)0x00002000) #define FMC_ReadPipe_Delay_2 ((uint32_t)0x00004000) // Комманды контроллера #define FMC_Command_Mode_normal ((uint32_t)0x00000000) #define FMC_Command_Mode_CLK_Enabled ((uint32_t)0x00000001) #define FMC_Command_Mode_PALL ((uint32_t)0x00000002) #define FMC_Command_Mode_AutoRefresh ((uint32_t)0x00000003) #define FMC_Command_Mode_LoadMode ((uint32_t)0x00000004) #define FMC_Command_Mode_Selfrefresh ((uint32_t)0x00000005) #define FMC_Command_Mode_PowerDown ((uint32_t)0x00000006) #define FMC_Command_Target_bank2 ((uint32_t)0x00000008) #define FMC_Command_Target_bank1 ((uint32_t)0x00000010) #define FMC_Command_Target_bank1_2 ((uint32_t)0x00000018) // управление памятью #define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000) #define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001) #define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002) #define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004) #define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) #define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) #define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020) #define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030) #define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000) #define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAM ((uint16_t)0x0000) #define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200) // Инициализация ОЗУ на плате. void draminit(void) { uint32_t tmp = 0; uint32_t timeout = SDRAM_TIMEOUT; // Инициализация пинов памяти PINSDRAM_INIT; // FMC SDRAM последовательность инициализации устройства // Шаг 1 // Строки: [9:0] tmp |= FMC_ColumnBits_Number_9b; // Столбцы: [13:0] tmp |= FMC_RowBits_Number_13b; tmp |= FMC_NORSRAM_MemoryDataWidth_16b; tmp |= FMC_InternalBank_Number_4; // CL: Cas Latency = 3 цикла tmp |= FMC_CAS_Latency_3; tmp |= FMC_Write_Protection_Disable; tmp |= FMC_SDClock_Period_2; tmp |= FMC_Read_Burst_Enable; tmp |= FMC_ReadPipe_Delay_1; // FMC SDRAM bank initialization // FMC SDRAM control configuration. Банк 1. FMC_Bank5_6->SDCR[0] = tmp; // Шаг 2 // Тайминги для 90 Mhz на SD. Частота (180Mhz/2) // TMRD: 2 цикла ожидания tmp = 2-1; // TXSR: min=70ns (7x11.11ns) tmp |= (7-1)<<4; // TRAS: min=42ns (4x11.11ns) max=120k (ns) tmp |= (4-1)<<8; // TRC: min=70 (7x11.11ns) tmp |= (7-1)<<12; // TWR: min=1+ 7ns (1+1x11.11ns) tmp |= (2-1)<<16; // TRP: 20ns => 2x11.11ns tmp |= (2-1)<<20; // TRCD: 20ns => 2x11.11ns tmp |= (2-1)<<24; // FMC SDRAM тайминги. Банк 1. FMC_Bank5_6->SDTR[0] = tmp; // Шаг 3 // Разрешение команд tmp = FMC_Command_Mode_CLK_Enabled; tmp |= FMC_Command_Target_bank1; // FMC_AutoRefreshNumber tmp |= (1-1)<<5; // FMC_ModeRegisterDefinition tmp |= 0<<9; // ждать пока SDRAM контроллер будет готов timeout = SDRAM_TIMEOUT; while((FMC_Bank5_6->SDSR & FMC_SDSR_BUSY) && (timeout > 0)) { timeout--; } // Послать комманду FMC_Bank5_6->SDCMR = tmp; // Шаг 4 // Задержка 100мс hDelay(100); // Шаг 5 // Сконфигурировать PALL (precharge all) tmp = FMC_Command_Mode_PALL; tmp |= FMC_Command_Target_bank1; // FMC_AutoRefreshNumber tmp |= (1-1)<<5; // FMC_ModeRegisterDefinition tmp |= 0<<9; // ждать пока SDRAM контроллер будет готов timeout = SDRAM_TIMEOUT; while((FMC_Bank5_6->SDSR & FMC_SDSR_BUSY) && (timeout > 0)) { timeout--; } // Послать комманду FMC_Bank5_6->SDCMR = tmp; // Шаг 6 // Сконфигурировать Auto-Refresh tmp = FMC_Command_Mode_AutoRefresh; tmp |= FMC_Command_Target_bank1; // FMC_AutoRefreshNumber tmp |= (8-1)<<5; // FMC_ModeRegisterDefinition tmp |= 0<<9; // ждать пока SDRAM контроллер будет готов timeout = SDRAM_TIMEOUT; while((FMC_Bank5_6->SDSR & FMC_SDSR_BUSY) && (timeout > 0)) { timeout--; } // Послать комманду FMC_Bank5_6->SDCMR = tmp; // Шаг 7 // Сконфигурировать load Mode регистр tmp = FMC_Command_Mode_LoadMode; tmp |= FMC_Command_Target_bank1; // FMC_AutoRefreshNumber tmp |= (8-1)<<5; // FMC_ModeRegisterDefinition // Запрограммировать mode register внешней памяти tmp |= ((uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 | SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | SDRAM_MODEREG_CAS_LATENCY_3 | SDRAM_MODEREG_OPERATING_MODE_STANDARD | SDRAM_MODEREG_WRITEBURST_MODE_SINGLE)<<9; // ждать пока SDRAM контроллер будет готов timeout = SDRAM_TIMEOUT; while((FMC_Bank5_6->SDSR & FMC_SDSR_BUSY) && (timeout > 0)) { timeout--; } // Послать комманду FMC_Bank5_6->SDCMR = tmp; // Шаг 8 // Установить счётчик регенерации памяти // (7.81 us x Freq) - 20 FMC_Bank5_6->SDRTR |= (683<<1); // ждать пока SDRAM контроллер будет готов timeout = SDRAM_TIMEOUT; while((FMC_Bank5_6->SDSR & FMC_SDSR_BUSY) && (timeout > 0)) { timeout--; } } Это LCD c DMA2D /************************************************************************ * *** Работа с оборудованием *** * ************************************************************************/ // Alias word address of PLLSAION bit #define RCC_OFFSET (RCC_BASE - PERIPH_BASE) #define CR_OFFSET (RCC_OFFSET + 0x00) #define PLLSAION_BITNUMBER 0x1C //#define CR_PLLSAION_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PLLSAION_BITNUMBER * 4)) #define RCC_FLAG_PLLSAIRDY 0x1D #define GCR_MASK ((uint32_t)0x0FFE888F) // LTDC GCR Mask #define LTDC_HSPOLARITY_AL ((uint32_t)0x00000000) // Horizontal Synchronization is active low. #define LTDC_HSPOLARITY_AH LTDC_GCR_HSPOL // Horizontal Synchronization is active high. #define LTDC_VSPOLARITY_AL ((uint32_t)0x00000000) // Vertical Synchronization is active low. #define LTDC_VSPOLARITY_AH LTDC_GCR_VSPOL // Vertical Synchronization is active high. #define LTDC_DEPOLARITY_AL ((uint32_t)0x00000000) // Data Enable, is active low. #define LTDC_DEPOLARITY_AH LTDC_GCR_DEPOL // Data Enable, is active high. #define LTDC_PCPOLARITY_IPC ((uint32_t)0x00000000) // input pixel clock. #define LTDC_PCPOLARITY_IIPC LTDC_GCR_PCPOL // inverted input pixel clock. #define LTDC_PIXELFORMAT_RGB565 ((uint32_t)0x00000002) #define LTDC_BLENDINGFACTOR1_CA ((uint32_t)0x00000400) #define LTDC_BLENDINGFACTOR1_PAXCA ((uint32_t)0x00000600) #define LTDC_BLENDINGFACTOR2_CA ((uint32_t)0x00000005) #define LTDC_BLENDINGFACTOR2_PAXCA ((uint32_t)0x00000007) #define LTDC_IMRELOAD LTDC_SRCR_IMR // Immediately Reload. #define LTDC_VBRELOAD LTDC_SRCR_VBR // Vertical Blanking Reload. // ChromART // @defgroup DMA2D_Input_Color_Mode DMA2D Input Color Mode #define CM_ARGB8888 ((uint32_t)0x00000000U) // ARGB8888 color mode #define CM_RGB888 ((uint32_t)0x00000001U) // RGB888 color mode #define CM_RGB565 ((uint32_t)0x00000002U) // RGB565 color mode #define CM_ARGB1555 ((uint32_t)0x00000003U) // ARGB1555 color mode #define CM_ARGB4444 ((uint32_t)0x00000004U) // ARGB4444 color mode #define CM_L8 ((uint32_t)0x00000005U) // L8 color mode #define CM_AL44 ((uint32_t)0x00000006U) // AL44 color mode #define CM_AL88 ((uint32_t)0x00000007U) // AL88 color mode #define CM_L4 ((uint32_t)0x00000008U) // L4 color mode #define CM_A8 ((uint32_t)0x00000009U) // A8 color mode #define CM_A4 ((uint32_t)0x0000000AU) // A4 color mode #define DMA2D_ARGB8888 ((uint32_t)0x00000000U) // ARGB8888 DMA2D color mode #define DMA2D_RGB888 ((uint32_t)0x00000001U) // RGB888 DMA2D color mode #define DMA2D_RGB565 ((uint32_t)0x00000002U) // RGB565 DMA2D color mode #define DMA2D_ARGB1555 ((uint32_t)0x00000003U) // ARGB1555 DMA2D color mode #define DMA2D_ARGB4444 ((uint32_t)0x00000004U) // ARGB4444 DMA2D color mode // Инициализация LCD void drvTFTinit(void) { uint32_t tmpreg; // 480X272 // Разрешить Pixel Clock // Конфигурируем PLLSAI предделитель для LCD // PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz // PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAI_N = 192 Mhz // PLLLCDCLK = PLLSAI_VCO Output/PLLSAI_R = 192/3 = 64 Mhz RCC->PLLSAICFGR = (192 << 6) | (7 << 24) | (3 << 28); // LTDC clock frequency = PLLLCDCLK / RCC_PLLSAIDivR = 64/8 = 8 Mhz tmpreg = RCC->DCKCFGR; tmpreg &= ~RCC_DCKCFGR_PLLSAIDIVR; // Очистить биты PLLSAIDIVR[2:0] tmpreg |= RCC_DCKCFGR_SAI1ASRC_1; // Установить значение PLLSAIDIVR 2 (поделить на 8) RCC->DCKCFGR = tmpreg; // Сохранить *(__IO uint32_t *) CR_PLLSAION_BB = (uint32_t)1; // Разрешить PLLSAI тактирование // Ждать запуска PLLSAI while((RCC->CR & (1<<RCC_FLAG_PLLSAIRDY)) == 0) { } // Включить тактирование LTDC __LTDC_CLK_ENABLE(); // Настроить пины LCD PINLCD_INIT; // ***** Инициализация LTDC ***** // *** Тайминги *** // горизонтальная синхронизация ширина = Hsync - 1 (41) LTDC->SSCR &= ~(LTDC_SSCR_VSH | LTDC_SSCR_HSW); tmpreg = (40 << 16); // вертикальная синхронизация высота = Vsync - 1 (10) LTDC->SSCR |= (tmpreg | 9); // горизонтальная ширина с полочкой = Hsync + HBP - 1 LTDC->BPCR &= ~(LTDC_BPCR_AVBP | LTDC_BPCR_AHBP); tmpreg = (42 << 16); // вертикальная высота с полочкой = Vsync + HBP - 1 LTDC->BPCR |= (tmpreg | 11); // активная ширина = Hsync + HBP + Active Width - 1 LTDC->AWCR &= ~(LTDC_AWCR_AAH | LTDC_AWCR_AAW); tmpreg = (522 << 16); // активная высота = Vsync + VBP + Active Heigh - 1 LTDC->AWCR |= (tmpreg | 283); // полная ширина = Hsync + HBP + Active Width + HFP - 1 LTDC->TWCR &= ~(LTDC_TWCR_TOTALH | LTDC_TWCR_TOTALW); tmpreg = (524 << 16); // полная высота = Vsync + VBP + Active Heigh + VFP - 1 LTDC->TWCR |= (tmpreg | 285); // *** Полярность *** // Полярность горизонтальной синхронизации = активный 0 // Полярность вертикальной синхронизации = активный 0 // Полярность "data enable" = активный 0 // Полярность "pixel clock" без инверсии LTDC->GCR &= (uint32_t)GCR_MASK; LTDC->GCR |= (uint32_t)(LTDC_HSPOLARITY_AL | LTDC_VSPOLARITY_AL | LTDC_DEPOLARITY_AL | LTDC_PCPOLARITY_IPC); // R,G,B фона //LTDC->BCCR &= ~(LTDC_BCCR_BCBLUE | LTDC_BCCR_BCGREEN | LTDC_BCCR_BCRED); //LTDC->BCCR |= BACKGROUNDCOLOR; LTDC->BCCR = BACKGROUNDCOLOR; // *** Завершение инициализации LTDC *** // *** инициализация слоя 1 *** // Если вся область активного дисплея используется для отображения изображения, то: // Horizontal start = horizontal synchronization + Horizontal back porch = 43 // Vertical start = vertical synchronization + vertical back porch = 12 // Horizontal stop = Horizontal start + window width -1 = 43 + 480 -1 // Vertical stop = Vertical start + window height -1 = 12 + 272 -1 //LTDC_Layer1->WHPCR &= ~(LTDC_LxWHPCR_WHSTPOS | LTDC_LxWHPCR_WHSPPOS); tmpreg = (480 + 43 - 1) << 16; // Horizontal stop LTDC_Layer1->WHPCR = (43 | tmpreg); // Horizontal start //LTDC_Layer1->WVPCR &= ~(LTDC_LxWVPCR_WVSTPOS | LTDC_LxWVPCR_WVSPPOS); tmpreg = (272 + 12 - 1) << 16; // Vertical stop LTDC_Layer1->WVPCR = (12 | tmpreg); // Vertical start // Формат пикселя //LTDC_Layer1->PFCR &= ~(LTDC_LxPFCR_PF); LTDC_Layer1->PFCR = LTDC_PIXELFORMAT_RGB565; // Alpha constant (255 totally opaque) //LTDC_Layer1->CACR &= ~(LTDC_LxCACR_CONSTA); LTDC_Layer1->CACR = 255; // Цвет по умолчанию LTDC_Layer1->DCCR = 0; // Блэндинг факторы LTDC_Layer1->BFCR = (LTDC_BLENDINGFACTOR1_CA | LTDC_BLENDINGFACTOR2_CA); // Стартовый адресс LTDC_Layer1->CFBAR = VIDEOBUF_L1ADR; // Длина одной строки пикселей в байтах + 3: // Длина строки = Ширина x число байт на пиксель + 3 // Ширина = 480 // число байт на пиксель = 2 (формат пикселя : RGB565) tmpreg = ((480 * 2) + 3); // Смещение между 2 строками LTDC_Layer1->CFBLR = ((480 * 2)<<16) | tmpreg; // Число строк LTDC_Layer1->CFBLNR = 272; // Разрешить работу слоя 1 LTDC_Layer1->CR |= (uint32_t)LTDC_LxCR_LEN; // Перегрузить конфигурацию слоя 1 LTDC->SRCR = (uint32_t)LTDC_IMRELOAD; // Запустить LCD LTDC->GCR |= (uint32_t)LTDC_GCR_LTDCEN; // Запустить ChromART __DMA2D_CLK_ENABLE(); } Я просто HAL не задействую. Ну и тащить хидеры, если это одна операция разовая, не очень желаю. Поэтому подкидывал так. Проект был "для изучения вопроса". Работу сейчас поменял.. Пока возвращаться планирую значительно позже... Некоторые примитивы кину. Собственно там всё понятно... Ну напрягитесь ребята... Почитайте. // Распаковать картинку A4 на экран void copyA4toTFT(void *pSrc, void *pDst, uint16_t xSize, uint16_t ySize) { DMA2D->CR = 0x00010000UL | (1 << 9); // Control Register (Memory to memory with pixel format conversion and TCIE) // Указатели DMA2D->FGMAR = (uint32_t)pSrc; // Foreground Memory Address Register (Source address) DMA2D->OMAR = (uint32_t)pDst; // Output Memory Address Register (Destination address) // Смещения DMA2D->FGOR = xSize; // Foreground Offset Register (Source line offset) DMA2D->OOR = _layerX-1; // Output Offset Register (Destination line offset) // Входной и выходной Форматы пикселя DMA2D->FGPFCCR = CM_A4; // Foreground PFC Control Register (Defines the input pixel format) DMA2D->OPFCCR = DMA2D_RGB565; // Output PFC Control Register (Defines the output pixel format) // Установить цвет DMA2D->FGCOLR = _fcolor; // Foreground PFC Control Register (Defines the input pixel format) // Установить размер DMA2D->NLR = (uint32_t)(xSize << 16) | ySize; // Number of Line Register (Size configuration of area to be transfered) // Выполнить DMA2D->CR |= DMA2D_CR_START; while (DMA2D->CR & DMA2D_CR_START) { } } // Скопировать картинку С16 на экран void copyC16(void *pSrc, void *pDst, uint16_t xSize, uint16_t ySize, uint16_t xSizeSrc, uint16_t xSizeDst) { DMA2D->CR = (1 << 9); // без модификации // Указатели DMA2D->FGMAR = (uint32_t)pSrc; // Foreground Memory Address Register (Source address) DMA2D->OMAR = (uint32_t)pDst; // Output Memory Address Register (Destination address) // Смещения DMA2D->FGOR = xSizeSrc; // Foreground Offset Register (Source line offset) DMA2D->OOR = xSizeDst; // Output Offset Register (Destination line offset) // Входной и выходной Форматы пикселя DMA2D->FGPFCCR = CM_RGB565; // Foreground PFC Control Register (Defines the input pixel format) DMA2D->OPFCCR = DMA2D_RGB565; // Output PFC Control Register (Defines the output pixel format) // Установить размер DMA2D->NLR = (uint32_t)(xSize << 16) | ySize; // Number of Line Register (Size configuration of area to be transfered) // Выполнить DMA2D->CR |= DMA2D_CR_START; while (DMA2D->CR & DMA2D_CR_START) { } } // Залить прямоугольник на экране void FillRectTFT(void *pSrc, uint16_t xSize, uint16_t ySize) { // Set up mode DMA2D->CR = 0x00030000UL | (1 << 9); DMA2D->OCOLR = _color; // Set up pointers DMA2D->OMAR = (uint32_t)pSrc; // Set up offsets DMA2D->OOR = _layerX-1; // Set up pixel format DMA2D->OPFCCR = DMA2D_RGB565; // Set up size DMA2D->NLR = (uint32_t)(xSize << 16) | (uint16_t)ySize; DMA2D->CR |= DMA2D_CR_START; // Wait until transfer is done while (DMA2D->CR & DMA2D_CR_START) { } }
  23. Может что с питанием? У меня всё заработало сразу да и всё! Я начал с DMA2D баловаться. И там всё с пол пинка заработало... Я, правда, наоборот КУБ убрал и всё перенёс на регистры. Там очень всё прозрачно получается.
  24. Обычно такое происходит если ОЗУ сбоит. Я себе брал, там инициализация ОЗУ была неверная... Точнее не совсем верная. В проге было на один адрес меньше. Ты проверь там всё.
  25. Нет ответов, потому что вы глупости пишете. При переводе на доступный примерно так.... Я тут вскочил на лошадь... Она скачет как-то странно. Как надо вскакивать чтобы она скакала нормально? А может кто-нибудь другую лошадь пришлёт? Или седло другое? Возьмите даташит на свой процессор и найдите там в разделе о программировании ног рекомендации по уменьшению потребления. Обычно примерно так. Незадействованные ноги вы должны проинитить на вывод и вывести на них 0. Входные ноги проинитить на вход и подпереть. Незадействованную перефирию отключить. Никто вам ничего не пришлёт, так как он не знает какая у вас схема и куда какие ноги назначены. Никто за вас не выполнит вашу работу. Работа по уменьшению потребления должна быть всеобъемлющей. То есть надо соответствующим образом переписать проект. А именно: при наступлении внешнего события, например получении байта либо пакета по uart, проц должен проснуться максимально быстро обработать событие и заснуть обратно. Лучше если для этого будет задействована периферия процессора. Например DMA. Ну и так далее... Для среднего проекта это не одна неделя...
×
×
  • Создать...