Jump to content

    
Sign in to follow this  
Сергей Борщ

STM32F070, подстава от ST в документации.

Recommended Posts

Имеем руководство пользователя для STM32F030, STM32F070. Смотрим картинку тактирования F070:

image.png.d528eeb72267e494d07c040dc674ae4f.png

Читаем описание:

image.thumb.png.27e8ef293d02f0cb80f51417499d75d9.png

image.thumb.png.07fe6c132453a9db6fb298660167d2b7.png

Уже странновато - в PLLSRC фигурирует откуда-то HSI/2. Ну хорошо, это оно так у STM32F030 из этого же руководства:

image.png.ca1d5928e35738d9b32ec43d925a21da.png

Допустим, забыли сделать сноску, что у 030 там HSI/2, а у 070, судя по картинке, там должно быть HSI/PREDIV.

Нам пофиг, нам нужно запитать PLL от HSE. Берем и спокойно пишем код

RCC->CFGR |= 1 * RCC_CFGR_PLLSRC;

Все же логично, RCC_CFGR_PLLSRC - однобитовое поле! И захвата PLL не происходит. Причем этот же код на 030 дает захват. А если запитать PLL от HSI, то есть убрать эту строку из кода - захват происходит. В процессе поиска ошибки мы обнаруживаем, что при запитке PLL от HSI значение PREDIV ни на что не влияет, между HSI и PLL гвоздями прибит делитель на 2. И только через часов 6 отладки, разбирая от безысходности сгенеренный кубом исходник мы обнаруживаем в загловочном файле такое:

#define RCC_CFGR_PLLSRC_Pos                      (15U)                         
#define RCC_CFGR_PLLSRC_Msk                      (0x3U << RCC_CFGR_PLLSRC_Pos) /*!< 0x00018000 */
#define RCC_CFGR_PLLSRC                          RCC_CFGR_PLLSRC_Msk           /*!< PLL entry clock source */
#define RCC_CFGR_PLLSRC_HSI_DIV2                 (0x00000000U)                 /*!< HSI clock divided by 2 selected as PLL entry clock source */
#define RCC_CFGR_PLLSRC_HSI_PREDIV               (0x00008000U)                 /*!< HSI/PREDIV clock selected as PLL entry clock source */
#define RCC_CFGR_PLLSRC_HSE_PREDIV               (0x00010000U)                 /*!< HSE/PREDIV clock selected as PLL entry clock source */

То есть по факту у STM32F070 PLLSRC имеет размер два бита, и запись  "1 * RCC_CFGR_PLLSRC" дает в них запрещенную комбинацию из обоих единичек.

Шах и блять!

Share this post


Link to post
Share on other sites
17 minutes ago, Сергей Борщ said:

То есть по факту у STM32F070 PLLSRC имеет размер два бита, и запись  "1 * RCC_CFGR_PLLSRC" дает в них запрещенную комбинацию из обоих единичек.

Помнится, тоже знатно оттоптался на этих граблях :)

Share this post


Link to post
Share on other sites
10 минут назад, MasterElectric сказал:

Сергей Борщ подскажите с каким конкретно чипом такая засада, сделаю заметку.

Дело не в чипе, а в библиотеках ST.

Там везде для битовых полей определяется маска.

И работать с ней нужно как с маской.

RCC->CFGR |= 1 * RCC_CFGR_PLLSRC;

Так делать нельзя. Нужно как-то так

RCC->CFGR &= RCC_CFGR_PLLSRC;
RCC->CFGR |= RCC_CFGR_PLLSRC_1; [RCC_CFGR_PLLSRC_HSI_DIV2 | RCC_CFGR_PLLSRC_HSE_PREDIV | etc]

Разумеется, кроме описания регистра нужно смотреть и на схему блока, читать весь текст и т.п.

Кста, я по ходу добавляю определений в свою библиотеку, где определяю не маски, а номера битов - путаницы гораздо меньше

#define RCC_CFGR_PLLSRC			(15UL)

RCC->CFGR = 0
  | (0 << RCC_CFGR_ADCPRE)
  | (0 << RCC_CFGR_PPRE)
  | (0 << RCC_CFGR_HPRE)
  | (4 << RCC_CFGR_PLLMUL)
  | (2 << RCC_CFGR_PLLSRC)
  ;

Share this post


Link to post
Share on other sites
1 hour ago, adnega said:

Там везде для битовых полей определяется маска.

И работать с ней нужно как с маской. 

Так в описании-то это единичный бит, а в хидере - поле. Вот в чем засада.

Share this post


Link to post
Share on other sites
5 минут назад, aaarrr сказал:

Так в описании-то это единичный бит, а в хидере - поле. Вот в чем засада.

Я начинал заполнять библиотеку с STM32F0x2. Там это два бита

image.png.949893d53ce1ff31ff1243a6ff4953a6.png

Share this post


Link to post
Share on other sites
1 час назад, adnega сказал:

Так делать нельзя.

Какой кошмар! Все мои программы в топку... adnega запертил :girl_cray2:

Открываем заголовочный файл на F030:

#define RCC_CFGR_PLLSRC_Pos                      (16U)                         
#define RCC_CFGR_PLLSRC_Msk                      (0x1U << RCC_CFGR_PLLSRC_Pos) /*!< 0x00010000 */
#define RCC_CFGR_PLLSRC                          RCC_CFGR_PLLSRC_Msk           /*!< PLL entry clock source */
#define RCC_CFGR_PLLSRC_HSI_DIV2                 (0x00000000U)                 /*!< HSI clock divided by 2 selected as PLL entry clock source */
#define RCC_CFGR_PLLSRC_HSE_PREDIV               (0x00010000U)                 /*!< HSE/PREDIV clock selected as PLL entry clock source */

Там PLLSRC - один бит. Почему с ним нельзя делать RCC->CFGR |= 1 * RCC_CFGR_PLLSRC ?

Share this post


Link to post
Share on other sites

Насчет преемственности. На днях погубил не один миллиард нервных клеток из-за регистра ADC->CCR.

У одних он по адресу +308h (STM32F303, STM32F0xx), а у кого-то +304h (STM32F40x, STM32L152)

 

Share this post


Link to post
Share on other sites
8 минут назад, adnega сказал:

Я начинал заполнять библиотеку с STM32F0x2. Там это два бита

А у меня в плату впаян F070. По наводке AHTOXA я глянул в руководство пользователя F072 - там картинка системы тактирования не имеет ничего общего с картинкой F070. Я в описание его регистров даже и смотреть не стал.

1 час назад, adnega сказал:

Так делать нельзя. Нужно как-то так

Я делаю иначе:

    RCC->CFGR = 0
        | 0 * RCC_CFGR_PLLNODIV                                 // PLL divider for MCO: 0: MCO = PLL/2, 1: MCO=PLL/1
        | 4 * (RCC_CFGR_MCOPRE & -RCC_CFGR_MCOPRE)              // MCO prescaler, 0: /1, 1: /2, 2: /4, 3: /8, 4: /16,
                                                                // 5: /32, 6: /64, 7: /128
        | 7 * (RCC_CFGR_MCOSEL & -RCC_CFGR_MCOSEL)              // MCO source, 0: disabled, 1: HSI14, 2: LSI, 3: LSE,
                                                                //             4: SYSCLK, 5: HSI, 6: HSE, 7: PLL
        | (PLL_MUL - 2) * (RCC_CFGR_PLLMUL & -RCC_CFGR_PLLMUL)  // Fvco = Fpll_in / PREDIV * PLLMUL
        | 0 * RCC_CFGR_PLLXTPRE                                 // LSB of PREDIV
        | 2 * (RCC_CFGR_PLLSRC &- RCC_CFGR_PLLSRC)              // PLL source, 0: HSI/2, 1: HSI/PREDIV 2: HSE/PREDIV
        | 0 * (RCC_CFGR_ADCPRE & -RCC_CFGR_ADCPRE)              // ADC clock: obsolete, use ADC->CFGR2 settings
        | (
            (AHBCLK / APBCLK == 1) ? 0
          : (AHBCLK / APBCLK == 2) ? 4
          : (AHBCLK / APBCLK == 4) ? 5
          : (AHBCLK / APBCLK == 8) ? 6
          : (AHBCLK / APBCLK == 16) ? 7
          : (1 << 64)                                           // unsupported value, generate uint32_t overflow warning
          ) * (RCC_CFGR_PPRE & -RCC_CFGR_PPRE)                  // APB prescaler, 0...3: /1, 4: /2, 5: /4, 6: /8, 7: /16
        | (
            (SYSCLK / AHBCLK == 1) ? 0
          : (SYSCLK / AHBCLK == 2) ? 8
          : (SYSCLK / AHBCLK == 4) ? 9
          : (SYSCLK / AHBCLK == 8) ? 10
          : (SYSCLK / AHBCLK == 16) ? 11
          : (SYSCLK / AHBCLK == 64) ? 12
          : (SYSCLK / AHBCLK == 128) ? 13
          : (SYSCLK / AHBCLK == 256) ? 14
          : (SYSCLK / AHBCLK == 512) ? 15
          : (1 << 64)                                           // unsupported value, generate uint32_t overflow warning
          ) * (RCC_CFGR_HPRE & -RCC_CFGR_HPRE)                  // AHB prescaler, 0...7: /1, 8: /2, 9: /4, 10: /8, 11: /16
                                                                //                12: /64, 13: /128, 14: /256, 15: /512
        | 2 * (RCC_CFGR_SW & -RCC_CFGR_SW)                      // SYSCLK source: 0 = HSI, 1 = HSE, 2 = PLL
        ;

 

Share this post


Link to post
Share on other sites
3 минуты назад, Сергей Борщ сказал:

Все мои программы в топку... adnega запертил :girl_cray2:

Ок. Я погорячился. Скажем так:

- есть операция деления

- на ноль делить нельзя.

Это не означает, что делить нельзя. Делить можно, только аккуратно.

В общем случае умножать на маску - нельзя, за исключением двух значений "0" или "1".

Я так понял, вы ими только так и пользуетесь. Я поторопился и подумал, что вместо "1" можно подставлять "2" и т.д.

Т.е. проблема в том, что где-то RCC_CFGR_PLLSRC == 0x0001_0000, а где-то 0x0001_8000.

Share this post


Link to post
Share on other sites
1 минуту назад, adnega сказал:

Я так понял, вы ими только так и пользуетесь. Я поторопился и подумал, что вместо "1" можно подставлять "2" и т.д.

Да, именно так. Мир-дружба.

Share this post


Link to post
Share on other sites
Только что, Сергей Борщ сказал:

Да, именно так. Мир-дружба.

Конечно!

Просто я видел два варианта использования битовых полей: AVR-подобный (определяет номера битов) и STM-подобный (определяет маски).

Исторически сложилось, что мне удобнее AVR-стиль со сдвигами. И библиотеку под STM я начал заполнять задолго до SPL/HAL/etc только на основе RM.

У вас получается какой-то гибрид: используете определения масок, а за счет магии работаете как с битами.

Мне нравится ваше решение, т.к. оно кажется удобным (поскольку AVR-похожее) и при этом сохраняется совместимость с заголовочными файлами производителя (и их не нужно делать/переделывать самому). эхх... где вы были 10 лет назад ;))

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this