110 lines
6.2 KiB
C
110 lines
6.2 KiB
C
/**
|
||
* Аппаратный порт STM32G474RB: векторы приложения, тактирование и GPIO.
|
||
* Алгоритмы UMP/TMS/IGBT находятся в общем C-ядре templates; здесь только пины.
|
||
*/
|
||
#include "board.h"
|
||
#include "board_config.h"
|
||
#include "transport.h"
|
||
#include "emulator.h"
|
||
#include "igbt_emulator.h"
|
||
#include "stm32g4xx_hal.h"
|
||
volatile uint32_t clock_fault;
|
||
uint32_t SystemCoreClock=16000000u;
|
||
const uint8_t AHBPrescTable[16]={0,0,0,0,0,0,0,0,1,2,3,4,6,7,8,9};
|
||
const uint8_t APBPrescTable[8]={0,0,0,0,1,2,3,4};
|
||
static uint8_t usb_clock_ready;
|
||
/* Восемь входов IGBT: PB0,PB1,PB2,PB10..PB14. PB3/SWO и PB8/PB9 CAN свободны. */
|
||
static const uint16_t input_pins[8]={GPIO_PIN_0,GPIO_PIN_1,GPIO_PIN_2,
|
||
GPIO_PIN_10,GPIO_PIN_11,GPIO_PIN_12,GPIO_PIN_13,GPIO_PIN_14};
|
||
/* До C runtime разрешены только регистровые операции; глобальные данные ещё не готовы. */
|
||
void SystemInit(void) { SCB->CPACR|=0xFu<<20; SCB->VTOR=0x08010000u; }
|
||
void SystemCoreClockUpdate(void) {
|
||
RCC_ClkInitTypeDef config; uint32_t latency;
|
||
HAL_RCC_GetClockConfig(&config,&latency);
|
||
SystemCoreClock=HAL_RCC_GetSysClockFreq() >> AHBPrescTable[config.AHBCLKDivider >> RCC_CFGR_HPRE_Pos];
|
||
}
|
||
/* ISR только считает миллисекунды: протоколы и модели обслуживаются главным циклом. */
|
||
void SysTick_Handler(void) { HAL_IncTick(); }
|
||
void board_fatal(uint32_t code) { clock_fault=code; for (;;) {} }
|
||
static void peripheral_clock(void)
|
||
{
|
||
RCC_OscInitTypeDef osc={0}; RCC_ClkInitTypeDef clk={0};
|
||
RCC_PeriphCLKInitTypeDef peripheral={0}; RCC_CRSInitTypeDef crs={0};
|
||
__HAL_RCC_PWR_CLK_ENABLE();
|
||
/* Для 160 МГц нужен Range1 Boost; Flash 4 wait states по таблице ST. */
|
||
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST)!=HAL_OK) board_fatal(3);
|
||
osc.OscillatorType=RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSI48;
|
||
osc.HSIState=RCC_HSI_ON; osc.HSICalibrationValue=RCC_HSICALIBRATION_DEFAULT;
|
||
osc.HSI48State=RCC_HSI48_ON;
|
||
osc.PLL.PLLState=RCC_PLL_ON; osc.PLL.PLLSource=RCC_PLLSOURCE_HSI;
|
||
/* HSI16 / 4 * 80 / 2 = 160 МГц; PLLQ также 160 МГц, FDCAN берёт PCLK1. */
|
||
osc.PLL.PLLM=RCC_PLLM_DIV4;
|
||
#if EMU_USE_HSE
|
||
#if EMU_HSE_HZ != 24000000u
|
||
#error This board profile supports 24 MHz HSE or internal HSI16
|
||
#endif
|
||
osc.OscillatorType|=RCC_OSCILLATORTYPE_HSE;
|
||
osc.HSEState=EMU_HSE_BYPASS ? RCC_HSE_BYPASS : RCC_HSE_ON;
|
||
osc.PLL.PLLSource=RCC_PLLSOURCE_HSE; osc.PLL.PLLM=RCC_PLLM_DIV6;
|
||
#endif
|
||
osc.PLL.PLLN=80; osc.PLL.PLLP=RCC_PLLP_DIV2;
|
||
osc.PLL.PLLQ=RCC_PLLQ_DIV2; osc.PLL.PLLR=RCC_PLLR_DIV2;
|
||
if (HAL_RCC_OscConfig(&osc)!=HAL_OK) board_fatal(3);
|
||
clk.ClockType=RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
|
||
clk.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK; clk.AHBCLKDivider=RCC_SYSCLK_DIV1;
|
||
clk.APB1CLKDivider=RCC_HCLK_DIV2; clk.APB2CLKDivider=RCC_HCLK_DIV1;
|
||
if (HAL_RCC_ClockConfig(&clk,FLASH_LATENCY_4)!=HAL_OK) board_fatal(3);
|
||
/* USB не зависит от PLL/HSE. USART2 и FDCAN получают 80 МГц PCLK1. */
|
||
peripheral.PeriphClockSelection=RCC_PERIPHCLK_USB|RCC_PERIPHCLK_FDCAN|RCC_PERIPHCLK_USART2;
|
||
peripheral.UsbClockSelection=RCC_USBCLKSOURCE_HSI48;
|
||
peripheral.FdcanClockSelection=RCC_FDCANCLKSOURCE_PCLK1;
|
||
peripheral.Usart2ClockSelection=RCC_USART2CLKSOURCE_PCLK1;
|
||
if (HAL_RCCEx_PeriphCLKConfig(&peripheral)!=HAL_OK) board_fatal(3);
|
||
__HAL_RCC_CRS_CLK_ENABLE();
|
||
crs.Prescaler=RCC_CRS_SYNC_DIV1; crs.Source=RCC_CRS_SYNC_SOURCE_USB;
|
||
crs.Polarity=RCC_CRS_SYNC_POLARITY_RISING;
|
||
crs.ReloadValue=__HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000u,1000u);
|
||
crs.ErrorLimitValue=RCC_CRS_ERRORLIMIT_DEFAULT;
|
||
crs.HSI48CalibrationValue=RCC_CRS_HSI48CALIBRATION_DEFAULT;
|
||
HAL_RCCEx_CRSConfig(&crs); usb_clock_ready=1;
|
||
}
|
||
void board_init(void)
|
||
{
|
||
GPIO_InitTypeDef gpio={0};
|
||
/* Этот образ связан с RB-загрузчиком: 128 КБ Flash, непрерывная карта DBANK=0. */
|
||
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||
if (*(const uint16_t *)FLASHSIZE_BASE!=128u ||
|
||
(FLASH->OPTR&(FLASH_OPTR_DBANK|FLASH_OPTR_BFB2)) ||
|
||
(SYSCFG->MEMRMP&SYSCFG_MEMRMP_FB_MODE)) board_fatal(5);
|
||
peripheral_clock();
|
||
__HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE();
|
||
__HAL_RCC_USART2_CLK_ENABLE(); __HAL_RCC_FDCAN_CLK_ENABLE();
|
||
/* ST-LINK VCP физически подключён к PA2/PA3; выбираем USART2 AF7, формат 8N1. */
|
||
gpio.Pin=GPIO_PIN_2|GPIO_PIN_3; gpio.Mode=GPIO_MODE_AF_PP;
|
||
gpio.Speed=GPIO_SPEED_FREQ_VERY_HIGH; gpio.Pull=GPIO_PULLUP;
|
||
gpio.Alternate=GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA,&gpio);
|
||
gpio.Pin=GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14;
|
||
gpio.Mode=GPIO_MODE_INPUT; gpio.Pull=GPIO_PULLDOWN; HAL_GPIO_Init(GPIOB,&gpio);
|
||
/* PC0..PC7 — восемь ответов IGBT. Устанавливаем нули до включения выходов. */
|
||
gpio.Pin=0xff; gpio.Mode=GPIO_MODE_OUTPUT_PP; gpio.Pull=GPIO_NOPULL;
|
||
HAL_GPIO_WritePin(GPIOC,0xff,GPIO_PIN_RESET); HAL_GPIO_Init(GPIOC,&gpio);
|
||
#if EMU_RS485_DE
|
||
gpio.Pin=GPIO_PIN_15; HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_RESET);
|
||
HAL_GPIO_Init(GPIOB,&gpio);
|
||
#endif
|
||
/* FDCAN1 Classic CAN: PB8 RX, PB9 TX. PA11/PA12 остаются для USB FS. */
|
||
gpio.Pin=GPIO_PIN_8|GPIO_PIN_9; gpio.Mode=GPIO_MODE_AF_PP;
|
||
gpio.Pull=GPIO_PULLUP; gpio.Alternate=GPIO_AF9_FDCAN1; HAL_GPIO_Init(GPIOB,&gpio);
|
||
transport_init();
|
||
}
|
||
uint8_t board_usb_ready(void) { return usb_clock_ready; }
|
||
/* Один шаг 1 мс. Бит n соответствует элементу input_pins[n], выход — PCn. */
|
||
void board_tick(void)
|
||
{
|
||
uint8_t inputs=0,outputs; unsigned i;
|
||
for(i=0;i<8;++i) if(HAL_GPIO_ReadPin(GPIOB,input_pins[i])==GPIO_PIN_SET) inputs|=(uint8_t)(1u<<i);
|
||
igbt_emu_set_tx(inputs); emu_tick(); outputs=igbt_emu_get_rx();
|
||
HAL_GPIO_WritePin(GPIOC,(uint16_t)(~outputs&0xffu),GPIO_PIN_RESET);
|
||
HAL_GPIO_WritePin(GPIOC,outputs,GPIO_PIN_SET);
|
||
}
|