Попробовал STM32G4 Nucleo-64 boards (MB1367). Скорее игрушка, чтобы посмотреть примеры. Писал, писал и просто кончилась память. Однако, наиграться вдоволь точно есть чем!
Для более-менее серьезного проекта я бы рекомендовал G473CEU.
G473CEU- влюбиться, да запросто. Во всяком случае напрочь отшибает желание взять в руки какой-нибудь STM32F0 или F1.
Сразу хочу сказать, что все сказанное в статье: «CCM (core coupled memory) data RAM. Документация на русском языке» — работает из коробки.
Хотя IAR Embedded Workbench for ARM 9.10.1 с этой серией преподносит некоторые «уроки» оптимизации.
Я особо не раскачивал ситуацию, но при размещении кода функции в CCMSRAM
с оптимизацией по памяти конструкция
for (uint8_t i = 0; i < 2; i++ )
{
for (uint8_t j = i + 1; j < 2; j++)
{
asm("nop");
}
}
внутренний цикл отрабатывает дважды.
IAR почему-то ставит оптимизацию по памяти по умолчанию для STM32G4. Это, наверное из расчета на G431CBU.
Можно, конечно, все заделать volatile, но тогда зачем ставить оптимизацию?
При стандартном объявлении модификация переменных внутреннего цикла происходит
после выхода во внешний.
Однако, если объявить переменные вне функции, а еще лучше использовать глобальные,
то все работает корректно.
Чудит и CubeMX.
При переходе от одного проекта к другому в CubeMX Version 6.9.1
дернуло включить Clock Source Internal Clock в режиме PWM четвертый таймер.
В предыдущем проекте было Clock Source Disable и все работало.
Получилась «такая трава»! Функции инициализации таймеров привожу в архиве.
Возможно решили проблему в новой библиотеке STM32Cube_FW_G4_V1.5.2. Не проверял.
В силу объективных причин пришлось перейти на версию IAR Embedded Workbench for ARM 9.50.1
SPI DMA problems in MCU STM32G4 IAR 9.50
Напрочь умерла красивая ардуиновская функция инициализации дисплея ST7735_Init.
Это которая static void ST7735_ExecuteCommandList(const uint8_t *addr).
Дисплейчик по-просту перестал включаться. Причем, если снять флаг оптимизации
Type-based alias analysis
то все опять заработало. Однако тогда зачем IAR?
Посмотрел IAR Runtime Environment and Library
User Guide pg. 54 Reference information
Там все чего-то мутновато описано, но про указатели. В нашей библиотеке команды передаются как константы, а данные, как указатель на массив.
В библиотеке STM32Cube\Repository\STM32Cube_FW_G4_V1.5.2\Drivers\BSP\Components\st7735
есть та еще функция инициализации этого дисплея.
Однако она написано совершенно прямолинейно. Глядя на это, я объявил структуру
typedef struct Init_CMD
{
// структура данных для передачи при инициализации
uint8_t Cm_SWRESET[1];
uint8_t Cm_SLPOUT[1];
uint8_t Cm_FRMCTR1[1];
uint8_t Dt_FRMCTR1[3];
uint8_t Cm_FRMCTR2[1];
uint8_t Dt_FRMCTR2[3];
и т.д., где и команды и данные представляют из себя элементы массивов, а функции передачи команд и данных сделал однотипными.
union {
uint32_t p_dma;
uint8_t* p_dat;
} send_union;
static void ST7735_Send_CMD(uint8_t* dat){ //отправка команды
// uint8_t* p_dat;
while (DMA2_Ch_5_Cf);
DMA2_Ch_5_Cf = 1;
// p_dat = &dat;
send_union.p_dat = dat;
// HAL_SPI_Transmit_DMA(&hspi1, p_dat, 1);
LL_DMA_DisableChannel(DMA2, LL_DMA_CHANNEL_5);
LL_DMA_ClearFlag_TC5(DMA2);
LL_DMA_ClearFlag_TE5(DMA2);
LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_CHANNEL_5, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA2, LL_DMA_CHANNEL_5, LL_DMA_PDATAALIGN_BYTE);
LL_DMA_SetMemorySize(DMA2, LL_DMA_CHANNEL_5, LL_DMA_MDATAALIGN_BYTE);
LL_DMA_SetDataLength(DMA2, LL_DMA_CHANNEL_5, 1);
LL_DMA_ConfigAddresses(DMA2, LL_DMA_CHANNEL_5, send_union.p_dma, LL_SPI_DMA_GetRegAddr(SPI1), LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_EnableIT_TC(DMA2, LL_DMA_CHANNEL_5);
LL_DMA_EnableIT_TE(DMA2, LL_DMA_CHANNEL_5);
LL_DMA_DisableIT_HT(DMA2, LL_DMA_CHANNEL_5);
LL_DMA_SetPeriphRequest(DMA2, LL_DMA_CHANNEL_5, LL_DMAMUX_REQ_SPI1_TX);
LL_SPI_EnableDMAReq_TX(SPI1);
ST7735_a0_L(); // В случае данных ST7735_a0_H();
ST7735_cs_L();
LL_DMA_EnableChannel(DMA2, LL_DMA_CHANNEL_5);
}
Функция инициализации приняла вид
void ST7735_Init_9_50(void) {
Cmd_Table_Init(&CMD_Tab);
LL_DMA_DisableIT_HT(DMA2, LL_DMA_CHANNEL_5);
ST7735_rst_L();
delay_ms(10);
ST7735_rst_H();
delay_ms(10);
DMA2_Ch_5_Cf = 0;
LL_SPI_Enable(SPI1);
ST7735_Send_CMD(CMD_Tab.Cm_SWRESET);
delay_ms(150);
ST7735_Send_CMD(CMD_Tab.Cm_SLPOUT);
// delay_ms(500);
ST7735_Send_CMD(CMD_Tab.Cm_FRMCTR1);
ST7735_Send_DAT(CMD_Tab.Dt_FRMCTR1, 3);
и т.д.
Ну и, как обычно, все зачирикало без снятия флагов оптимизации. Буду рад, если кому-то это поможет избежать танцев с бубнами. )))
Из «вкусного» на бытовом уровне, например, вывод картинок через DMA с W25Q прям на ST7735 в режиме «из периферии в периферию» мимо процессора с частотой SPI 60 МГц.
LL_DMA_ConfigAddresses (DMA1, LL_DMA_CHANNEL_6, LL_SPI_DMA_GetRegAddr(SPI1), LL_SPI_DMA_GetRegAddr(SPI2), LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
Документацию выкладываю «в части касающейся», в рамках того, что пришлось разобрать самому.
(RM0440)_Analog_to_digital_converters_(ADC)_RU
(RM0440)_STM32_Digital-to-analog_converter_(DAC)_RU
(RM0440)_STM32_General_purpose_timers_(TIM2_TIM3_TIM4_TIM5)_RU
(RM0440)_System_and_memory_overview _RU
(RM0440)_Voltage_reference_buffer_(VREFBUF)_RU
С уважением Петр.
Реализуем коммерческие проекты.
Возможна работа по договору подряда.
t654rk@mail.ru