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

billidean

Свой
  • Постов

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

  • Посещение

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


  1. - очень ёмкое уточнение вопроса. А по поводу документации, то перевод относится к части USB OTG FS документации "Reference manual. STM32F405xx/07xx, STM32F415xx/17xx, STM32F42xxx and STM32F43xxx advanced ARM-based 32-bit MCUs" (RM0090).
  2. Извиняюсь, но не пойму вопроса " какой процессор" - где именно, о каком процессоре не понятно?
  3. Спасибо. Я так и собираюсь поступить.
  4. OTG_... пытаюсь поднять

    Приветствую всех. Задался целью мимо библиотеки реализовать OTG_FS (аки Устройство(Device)) на регистрах. Реализовал перевод доки в части USB-Устройства (в аттаче). Теперь нужно в соответствии в докой реализовать все моменты настройки/приема/выдачи (казалось бы). НО при первом же "желании" обратиться к регистру OTG_FS_GINTSTS - не могу его найти в системе. Прошу подсказать как обращаться к регистрам такого рода в начальном проекте(без библи..и)? З.Ы.: прочтите перевод и предложите дополнения/изменения. USB_on_the_go_full_speed__OTG_FS_.pdf
  5. Вы вот это имеете в виду (выделенная строчка): из настроек регистра RCC_CFGR? просто я решил раскопать и расставить все точки над этими мутными "и". А все может быть просто потыкались/понастраивали_как-то свои девайсы да и проглотили эту непонятку, успокоив себя: "не знаю почему, но тактовая у меня вот такая..".
  6. А теперь самое ИНТЕРЕСНОЕ: Вот код моей программки: #include "stm32f4xx.h" #include "stm32f4xx_rcc.h" #include "stm32f4xx_gpio.h" #include "stm32f4xx_tim.h" #include "xprintf/xprintf.h" #define TimerTick (SystemCoreClock/1000-1) // Получим 1 килогерц int counter = 0; int flag = 0; // SysTick Interrupt Handler //void SysTick_Handler(void) void TIM6_DAC_IRQHandler(void) { /* Так как этот обработчик вызывается и для ЦАП, нужно проверять, * произошло ли прерывание по "переполнению" счётчика таймера TIM6. */ if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) { /* Очищаем бит обрабатываемого прерывания */ TIM_ClearITPendingBit(TIM6, TIM_IT_Update); flag = 1; } } int main(void) { SystemInit(); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD , ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOD, &GPIO_InitStructure); //********************************************** // Настроим таймер TIM RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); // включаем тактирование таймера /* Другие параметры структуры TIM_TimeBaseInitTypeDef * не имеют смысла для базовых таймеров. */ TIM_TimeBaseInitTypeDef base_timer; // TIM_TimeBaseStructInit(&base_timer); /* Делитель учитывается как TIM_Prescaler + 1, поэтому отнимаем 1 */ // base_timer.TIM_Prescaler = 16 - 1; // 16MHz/16 = 1000KHz // base_timer.TIM_Prescaler = 168 - 1; // (168)MHz/168 = 1000KHz (168/RCC_CFGR_PPRE1_DIV1-freq from PLL (1/1) for APB1) // base_timer.TIM_Prescaler = 84 - 1; // (84)MHz/84 = 1000KHz (168/RCC_CFGR_PPRE1_DIV4-freq from PLL (1/2) for APB1) base_timer.TIM_Prescaler = 42 - 1; // (42)MHz/42 = 1000KHz (168/RCC_CFGR_PPRE1_DIV8-freq from PLL (1/4) for APB1) base_timer.TIM_Period = 1000-1; //период 1000 тактов == получим прерывания через 1мс (1KHz) base_timer.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM6, &base_timer); TIM_ARRPreloadConfig(TIM6, ENABLE); /* Разрешаем прерывание по обновлению (в данном случае - * по переполнению) счётчика таймера TIM6. */ TIM_ClearITPendingBit(TIM6, TIM_IT_Update); TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE); TIM_Cmd(TIM6, ENABLE); // Включаем таймер /* Разрешаем обработку прерывания по переполнению счётчика * таймера TIM6. это же прерывание * отвечает и за опустошение ЦАП. */ NVIC_SetPriority(TIM6_DAC_IRQn, 15); NVIC_EnableIRQ(TIM6_DAC_IRQn); //********************************************** xprintf("dv\n"); while(1) { if( flag == 1 ) { if(counter == 0) { GPIO_SetBits(GPIOD, GPIO_Pin_12); } counter++; if(counter == 1000) { GPIO_ResetBits(GPIOD, GPIO_Pin_12); } if(counter == 2000) { counter = 0; } flag = 0; } } } Вот настройки моей системы: #if !defined (HSE_VALUE) #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ #endif /* HSE_VALUE */ ... /************************* PLL Parameters *************************************/ /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */ #define PLL_M 8 #define PLL_N 336 /* SYSCLK = PLL_VCO / PLL_P */ #define PLL_P 2 Система каждую 1 секунду переключает состояние светодиода (горит/НЕгорит) (проверялось на плате STM32F4-Discovery). Обратим внимание на строки: // base_timer.TIM_Prescaler = 16 - 1; // (16)MHz/16 = 1000KHz (16MHz - internal clock without SystemInit()-function) // base_timer.TIM_Prescaler = 168 - 1; // (168)MHz/168 = 1000KHz (168/RCC_CFGR_PPRE1_DIV1-freq from PLL (1/1) for APB1) // base_timer.TIM_Prescaler = 84 - 1; // (84)MHz/84 = 1000KHz (168/RCC_CFGR_PPRE1_DIV4-freq from PLL (1/2) for APB1) base_timer.TIM_Prescaler = 42 - 1; // (42)MHz/42 = 1000KHz (168/RCC_CFGR_PPRE1_DIV8-freq from PLL (1/4) for APB1) base_timer.TIM_Period = 1000-1; //период 1000 тактов == получим прерывания через 1мс (1KHz) Т.е. при использовании параметра для PLL - prescale=RCC_CFGR_PPRE1_DIV1, таймер (TIM6) тактируется частотой 168МГц, что СОВСЕМ НЕ СООТВЕТСТВУЕТ приведенной выше таблице (из официального документа-DataSheet на кристалл). Как эту всю байду с тактированием таймеров (конкретно - для TIM6) понять???
  7. - здесь я опечатался: - здесь вместо RCC_CFGR_PPRE1_DIV2 следует писать RCC_CFGR_PPRE1_DIV4. Т.е. если устанавливаем RCC_CFGR_PPRE1_DIV1 или RCC_CFGR_PPRE1_DIV2, то частота, поступающая на таймер, не делится, а при RCC_CFGR_PPRE1_DIV4 - частота делится на 2, при RCC_CFGR_PPRE1_DIV8 - на 4, при RCC_CFGR_PPRE1_DIV16 - на 8. Т.е. высказывание: - считаю точным описанием поведения определения частот тактирования таймеров. По поводу максимальных частот таймеров нашел таблицу: - сброс всех установочных регистров выполняется в функции SystemInit() - сначала все сбросы, а затем вызов функции SetSysClock(), которая уже и устанавливает частоты. Пока я не пишу свою функцию инициализации, а пытаюсь разобрать библиотечные, чтобы потом уже составить свою.
  8. я об этом и говорю, что без деления и при делении на 2 - получаем тактовую на таймер одинаковую. - конечно. Если я поставлю "RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;", то частота падает вдвое. З.Ы.: Блин.. хоть немного понятно стало.
  9. Тут нарыл в даташите: - это к вопросу удвоения частоты тактирования таймеров. А в Референсе нашел следующее: , но это только для STM32F42/43хх. Значит в моем случае (STM32F407) на таймеры поступает прямая частота с PLL (не умноженная). Здесь еще один "прикол": при установках "RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;" и "RCC->CFGR |= RCC_CFGR_PPRE1_DIV1;" таймеры тикают с одинаковой частотой. В описании регистра RCC->CFGR сказано: При: #define RCC_CFGR_PPRE1_DIV1 ((uint32_t)0x00000000) /*!< HCLK not divided */ #define RCC_CFGR_PPRE1_DIV2 ((uint32_t)0x00001000) /*!< HCLK divided by 2 */ тиканье должно отличаться в два раза. Чота с этими таймерами/тактовыми ваще х.. какая-то. И эту хрень нужно постоянно таскать с собой в голове при написании кода .
  10. см.: - дабы иметь под рукой русскую версию при начальной работе над USB (я еще не реализовывал этот интерфейс на СТМ), да и помочь другим начинающим.
  11. ...да... вместо PLL-prescaler нужно понимать prescaler для шин (АРВ1 и АРВ2), которые задаются в RCC->CFGR. UPD: спасибо за помощь. Сейчас занимаюсь переводом главы USB on-the-go full-speed (OTG_FS) из Референса, Никто не встречал уже переведенной версии(?), иначе жалко будет потраченного времени. Если перевод не найдется, то постараюсь аккуратно оформить и выложить в сеть.
  12. Кстати, нашел еще один параметр, который надо поменять под свой внешний кварц: #define PLL_M 25, нужно сделать 8. Так, немного подсоберу все в одну картину: 1. В функции SystemInit() происходит настройка частот системы и PLL на 168МГц(при работе с внешним кварцем), при условии установки правильных дефайнов (HSE_VALUE, PLL_M, и может еще каких..). 2. Если в настройках PLL параметр prescaler не равен 1, то таймеры (на шинах APBx) тактируются удвоенной частотой, иначе НЕудвоенной(прямой). 3. В случае, если мы не используем функцию SystemInit(), то мы не запускаем PLL (если, конечно, отдельно не прописали этот запуск), и следовательно: частота у нас используется внутренняя (16МГц), а таймеры тактируются тоже этой же частотой 16МГц (не удвоенной, т.к. PLL-prescaler в коде не был установлен). Я правильно рассуждаю?
  13. Да, нашел это место, спасибо. Тогда получается, что при НЕвызове функции SystemInit() таймер_6 тактируется просто внутренней частотой, а не удвоенной (где-то это вычитал в инете и оказалось, что это обман).
  14. И светодиод задействую, по-необходимости, но это всё все-равно будет только вечером, дома. А пока на работе есть время поразбирать/подготовить какие-либо коды, в том числе и использование printf'a (он потом все-таки пригодится, и чем быстрее я его зпущу, тем проще будет дальнейшая жизнь и отладка). По настройкам: #if !defined (HSE_VALUE) /** * @brief In the following line adjust the value of External High Speed oscillator (HSE) used in your application Tip: To avoid modifying this file each time you need to use different HSE, you can define the HSE value in your toolchain compiler preprocessor. */ #define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */ #endif /* HSE_VALUE */ /** * @brief In the following line adjust the External High Speed oscillator (HSE) Startup Timeout value */ #if !defined (HSE_STARTUP_TIMEOUT) #define HSE_STARTUP_TIMEOUT ((uint16_t)0x0500) /*!< Time out for HSE start up */ #endif /* HSE_STARTUP_TIMEOUT */ #if !defined (HSI_VALUE) #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ #endif /* HSI_VALUE */ Здесь 25000000 нужно заменить на 8000000 (внешний кварц 8МГц вроде стоит). HSE_STARTUP_TIMEOUT - менять думаю не стоит. А вот почему на "заводе" HSI_VALUE 16000000 поставили, это мне не понятно, вроде для этих кристаллов должна быть внутренняя частота 8МГц, или я ошибаюсь??
  15. Вы про stm32f4xx.h-файл? Там всякие определения/размещения регистров, маски, макросы управления битами. Так-то по всей линейке (F4) вроде по регистрам должно быть полное соответствие (помнится где-то встречал такую фразу по СТМ).
  16. При работе с ПЛИС, при софтовой разработке/настройке контроллеров интерфейсов, всегда хочется иметь Hard'овый контроллер, проверенный/протестированный/заточенный под нужнй интерфейс. А с другой стороны, работая с Железными реализациями контроллеров, иногда хочется что-то подправить/переделать под себя, но уже нельзя, т.к. в микруху не полезешь. При больших загрузках ПЛИСок, да и при больших частотах работы процессов (100-200 МГЦ), ПЛИС начинает нормально греться, поэтому нужно обеспечивать теплоотводы. Про сам НИОС могу сказать - при нормальных (НЕкривых) настройках вещь стабильная, каких-то непонятных сбоев не наблюдал. Про контроллеры интерфейсов - здесь да... иногда нужен настоящий "Шаманский" бубен, чтобы ОНО заработало.
  17. - это уже идут настройки Вашего кристалла/драйвера, а не PHY. Я, настроив свои контроллеры в ПЛИСке, просто ждал появления линка от PHY, и все, начинал работать. Правда, для меня было совсем не важно в каком режиме, на какой скорости идут обмены, мне нужен был очень медленный обмен, поэтому я и не заморачивался. На начальном этапе на Вашем месте я бы также забил на все эти настройки и поработал с автоматическими настройками PHY, а потом уже можно и поработать напильником для улучшения характеристик.
  18. Тоже работал с несколькими типами PHY, правда работал с ПЛИСками (но это не важно от куда управлять), и, действительно, все настройки сводились только на настройку драйверов своих кристаллов (ПЛИС).
  19. - что вы имеете в виду? При создании проекта я выбирал кристалл, и это, как я предполагаю, и определяет всякие там дефайны. По поводу контроля регистров (RCC_CFGR) - нашел какую-то реализацию printf'a, люди пишут, что работает, вечером попробую запустить. И если все пойдет нормально, то можно будет контролировать все регистры настройки системы.
  20. При установке base_timer.TIM_Prescaler = (42-1) и (21-1) получаю тоже неверный результат, светодиод разбегается с часами(секундомером) уже за 10-15 тиков (морганий). Вы работали с подобной задачей/кодом? или все теория? (Просто я уже много где потыкался, а результат пока один - тактовая на таймере непонятно-какая и чем определена)
  21. В systemInit() dspsdftncz SetSysClock(), код которой: static void SetSysClock(void) { /******************************************************************************/ /* PLL (clocked by HSE) used as System clock source */ /******************************************************************************/ __IO uint32_t StartUpCounter = 0, HSEStatus = 0; /* Enable HSE */ RCC->CR |= ((uint32_t)RCC_CR_HSEON); /* Wait till HSE is ready and if Time out is reached exit */ do { HSEStatus = RCC->CR & RCC_CR_HSERDY; StartUpCounter++; } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); if ((RCC->CR & RCC_CR_HSERDY) != RESET) { HSEStatus = (uint32_t)0x01; } else { HSEStatus = (uint32_t)0x00; } if (HSEStatus == (uint32_t)0x01) { /* Select regulator voltage output Scale 1 mode, System frequency up to 168 MHz */ RCC->APB1ENR |= RCC_APB1ENR_PWREN; PWR->CR |= PWR_CR_VOS; /* HCLK = SYSCLK / 1*/ RCC->CFGR |= RCC_CFGR_HPRE_DIV1; /* PCLK2 = HCLK / 2*/ RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; /* PCLK1 = HCLK / 4*/ RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; /* Configure the main PLL */ RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24); /* Enable the main PLL */ RCC->CR |= RCC_CR_PLLON; /* Wait till the main PLL is ready */ while((RCC->CR & RCC_CR_PLLRDY) == 0) { } /* Configure Flash prefetch, Instruction cache, Data cache and wait state */ FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; /* Select the main PLL as system clock source */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= RCC_CFGR_SW_PLL; /* Wait till the main PLL is used as system clock source */ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL); { } } else { /* If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error */ } } А строка /* Select regulator voltage output Scale 1 mode, System frequency up to 168 MHz */ - вообще внушает уверенность и оптимизм в 168МГц. Но вот, почему-то, это не работает.
  22. В SystemInit() - вроде какие-то предделители устанавливаются... (я, если честно, не встречал таких, как вы говорите, при поисках всяких исходников для установки таймеров). То, что я нарыл (по-быстрому) в инете, я и накидал в своем коде, НИКАКИХ доп. установок не встречал. Можете по-подробнее объяснить мою недоработку. (если можно, то с кодом)
  23. Здравствуйте. Хочу заставить светодиод мигать с тактом 1с. Казалось бы - задача тривиальней некуда. Но я зашел в тупик. Пишу простейший код: #include "stm32f4xx.h" #include "stm32f4xx_rcc.h" #include "stm32f4xx_gpio.h" #include "stm32f4xx_tim.h" int counter = 0; int flag = 0; void TIM6_DAC_IRQHandler(void) { /* Так как этот обработчик вызывается и для ЦАП, нужно проверять, * произошло ли прерывание по "переполнению" счётчика таймера TIM6. */ if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) { /* Очищаем бит обрабатываемого прерывания */ TIM_ClearITPendingBit(TIM6, TIM_IT_Update); flag = 1; } } int main(void) { // SystemInit(); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD , ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOD, &GPIO_InitStructure); //********************************************** // Настроим таймер TIM RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); // включаем тактирование таймера TIM_TimeBaseInitTypeDef base_timer; TIM_TimeBaseStructInit(&base_timer); /* Делитель учитывается как TIM_Prescaler + 1, поэтому отнимаем 1 */ base_timer.TIM_Prescaler = 16 - 1; base_timer.TIM_Period = 1000-1; base_timer.TIM_ClockDivision = TIM_CKD_DIV1; base_timer.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM6, &base_timer); TIM_ARRPreloadConfig(TIM6, ENABLE); /* Разрешаем прерывание по обновлению (в данном случае - * по переполнению) счётчика таймера TIM6. */ TIM_ClearITPendingBit(TIM6, TIM_IT_Update); TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE); TIM_Cmd(TIM6, ENABLE); // Включаем таймер /* Разрешаем обработку прерывания по переполнению счётчика * таймера TIM6. это же прерывание * отвечает и за опустошение ЦАП. */ NVIC_SetPriority(TIM6_DAC_IRQn, 15); NVIC_EnableIRQ(TIM6_DAC_IRQn); //********************************************** while(1) { // отсчитываем каждые 1000 тактов таймера и переключаем светодиод if( flag == 1 ) { if(counter == 0) { GPIO_SetBits(GPIOD, GPIO_Pin_12); } counter++; if(counter == 1000) { GPIO_ResetBits(GPIOD, GPIO_Pin_12); } if(counter == 2000) { counter = 0; } flag = 0; } } } - мигает как надо. Но здесь параметры: base_timer.TIM_Prescaler = 16 - 1; и base_timer.TIM_Period = 1000-1;, т.е. получается, что частота тактирования = 16МГц. Это можно объяснить тем, что идет тактирование от внутреннего генератора (8МГц), но с удвоенной частотой (это, типа, из-за использования предделителей, не равных 1 на шине АРВ1). Но так-то я раситывал на 168МГц. Пробовал с разными коэффициентами - полная ерунда. Если я раскомментирую строчку // SystemInit(); , то светик мигает почти с тактом в 1 сек, но "ПОЧТИ"=чуть-чуть быстрее. В чем может быть моя неправда? Ткните носом, ПЛЗ. Или объясните матчасть (может все так и должно быть :05: ). ИМХО, кварц может глючит? (но проверить нечем, нет никаких девайсов)
  24. Спасибо за подсказку. Я не нашел этого момента в доке "референс мануале", поэтому и задал вопрос. я разбираю конкретный проект, который у автора работает. А использование ST мне просто не нравится, т.к. посторение этой "библиотеки" для меня неприемлимо. Как разработчику "своих" проектов, мне интересна разработка с ноля, и не по навязываемому шаблону, а именно по такой структуре, по которой я захочу.
×
×
  • Создать...