Embedded HandbookПриложения
Все разделы › I. Основы
STM32U585CIU6 · уровень средний · 13 мин чтения
Открыть в интерактивном справочнике

2д. STM32U585CIU6 в корпусе на 48 выводов: что остаётся от U585 и на что его ставить

Раздел 2б сравнил U585 с F405 и разобрал TrustZone, 10а — его режимы сна. Там U585 — кристалл целиком: 2 МБ Flash, 786 КБ ОЗУ, десятки блоков. Здесь — самый маленький его корпус, UFQFPN48 (буква C в маркировке, 2б.1). Кристалл тот же, но наружу выходит меньше половины сигналов. Вопрос раздела практический: какая периферия в 48 выводах реально доступна, чем питать, как запустить на 160 МГц и что из этого собрать.

Опоры: даташит DS13086 (ред. 8) и справочное руководство RM0456 (ред. 4) из пака Keil STM32U5xx_DFP 2.2.1, заголовок stm32u585xx.h оттуда же; описания кристаллов STM32U585CIUx.xml и STM32U585CIUxQ.xml из базы STM32CubeMX; пакет платы B-U585I-IOT02A_BSP 1.1.0. Периферию по выводам и три изделия считает скрипт на ПК по файлам CubeMX. Код старта собран armclang и прогнан на ПК над «регистрами» в памяти. QEMU U5 не моделирует, на плате не запускалось.

Как это называется в документации

Оригинал Перевод
UFQFPN48 безвыводной корпус 7×7 мм, 48 контактов по сторонам
Dedicated pinout supporting SMPS (Q) разводка выводов под импульсный стабилизатор — буква Q в конце маркировки
LDO / SMPS step-down converter линейный стабилизатор / импульсный понижающий стабилизатор ядра
VCAP, VDD11 вывод ядра под конденсатор: у LDO — VCAP, у SMPS — два VDD11
Voltage scaling range 1…4 диапазон напряжения ядра: 1 — самый быстрый, 4 — самый экономный
EPOD booster усилитель питания ядра: без него выше 55 МГц нельзя
MSIS, MSIK два выхода внутреннего генератора MSI: для ядра и для периферии
OCTOSPIM коммутатор выводов двух контроллеров OCTOSPI
Linked-list item (GPDMA) элемент связного списка: описание следующей пересылки в памяти

2д.1 Два кристалла под одной маркировкой

Даташит перечисляет у U585 восемь корпусов от 48 до 169 выводов. В 48 есть два варианта, и CubeMX хранит их отдельными файлами:

STM32U585CIU6 STM32U585CIU6Q
Стабилизатор ядра LDO, вывод VCAP SMPS и LDO, выводы VLXSMPS, VDDSMPS, VSSSMPS, два VDD11
Ввод-вывод 37 33
Питание и сброс 11 15
Выводы пробуждения 17 15
Входы АЦП (выводы) 11 10
Каналы сенсорных кнопок TSC 5 4

Буква Q в схеме заказа — «разводка под SMPS». Под дроссель и второе питание ядра уходят выводы 20…25 и 46; вместе с ними исчезают PB2, PB10, PB12 и PB9. Остальные 41 вывод совпадают.

Выводы STM32U585CIU6 в корпусе UFQFPN48, вид сверху: 37 выводов ввода-вывода и 11 питания и сброса; красным — выводы 20…25 и 46, которые в CIU6Q заняты SMPS: VLXSMPS, VDDSMPS, VSSSMPS, VDD11 вместо PB2, PB10, VCAP и PB12, сдвинутые VSS и VDD, VDD11 вместо PB9

Ещё из рисунка видно, чего в 48 выводах нет совсем: портов D, E, F, G и I; от порта C остались PC13…PC15, от порта H — PH0, PH1 и PH3 (он же BOOT0). Пять выводов заняты почти всегда: PA13 и PA14 — SWD, PH3 — выбор загрузки, PC14 и PC15 — часовой кварц.


2д.2 Что выведено: периферия по экземплярам

Скрипт pins2f.py берёт из файла CubeMX список сигналов каждого вывода и для каждого блока ищет полный набор на разных выводах: у UART — TX и RX, у SPI — SCK, MISO, MOSI, у I2C — SCL и SDA. Сигнал на выводе ещё не значит, что блок работает: у USART3 вход RX есть только на PA5, и если PA5 занят, USART3 нет.

Блок CIU6 (LDO) CIU6Q (SMPS)
USART1, USART2, USART3, UART4, LPUART1 все пять все пять
SPI1, SPI2, SPI3 все три все три
I2C1…I2C4 все четыре все четыре
FDCAN1 PA11/PA12 или PB8/PB9 только PA11/PA12
USB OTG FS, UCPD1 есть есть
SAI1 блоки A и B блоки A и B
OCTOSPI Quad: CLK, NCS, IO0…IO3; IO4…IO7 нет то же, CLK только на PA3
SDMMC, DCMI, FMC, UART5 нет нет
TIM1…TIM5 по 4 канала у TIM4 — 3
TIM8 только CH1N…CH4N только CH1N…CH3N
TIM15, TIM16, TIM17 2, 1 и 1 канал 2, 1 и 1 канал
LPTIM1…LPTIM3 / LPTIM4 по 2 канала / выводов нет то же
Входы АЦП 11: ADC1 — 11, ADC4 — 6 10
DAC1 PA4, PA5 PA4, PA5

Итоги совпали с таблицей 2 даташита для STM32U585CI: 37/33 ввода-вывода, 17/15 выводов пробуждения, 11/10 каналов АЦП, SPI — 3, I2C — 4, USART — 3, UART — 1, SAI — 1, SDMMC — 0. Таймеров и последовательных портов хватает; в 48 выводах теряются параллельные шины (FMC, камера, SDMMC), вторая SAI и восьмилинейный OCTOSPI.


2д.3 Питание: SMPS или LDO, VBAT, VDDA и USB

Ядро. У U585 два стабилизатора ядра, включённых параллельно. LDO просит конденсатор 4,7 мкФ на VCAP, SMPS — дроссель 2,2 мкГн, по 2,2 мкФ на каждый из двух VDD11 и 10 мкФ на VDDSMPS; частота переключения SMPS — 3 МГц при VDD выше 1,9 В. После сброса работает LDO в диапазоне 4, на SMPS переключает бит REGSEL в PWR_CR3 — в любом диапазоне и на ходу.

Выгода — в токе. Ядро на 160 МГц от PLL, периферия выключена, 25 °C, типовые значения:

Стабилизатор VDD Ток
LDO 3,0 В 13,50 мА
SMPS 3,0 В 7,15 мА
SMPS 1,8 В 10,50 мА

От 3 В импульсный стабилизатор почти вдвое экономнее. Цена — шум: RM прямо пишет, что некоторым приложениям SMPS мешает, и тогда переключаются на LDO. А в корпусе без Q бит REGSEL зарезервирован и должен оставаться нулём: у CIU6 есть только LDO.

VBAT (вывод 1): 1,65…3,6 В, питает RTC, блок TAMP, часовые генераторы 32 кГц, 2 КБ резервного ОЗУ и 32 резервных регистра. Входов вскрытия в 48 выводах три, активных — два. Режимы сна и срок батареи — в 10а.

VDDA и VREF+. Отдельного VREF+ в 48 выводах нет: он соединён с VDDA внутри корпуса, VREF− — с VSSA. Поэтому опорное напряжение АЦП и ЦАП — само VDDA, а встроенный буфер VREFBUF недоступен и должен оставаться выключенным. Точность АЦП здесь равна точности аналогового питания.

USB. VDDUSB по даташиту — 3,0…3,6 В, но в таблице выводов у обоих 48-выводных корпусов на его месте прочерк. Отдельно его не подать, так что для USB всё питание камня держат в этих пределах; даташит об этом прямо не пишет, это вывод из таблиц. Бит USV в PWR_SVMCR ставят всё равно: без него USB изолирован от своего питания.


2д.4 Внешняя флеш и GPDMA

У OCTOSPI в 48 выводах один порт P1 и четыре линии данных: IO0 — PB1, IO1 — PB0, IO2 — PA7, IO3 — PA6, такт — PA3 или PB10, выбор — PA2 или PA4. Этого хватает на Quad-SPI-флеш из раздела 41в, а восьмилинейную память не подключить. У порта P2 выведен только выбор кристалла (PA0 или PA12). Даташит так и пишет: два контроллера OCTOSPI в этом корпусе — только в мультиплексном режиме. Они делят линии P1 по очереди, а выбор у каждого свой: так на одну шину сажают две микросхемы.

Для сравнения — отладочная плата B-U585I-IOT02A: на ней U585 в корпусе на 169 шариков, флеш MX25LM51245G на OCTOSPI2 работает на восьми линиях с двойной скоростью (режимы OPI и DTR в пакете платы), выводы — порты F, H и I. Пример с этой платы на 48 выводов не переносится.

Пересылки между флеш, ОЗУ и периферией ведёт GPDMA1: 16 каналов, у каждого своя очередь данных и связный список — цепочка описаний пересылок в памяти, которую контроллер проходит сам. Каналы неравные:

Каналы Буфер Адресация Для чего
0…11 8 байт линейная периферия на APB и AHB ↔ ОЗУ
12…15 32 байта двумерная тяжёлая периферия AHB, внешняя память

Под OCTOSPI берут канал из 12…15. GPDMA1 работает сама в Sleep, Stop 0 и Stop 1; в Stop 2 остаётся только LPDMA1.


2д.5 Такт 160 МГц и минимальный старт

После сброса ядро идёт от MSIS на 4 МГц, Flash без задержек, стабилизатор — LDO в диапазоне 4. До 160 МГц путь по RM0456 (10.5.4) такой:

  1. Источник PLL1 — MSIS: 4 МГц на входе PLL попадают в окно 4…8 МГц (PLL1RGE = 00). Делитель бустера — 1 (PLL1MBOOST = 0): бустер хочет 4…16 МГц.
  2. Диапазон 1 (VOS = 11) и бустер BOOSTEN; ждать VOSRDY и BOOSTRDY. Без готового бустера выше 55 МГц переходить нельзя.
  3. Задержки Flash: в диапазоне 1 — 4 такта до 160 МГц (3 — до 128 МГц). ОЗУ в диапазоне 1 до 160 МГц задержек не требует.
  4. PLL1: ×80 → VCO 320 МГц (окно 128…544), выход R ÷2 → 160 МГц.
  5. Переключить SW на PLL1 и дождаться SWS.

Для U59x/5Ax/5Fx/5Gx RM требует ещё подниматься выше 80 МГц через делитель AHB; к U585 это не относится.

/* Раздел 2д: минимальный старт STM32U585CIU6 / CIU6Q — стабилизатор, 160 МГц от MSIS, задержки Flash.
   Порядок — RM0456, 10.5.4 (повышение диапазона напряжения) и 7.3.3 (задержки Flash).
   USE_SMPS = 1 — только для корпуса с буквой Q (CIU6Q): в CIU6 бит REGSEL зарезервирован. */
#include "stm32u5xx.h"

#ifndef USE_SMPS
#define USE_SMPS 0
#endif

#define MSIS_HZ   4000000u          /* MSIS после сброса */
#define PLL_M     1u                /* 4 МГц на вход PLL1: окно 4…8 МГц, PLL1RGE = 00 */
#define PLL_N     80u               /* VCO 320 МГц: окно 128…544 МГц */
#define PLL_R     2u                /* PLL1R: только 1 или чётное */
#define REF_HZ    (MSIS_HZ / PLL_M)
#define VCO_HZ    (REF_HZ * PLL_N)
#define SYSCLK_HZ (VCO_HZ / PLL_R)
#define FLASH_WS  4u                /* диапазон 1: 4 такта ожидания — до 160 МГц */

_Static_assert(SYSCLK_HZ == 160000000u, "частота ядра");
_Static_assert(REF_HZ >= 4000000u && REF_HZ <= 8000000u, "вход PLL1 при PLL1RGE = 00");
_Static_assert(VCO_HZ >= 128000000u && VCO_HZ <= 544000000u, "VCO в диапазоне 1");
_Static_assert(SYSCLK_HZ > 128000000u && SYSCLK_HZ <= 160000000u, "4 такта Flash только для 128…160 МГц");
_Static_assert(RCC_PLL1CFGR_PLL1M_Msk == 0x00000F00u, "PLL1M — биты 11:8");
_Static_assert(RCC_PLL1CFGR_PLL1MBOOST_Msk == 0x0000F000u, "PLL1MBOOST — биты 15:12");

void clock_160mhz(void)
{
    RCC->AHB3ENR |= RCC_AHB3ENR_PWREN;                  /* такт блока PWR */
    (void)RCC->AHB3ENR;

#if USE_SMPS
    PWR->CR3 |= PWR_CR3_REGSEL;                         /* LDO -> SMPS */
    while (!(PWR->SVMSR & PWR_SVMSR_REGS)) {
    }
#endif

    /* 1. Источник PLL1 и делитель для бустера: 4 МГц / 1 */
    RCC->PLL1CFGR = RCC_PLL1CFGR_PLL1SRC_0              /* 01: MSIS */
                  | ((PLL_M - 1u) << RCC_PLL1CFGR_PLL1M_Pos);   /* PLL1MBOOST = 0, PLL1RGE = 00 */

    /* 2. Диапазон 1 и бустер: без BOOSTRDY выше 55 МГц нельзя */
    PWR->VOSR = PWR_VOSR_VOS_1 | PWR_VOSR_VOS_0 | PWR_VOSR_BOOSTEN;
    while ((PWR->VOSR & (PWR_VOSR_VOSRDY | PWR_VOSR_BOOSTRDY)) != (PWR_VOSR_VOSRDY | PWR_VOSR_BOOSTRDY)) {
    }

    /* 3. Задержки Flash до повышения частоты */
    FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | FLASH_WS | FLASH_ACR_PRFTEN;
    while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != FLASH_WS) {
    }

    /* 4. PLL1: N и R пишутся минус один; выход R -> SYSCLK */
    RCC->PLL1DIVR = ((PLL_N - 1u) << RCC_PLL1DIVR_PLL1N_Pos)
                  | (1u << RCC_PLL1DIVR_PLL1P_Pos) | (1u << RCC_PLL1DIVR_PLL1Q_Pos)
                  | ((PLL_R - 1u) << RCC_PLL1DIVR_PLL1R_Pos);
    RCC->PLL1CFGR |= RCC_PLL1CFGR_PLL1REN;
    RCC->CR |= RCC_CR_PLL1ON;
    while (!(RCC->CR & RCC_CR_PLL1RDY)) {
    }

    /* 5. Переключение SYSCLK на PLL1 (11) */
    RCC->CFGR1 = (RCC->CFGR1 & ~RCC_CFGR1_SW_Msk) | (3u << RCC_CFGR1_SW_Pos);
    while ((RCC->CFGR1 & RCC_CFGR1_SWS_Msk) != (3u << RCC_CFGR1_SWS_Pos)) {
    }
}

armclang (-std=c11 -Os -Wall -Wextra -pedantic) собирает оба варианта без предупреждений: clock_160mhz — 140 байт с LDO и 152 байта с SMPS. Копия с PLL_N = 90 (180 МГц) не собирается: _Static_assert ловит частоту ещё при компиляции.

Проверка на ПК. model2f.c подключает этот файл без правок, но RCC, PWR и FLASH — структуры в памяти ПК, а второй поток играет железо: ставит флаг готовности, только когда программа включила блок, и запоминает регистры в этот момент. В обоих вариантах PLL1 включается уже при LATENCY = 4 и диапазоне 1 с бустером, SW — после PLL1RDY. Итог: PLL1CFGR = 0x00040001, PLL1DIVR = 0x0101024F, ACR = 0x00000104; по формуле RM это 4 МГц × 80 / 2 = 160 МГц.


2д.6 Три изделия на одном камне

Скрипт раскладывает нужные сигналы по разным выводам перебором и считает, что осталось. Каждый проект держит SWD.

Изделие Камень Что занято Занято / свободно
Датчик на батарейке CIU6Q LSE, I2C3, LPUART1, вывод пробуждения PA0 9 / 24
USB-устройство без кварца CIU6Q LSE, USB, UCPD1 (CC1, CC2), USART1 10 / 23
Узел с внешней флеш CIU6 HSE, OCTOSPI Quad, USB, FDCAN1, USART1 16 / 21

Датчик. CIU6Q — ради SMPS. I2C3 и LPUART1 выбраны не случайно: по даташиту в Stop 2 сами работают только ADC4, DAC1, LPTIM1, LPTIM3, LPTIM4, LPUART1, SPI3, I2C3, ADF1 и LPDMA1. Датчик читается по I2C3, данные уходят в радиомодуль по LPUART1, ядро спит. Свободных входов АЦП остаётся 6, свободны ещё SPI1 и SPI2.

USB без кварца. HSE не нужен: MSIK в диапазоне 0 (около 48 МГц, MSIKRANGE = 0000 при MSIRGSEL = 1) подстраивается по часовому кварцу — MSIPLLSEL = 0, затем MSIPLLEN = 1, и только после LSERDY. USB берёт такт через ICLKSEL = 11. Точность — лучше ±0,25 % по даташиту; механизм и допуск USB разобраны в 20а. Выводы PH0 и PH1 освобождаются; на 23 свободных выводах ещё помещаются OCTOSPI Quad, SPI1, SPI3, все четыре I2C и 10 входов АЦП.

Узел с флеш. Здесь нужен CIU6: FDCAN1 и USB вместе помещаются только в нём — FDCAN1 уходит на PB8/PB9. В CIU6Q у FDCAN1 передатчик есть только на PA12, а это USB D+, и перебор решения не находит. Кварц HSE нужен для CAN. OCTOSPI занимает PA2, PA3, PA6, PA7, PB0, PB1, поэтому из входов АЦП остаются 5.


2д.7 Грабли

Плата под CIU6, а запаян CIU6Q. Маркировки отличаются одной буквой, а выводы 20…25 и 46 — нет. Плата CIU6 подаёт VDD на вывод 24, а у CIU6Q это VSS; на выводе 25 ждут PB12, а там питание. Букву Q сверяют в спецификации и при приёмке.

REGSEL на CIU6. В корпусе без SMPS бит зарезервирован. Код с USE_SMPS = 1 для такого камня — ошибка; держать один проект на оба варианта можно только через этот флаг сборки.

Сбой после выхода из Stop. BOOSTEN сбрасывается во всех режимах Stop, а после выхода диапазон — снова 4. Разгон до 160 МГц повторяют целиком, начиная с диапазона и бустера.

USB и CAN на одних выводах. В CIU6Q FDCAN1_TX есть только на PA12. Выбор между CIU6 и CIU6Q решают до разводки, перебором как в 2д.6.

Комментарий к маске врёт. В stm32u585xx.h у 226 из 7306 определений вида (0x…UL << …_Pos) число в комментарии не равно маске. У PLL1M и PLL1MBOOST там написано 0x000003F0, а на деле 0x00000F00 и 0x0000F000. Верить имени, а не комментарию; в коде выше это проверяет _Static_assert.

USB потерял точность. Если часовой кварц остановился, MSI выходит из режима подстройки и уплывает. На всех U5, кроме U575/585 ревизии X, это событие заведено на линию EXTI; на ревизии X его не поймать прерыванием.

VREFBUF включили. В 48 выводах VREF+ соединён с VDDA, буфер должен оставаться выключенным.


2д.8 Итоги

Дальше: раздел 2е «TrustZone на практике: SAU, GTZC, шлюз вызовов и два проекта на STM32U585» — как размечается U585 с включённым TrustZone и как собрать безопасный и небезопасный проекты.

Открыть в интерактивном справочнике