Например TDA7294

Форум РадиоКот • Просмотр темы - RTC: установка даты и времени через HAL
Форум РадиоКот
Здесь можно немножко помяукать :)

Текущее время: Ср дек 31, 2025 13:31:51

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 9 ] 
Автор Сообщение
Не в сети
 Заголовок сообщения: RTC: установка даты и времени через HAL
СообщениеДобавлено: Вт июл 19, 2022 05:31:48 
Опытный кот
Аватар пользователя

Карма: 13
Рейтинг сообщений: 163
Зарегистрирован: Сб дек 22, 2012 08:17:42
Сообщений: 744
Откуда: Караганда, Казахстан
Рейтинг сообщения: 0
Коллеги, подскажите, плз... Никак не въеду в установку даты-времени через HAL. Ситуация элементарная: оставил я плату со своим STM32F407VET6 на полгода в покое, RTC работает от батарейки. Включаю, а часы отстали или убежали на несколько часов.

Через регистры, вроде-бы, все понятно, а вот через HAL что-то никак не въеду. Подкиньте, плз, последовательность вызовов HAL для установки даты и времени?

_________________
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: RTC: установка даты и времени через HAL
СообщениеДобавлено: Вт июл 19, 2022 09:26:17 
Собутыльник Кота
Аватар пользователя

Карма: -12
Рейтинг сообщений: -24
Зарегистрирован: Пт июл 12, 2019 22:52:01
Сообщений: 2516
Рейтинг сообщения: -1
А что, надо именно через кал?
Тернист путь…

_________________
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: RTC: установка даты и времени через HAL
СообщениеДобавлено: Вт июл 19, 2022 11:12:31 
Опытный кот
Аватар пользователя

Карма: 13
Рейтинг сообщений: 163
Зарегистрирован: Сб дек 22, 2012 08:17:42
Сообщений: 744
Откуда: Караганда, Казахстан
Рейтинг сообщения: 0
Да я уже тоже склоняюсь к тому, чтобы забить на эту гадость и сделать всё через регистры. Просто у меня большой проект собран из кубиков, там задействована FATFS от Чана, основное взаимодействие с периферией у меня и так через регистры, через кубики идёт только FATFS. А RTC так, между делом, есть оборудование на МК, почему бы его и не использовать. Только посмотрел я на эти кубические драйвера HAL и решил, что эту дрянь я себе в голову загружать не буду. В слабой надежде спросил, может кто это делал, а сам сегодня поразглядывал работу с RTC через регистры. В общем-то, ничего военного, просто я надеялся, что у кого-нибудь найдется готовое решение, которое можно будет скопипастить, и мне можно будет не вникать в подробности этого самого RTC. Получается, нет! Ладно, вникну...

_________________
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: RTC: установка даты и времени через HAL
СообщениеДобавлено: Ср июл 20, 2022 18:10:51 
Вымогатель припоя
Аватар пользователя

Карма: 10
Рейтинг сообщений: 171
Зарегистрирован: Ср июн 29, 2022 16:25:45
Сообщений: 525
Рейтинг сообщения: 0
afz, так вроде FATFS требует от железа только процедуру чтения/отправки байта через SPI... И ее вполне на регистрах можно...
А, в какой то версии еще FATFS хотел тик от таймера 100 раз в сек. Но там сервисные функции - их можно дергать и не строго 100 раз в сек.

_________________
Белая и Пушистая


Вернуться наверх
 
Эиком - электронные компоненты и радиодетали
Не в сети
 Заголовок сообщения: Re: RTC: установка даты и времени через HAL
СообщениеДобавлено: Ср июл 20, 2022 18:20:16 
Собутыльник Кота
Аватар пользователя

Карма: -12
Рейтинг сообщений: -24
Зарегистрирован: Пт июл 12, 2019 22:52:01
Сообщений: 2516
Рейтинг сообщения: 0
Есть же компактные ФС для МК - специально, чтобы не было всякого излишества (скажем, зачем там права пользователя как в ext2?). Можно и вообще свое что-нибудь примитивное реализовать. Допустим, если файлы не нужно удалять, можно сделать последовательную запись, чем-то напоминающую структуру архива tar. Потом его просто при помощи dd к себе забрать и распаковать стандартными средствами.

_________________
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: RTC: установка даты и времени через HAL
СообщениеДобавлено: Ср июл 20, 2022 21:51:22 
Опытный кот
Аватар пользователя

Карма: 13
Рейтинг сообщений: 163
Зарегистрирован: Сб дек 22, 2012 08:17:42
Сообщений: 744
Откуда: Караганда, Казахстан
Рейтинг сообщения: 0
Нет, коллеги, мне была нужна настоящая FAT32, чтобы можно было выдернуть uSD-шку из моего контроллера, сунуть ее в кардридер и работать с ней на PC, потом выдернуть из кардридера, сунуть в мой контроллер и продолжить работу на нем. Если нужны подробности, приведу ссылки, но думаю, что вас это не заинтересует.

А на тему моего вопроса, так я уже, практически, вник в работу с RTC через регистры, да и нашел, где подкрутить, чтобы кубики под ногами не путались, когда мне это не нужно. Не хотелось вникать, надеялся скопипастить, но, увы, пришлось таки вникнуть...

Тогда еще один вопрос.
Хочу задействовать USART1, пусть кубики его проинитят, но потом хочу перехватить у них управление и отработать опять же, через регистры. Напомните, плз, где там подключить свою программу прерываний - вроде-бы там было что-то, объявленное, как weak и туда можно подсунуть свою программулю. Кажется, у них это называется коллбэком...

Добавлено after 2 hours 42 minutes 19 seconds:
Что-то я ничего не нашел внятного про кубические коллбэки. То есть, конечно, никто мне не мешает вписать в программу STM32F4xx_it.c между
/* USER CODE BEGIN USART1_IRQn 0 */ и /* USER CODE END USART1_IRQn 0 */ вызов своей программы обработки прерываний, только вот это еще одно место правки сгенерированного кубического кода, что мне активно не нравится. То есть, конечно, именно этот исходник должен сохранить мои изменения при повторной генерации из кубиков, но перегенеришь что-то по-другому, так не забыть и здесь подправить...

_________________
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: RTC: установка даты и времени через HAL
СообщениеДобавлено: Чт июл 21, 2022 12:30:20 
Прорезались зубы
Аватар пользователя

Карма: 5
Рейтинг сообщений: 30
Зарегистрирован: Пн июл 04, 2016 16:51:22
Сообщений: 234
Откуда: Россия, Омск
Рейтинг сообщения: 0
Писать программу между USER CODE BEGIN USART1_IRQn 0 USER CODE END USART1_IRQn 0 должен мешать здравый смысл, т.к. в этот момент ядро контроллера будет находиться в обработчике прерывания, а он должен быть максимально коротким и минимально взаимодействовать с общей памятью (ну, кроме чтения - читать можно, но можно получить случайные данные).

Может вам дать код на регистрах? Для себя писал на кольцевом буфере (на чтение и запись), работа с DMA для приёма и передачи. Дополнительных сложностей не добавлял, типа snprintf(что-нибудь) - просто console_put(нуль-терминированная-строка) и дополнительные сущности типа _hex_word, _hex_byte, _int...

В общем, если будет интересно, код ниже.
Спойлер
Код:
volatile uint8_t DMA_STATE;
#define DMA_tty0_TX_ACTIVE   0x01

uint8_t tty0_TX_BUF[1024];
volatile uint16_t tty0_TX_POS;
volatile uint16_t tty0_WR_POS;

void DMA2_Stream7_IRQHandler(void) {
   // tty0 (отладочная консоль)
   if (DMA2->HISR & DMA_HISR_TCIF7) {
      DMA2->HIFCR = DMA_HIFCR_CTCIF7;         // сброс флага события TCIF
      DMA_STATE &= ~DMA_tty0_TX_ACTIVE;
      tty0_ActivateDMA();
   } else if (DMA2->HISR & DMA_HISR_HTIF7) {
      DMA2->HIFCR = DMA_HIFCR_CHTIF7;         // сброс флага события HTIF
   } else if (DMA2->HISR & DMA_HISR_FEIF7) {
      DMA2->HIFCR = DMA_HIFCR_CFEIF7;         // сброс флага события FEIF
   } else if (DMA2->HISR & DMA_HISR_DMEIF7) {
      DMA2->HIFCR = DMA_HIFCR_CDMEIF7;      // сброс флага события DMEIF
   } else if (DMA2->HISR & DMA_HISR_TEIF7) {
      DMA2->HIFCR = DMA_HIFCR_CTEIF7;         // сброс флага события TEIF
   };
};
void USART1_IRQHandler(void) {
   uint8_t tmp;
   while (USART1->SR & USART_SR_RXNE) {
      tmp = USART1->DR;
      if (DMA_STATE & DMA_tty0_thread_ready) {
#ifdef USE_FREERTOS
         xQueueSendFromISR(Q_tty0, &tmp, 0);
#endif
      } else {
         microrl_insert_char(prl, tmp);
      };
   };
};

void tty0_ActivateDMA(void) {
   uint16_t CurrWrPos = tty0_WR_POS;
   uint16_t DataToSend;
   DataToSend = 0;
   if(!(DMA_STATE & DMA_tty0_TX_ACTIVE)) {
      DMA2_Stream7->CR &= ~DMA_SxCR_EN;   // Отключаем поток DMA
      if (tty0_TX_POS != CurrWrPos) {
         // Если не совпадает - значит, данные есть. Или малый шанс на переполнение буфера.
         DMA2_Stream7->M0AR = (uint32_t)&(tty0_TX_BUF[tty0_TX_POS]);
         if (tty0_TX_POS < CurrWrPos) {
            // Нет перехода через конец буфера
            DataToSend = (CurrWrPos - tty0_TX_POS);
            tty0_TX_POS = CurrWrPos;
         } else {
            // Нужно сделать кольцо.
            DataToSend = (sizeof(tty0_TX_BUF) - tty0_TX_POS);
            tty0_TX_POS = 0;
         };
         DMA2_Stream7->NDTR = DataToSend;
         DMA2_Stream7->FCR = 0;
         USART1->SR = ~(USART_SR_TC);
         // И только ПОСЛЕ этого включаем его. Да, странность. Но иначе он уходит в ошибку.
         DMA2_Stream7->CR |= DMA_SxCR_EN;
         DMA_STATE |= DMA_tty0_TX_ACTIVE;
      };
   };   // Если активен - сработает при вызове события завершения обмена.
};


// ---------- Аппаратно-зависимые функции - инициализпция ----------
void UpdateUSART_BR(void) {
   static uint8_t PrescalerTable[8] = {1,1,1,1,2,4,8,16};
   static uint16_t AHB_Presc[16] = {1,1,1,1,1,1,1,1,2,4,8,16,64,128,256,512};
   uint8_t presc;
   uint16_t APB_Presc;
   SystemCoreClockUpdate();
   APB_Presc = AHB_Presc[(RCC->CFGR >> 4) & 0x0F];
   presc = PrescalerTable[(RCC->CFGR >> 13) & 0x07];
   USART1->CR1 &= ~(USART_CR1_TE | USART_CR1_RE | USART_CR1_UE);
   // Системная консоль / tty0 - 115200
   USART1->BRR = (SystemCoreClock / 115200 / presc / APB_Presc);   // Делим системную частоту на скорость порта, на делители APB и AHB, чтобы получить правильный делитель.
   USART1->CR1 |= (USART_CR1_TE | USART_CR1_RE | USART_CR1_UE);
};
void InitUSART(void) {
   GPIOB->MODER &= 0xFFFF0FFF;   // GPIOB[6-7].MODER = 00 - Input
   GPIOB->MODER |= 0x0000A000;   // GPIOB[6-7].MODER = 10 - Alternate
   GPIOB->AFR[0] &= 0xFFFFFFFF;   // GPIOB[6-7].Alternate = 0 (Sys)
   GPIOB->AFR[0] |= 0x77000000;   // GPIOB[6-7].Alternate = 7 (USART1)
   // Enable USART1 (tty0)
   RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
   // Reset USART1
   RCC->APB2RSTR |= RCC_APB2RSTR_USART1RST;
   // UnReset USART1
   RCC->APB2RSTR &= ~RCC_APB2RSTR_USART1RST;
   USART1->CR2 = 0;
   USART1->CR3 = 0;
   // Сброс DMA
   RCC->AHB1RSTR |= RCC_AHB1RSTR_DMA2RST | RCC_AHB1RSTR_DMA1RST;
   RCC->AHB1RSTR &= ~(RCC_AHB1RSTR_DMA2RST | RCC_AHB1RSTR_DMA1RST);
   // Enable DMA1 & DMA2.
   RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN | RCC_AHB1ENR_DMA1EN;
   // Config USART1 to DMA Operations and clear flags.
   USART1->CR3 |= /*USART_CR3_DMAR |*/ USART_CR3_DMAT;
   USART1->SR &= ~(USART_SR_TC/* | USART_SR_RXNE*/);
   UpdateUSART_BR();
   // Указываем периферию
   DMA2_Stream7->PAR = (uint32_t)&(USART1->DR);
   // Указываем память
   DMA2_Stream7->M0AR = (uint32_t)&tty0_TX_BUF;
   // DMA1:Stream1:Channel4 (HW Console RX): MemInc + P->M + Transfer Complete INT.
//    DMA1_Stream1->CR = DMA_SxCR_CHSEL_2 | DMA_SxCR_MINC | DMA_SxCR_TCIE;
   // DMA1:Stream3:Channel4 (HW Console TX): MemInc + M->P + Transfer Complete INT.
   DMA2_Stream7->CR = DMA_SxCR_CHSEL_2 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_TCIE;
   NVIC_EnableIRQ(USART1_IRQn);
   NVIC_SetPriority(USART1_IRQn, 0x04);
   NVIC_SetPriority(DMA2_Stream7_IRQn, 0x03);
   NVIC_EnableIRQ(DMA2_Stream7_IRQn);
//   microrl_init (prl, console_put);         // Инициализпция консоли Microtl
//   microrl_set_complete_callback(prl, console_complete);   // Выставляем callback "Дополнить!"
//   microrl_set_execute_callback(prl, console_execute);   // Добавляем callback на выполнение.
   USART1->CR1 = (USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE | USART_CR1_UE);
};
// ---------- "Высокоуровневые" функции.

char char_to_hex(char value) {
   if (value > 9)
      return '7' + value;
   return '0' + value;
};
uint8_t hchar_to_int(char value) {
   if ((value >= '0') && (value <= '9')) {
      return (value - '0');
   };
   if ((value >= 'A') && (value <= 'F')) {
      return (value - 'A' + 0x0A);
   };
   if ((value >= 'a') && (value <= 'f')) {
      return (value - 'a' + 0x0A);
   };
   return 0;
};
void console_put(const char *text) {
   while(*text) {
      // Пока не нуль-терминатор
      tty0_TX_BUF[tty0_WR_POS] = *text;      // Копируем данные в буфер
      text++;                  // Сдвигаем указатель текста.
      tty0_WR_POS++;               // Сдвигаем указатель на 1 байт дальше.
      if (tty0_WR_POS >= sizeof(tty0_TX_BUF)) tty0_WR_POS = 0;   // Указатель должен быть в пределах допустимых значений.
   };
   // Здесь всё хорошо, записываем от старой позиции до новой.
   tty0_ActivateDMA();
};
void console_put_hex_dword(const uint32_t Data) {
   char txt[9];
   txt[0] = char_to_hex((Data >> 28) & 0x0F);
   txt[1] = char_to_hex((Data >> 24) & 0x0F);
   txt[2] = char_to_hex((Data >> 20) & 0x0F);
   txt[3] = char_to_hex((Data >> 16) & 0x0F);
   txt[4] = char_to_hex((Data >> 12) & 0x0F);
   txt[5] = char_to_hex((Data >> 8) & 0x0F);
   txt[6] = char_to_hex((Data >> 4) & 0x0F);
   txt[7] = char_to_hex((Data) & 0x0F);
   txt[8] = 0;
   console_put(txt);
};
void console_put_hex_word(const uint16_t Data) {
   char txt[5];
   txt[0] = char_to_hex((Data >> 12) & 0x0F);
   txt[1] = char_to_hex((Data >> 8) & 0x0F);
   txt[2] = char_to_hex((Data >> 4) & 0x0F);
   txt[3] = char_to_hex((Data) & 0x0F);
   txt[4] = 0;
   console_put(txt);
};
void console_put_hex_byte(const uint8_t Data) {
   char txt[3];
   txt[0] = char_to_hex((Data >> 4) & 0x0F);
   txt[1] = char_to_hex((Data) & 0x0F);
   txt[2] = 0;
   console_put(txt);
};
void console_put_int(const uint32_t value) {
   uint8_t txt[13];
   txt[12] = 0;
   console_put(utoa_builtin_div(value, (char *)txt));
};

Собственно, любой вывод текста отправляется в console_put(), который занимается рутиной, копируя строку из входа в кольцевой буфер. После этого пинается DMA контроллер, который перебрасывает данные в USART1. Если данные закончились - производится новая попытка запустить DMA, перепроверив указатели на буфер. Если совпадают - все данные были отправлены (или буфер был переполнен идеально полностью) и запускать не нужно. Если нужно - указатели соответствующим образом обновляются (указатель, который принадлежит DMA, а не функции!).

Получение байтов - посимвольное. Где-то в другом проекте принимал по DMA, но переписывать, чтобы заработало, немного лень.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: RTC: установка даты и времени через HAL
СообщениеДобавлено: Пт июл 22, 2022 19:25:04 
Опытный кот
Аватар пользователя

Карма: 13
Рейтинг сообщений: 163
Зарегистрирован: Сб дек 22, 2012 08:17:42
Сообщений: 744
Откуда: Караганда, Казахстан
Рейтинг сообщения: 0
AlanDrakes, вообще-то, не так всё плохо. Точнее, многое зависит от кучи всяких факторов, но, если нет каких-то параллельных скоростных процессов, то, грамотно используя прерывания, все проблемы легко обходятся. Что действительно нельзя делать - это ждать чего-то в этом обработчике, а так - времени от одного до другого прерывания по TXE - 14.5 тыс тактов при работе на168 мГц и скорости USART'а 115200. И я с трудом представляю, чего туда такого можно насочинять, что бы потребовало больше 1000 тактов.

Естественно, все программы, работающие в прерываниях, должны быть быстрыми. То есть взяли что-то из регистров, поместили что-то в регистры, где-то отметились, и на выход. А ожидания будут в основном цикле, который while(1).

А без DMA не обойтись только тогда, когда нужно что-то скоростное и/или с минимально возможным джиттером.

_________________
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: RTC: установка даты и времени через HAL
СообщениеДобавлено: Вс июл 24, 2022 05:21:07 
Прорезались зубы
Аватар пользователя

Карма: 5
Рейтинг сообщений: 30
Зарегистрирован: Пн июл 04, 2016 16:51:22
Сообщений: 234
Откуда: Россия, Омск
Рейтинг сообщения: 0
А без DMA не обойтись только тогда, когда нужно что-то скоростное и/или с минимально возможным джиттером.


Либо наоборот, очень медленное, что может работать пока ядро спит =)


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 9 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 26


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y