В предыдущих статьях мы уже немного касались темы требований функциональной безопасности для автомобильной электроники. Очевидно, что отказ автомобильной электронной системы ABS или ECU может привести к тяжёлым последствиям. Для автомобильной электрики/электроники был разработан стандарт ISO26262, который, в частности, содержит требования по отказу и надёжности. По этому стандарту, все устройства делятся на 4 уровня по требованиям, которые приведены в таблице ниже.
Таблица из стандарта IS26262 с detection rate для SPF/LF и FIT
|
|
ASIL-A |
ASIL-B |
ASIL-C |
ASIL-D |
|
Not applicable |
> 90% |
> 97% |
> 99% |
|
|
Not applicable |
> 60% |
> 80% |
> 90% |
|
|
Failure rate |
10-6 / hour |
10-7 / hour |
10-7 / hour |
10-8 / hour |
|
< 1000 |
< 100 |
< 100 |
< 10 |
В этой статье мы будем рассматривать один из основных управляющих элементов для построения подобных систем, а именно, микроконтроллер.
По статистике, ряд электронных устройств для автомобиля строится на микроконтроллерах общего применения, таких как STM32, ESP32 и других. Они подробно документированы, поддерживаются опытными разработчиков, но не слишком подходят для ответственного автомобильного применения.
Также ряд производителей выпускает микроконтроллеры, специально предназначенные для автомобильного сегмента. Микросхемы, которые применяются в автомобилях, должны соответствовать квалификации AEC-Q100 и иметь набор документов, связанных с функциональной безопасностью. В частности Safety Manual, в котором изложены требования к дизайну железу и софту, а также расписаны конкретные Safety Mechanisms.
К сожалению, в связи с текущей геополитической ситуацией, популярные микроконтроллеры, удовлетворяющие требованиям ISO26262, стали практически недоступны. При этом отечественная микроэлектронная промышленность только набирает обороты в производстве безопасных автомобильных микроконтроллеров.

В результате поисков доступных альтернатив мы вышли на китайского производителя Flagchip as Flagship, контроллеры которого обладают достаточно неплохими характеристиками и Safety Mechanisms для реализации автомобильных Raptor (FC4150) и Rex (FC7300), характеристики которых показаны в таблице:
|
|
FC4150x |
FC7300x |
|
Core |
1x Cortex-M4 150MHz |
Up to 6x Cortex-M7 300MHz with Lockstep capabilities |
|
RAM |
Up to 256 KB with SECDED |
Up to 512 KB with SECDED |
|
Flash |
512KB / 2MB with SECDED |
4 / 8 MB with SECDED |
|
Analog |
||
|
ADC |
Up to 2 12bit SAR with up to 32 channel per module |
Up to 2 12bit SAR with up to 32 channel per module |
|
CMP |
Up to 3 comparators with 8bit DAC |
Up to 3 comparators with 8bit DAC |
|
Communication |
||
|
UART |
Up to 6 with LIN |
Up to 18 with LIN |
|
SPI |
Up to 4 with 1/2/4 lane Master/Slave |
up to 8 with 1/2/4 lane with Master/Slave |
|
I2S |
Up to 2 |
— |
|
Network |
1 MII/RMII (Only in 2MB version) |
1 MII/RMII/RGMII |
|
CAN |
Up to 6 with 3 CAN-FD |
Up to 10 with CAN-FD |
|
Safety |
||
|
ASIL Level |
Up to ASIL-B |
Up to ASIL-D |
|
Safety Mechanism |
ECC, 4x CMU, ISM, MAP, AFCB, CRC, WDOG, EIM, ERM, FWM, BIST |
Lockstep, Triple critical registers, ECC, CMU, FCSMU, PMC, AFCB, CRC, WDOG, EIM, ERM, LBIST, MBIST |
|
Operational Conditions |
||
|
Voltage Range, V |
3.0 — 5.5 |
3.0 — 5.5 |
|
Temperature range |
-40 — +125 |
-40 — +125 |
|
Package |
LQFP 64/100/144/176 |
LQFP 144/176, MAPBGA 320 |
Обычно требования к электронному устройству разделяются на программные и аппаратные. Рассмотрим требования к аппаратной части MCU 
Не менее важным для соответствия требованиям ISO26262 является механизм 
На плате установлен микроконтроллер с наибольшим количеством периферийных устройств и встроенным Flash — FC4150F2MBS1P144T1A.
Также на плате присутствует довольно большой набор периферийных устройств:
|
Количество |
Функция |
Компонент |
Комментарий |
|
1 |
CAN |
NXP TJA1042T/3 |
|
|
1 |
CAN |
NXP TJA1043T / Infineon TLE6251 |
С поддержкой Wake / Error detection |
|
2 |
LIN |
NXP TJA1021T/20 |
|
|
1 |
EEPROM |
BL24C64A-PARC |
|
|
2 |
|
Potentiometer |
|
|
3 |
|
Blue Leds |
|
|
2 |
|
RGB Leds |
|
|
4 |
|
User Keys |
|
|
1 |
SPI Flash |
Gigadevice GD25Q32CSIGR |
Разделяют общие пины, выбор производится перепайкой 0 омных резисторов на плате. |
|
1 |
100Base-TX |
Motorcomm YT8512H |
|
|
1 |
100Base-T1 |
Motorcomm YT8010A |
Для подключения отладчика используется стандартный для ARM 20pin JTAG разъём с выведенными на него интерфейсами отладки JTAG и SWD.
Также на плате присутствуют 3 PLD разъёма с большим количеством User GPIO. Даже по маркировке на плате MOTOR1/MOTOR2 понятно, что они предназначены для управления BLDC моторами, что, впрочем, не мешает подключить на них что-то другое.
Также во Flash записана тестовая программа от производителя, которая при запуске пытается поднять линк на Ethernet порту и отправляет сообщения в UART.
Отладочная плата на FC7300
На плате установлен довольно мощный FC7300F8MDT2A320T1A в BGA корпусе.
В этом микроконтроллере установлено 3 ядра: два D-Core LS M7 и один B-Core M7 по терминологии Flagchip. D-Core LS — это как раз безопасные Lockstep ядра. B-Core — обычное M7.
|
Количество |
Функция |
Компонент |
Комментарий |
|
5 |
CAN |
NXP TJA1042T/3 |
|
|
1 |
CAN |
NXP TJA1043T / Infineon TLE6251 |
С поддержкой Wake / Error detection |
|
4 |
LIN |
NXP TJA1021T/20 |
|
|
1 |
EEPROM |
FM24C256EA1SO |
|
|
2 |
|
Потенциометр |
|
|
3 |
|
Blue LED |
|
|
1 |
|
RGB LED |
|
|
4 |
|
Кнопки пользователя |
|
|
1 |
SPI Flash |
Gigadevice GD25Q32ESIGR |
|
|
1 |
1000Base-TX |
Motorcomm YT8531SH / Realtek RTL8211FS-CG |
|
|
1 |
1000Base-T1 |
Semidrive JL3113 |
SGMII YT8531/RTL8211 |
Сборка прошивки для моргания светодиодами
Производитель вместе с SDK распространяет свою среду разработки FC IDE на базе opensource Eclipse:
Сразу хочу заметить, что мы получили в своё распоряжение версию SDK 1.2.1, поэтому всё нижеследующее относится в первую очередь к ней. В SDK встречаются ошибки, связанные с регистром в именовании файлов, что намекает на использование авторами Windows. Впрочем, всё это легко исправляется.
SDK выглядит довольно традиционно — примеры использования различных драйверов и шаблон для сборки проекта. К сожалению, Flagchip не делится библиотеками для работы с HSM, которые поставляются пресобранными в директориях _gcc_libs / _iar_libs соответственно. Также пресобранными поставляется библиотека для работы со встроенной Flash-памятью, которая, впрочем, представляет набор обёрток для функций из ROM, которые описаны в Reference Manual.
Также производитель поставляет
Для сборки нам понадобятся После сборки всех объектных файлов, линкуем их с использованием скрипта линкера Заливаем код в SRAM, записываем в регистры PC и SP значения по смещению +0 и +4 соответственно и продолжаем выполнение. Запускаем openocd и наблюдаем за миганием светодиодов на плате.#inlcude "_driver_header.h" #define SOSC_CLOCK_DFT 32000U #define FOSC_CLOCK_DFT 24000000U #define USED_PCC_NUMBER 3U static void Bsp_SCG_Init(void); static void Bsp_PCC_Init(void); int main(void) { Bsp_CLOCK_Init(); Bsp_Port_Gpio_Init(); while (true) { Bsp_Gpio_Toggle(); delay(1000U); } return 0; } void Bsp_Port_Gpio_Init(void) { PORT_InitType tInitStruct = {0}; /* LED0: PortC 30: MUX = GPIO output */ tInitStruct.u32PortPins = PORT_PIN_30; tInitStruct.uPortPinMux.u32PortPinMode = PORT_GPIO_MODE; tInitStruct.ePortGpioDir = PORT_GPIO_OUT; tInitStruct.ePortGpioLevel = PORT_GPIO_HIGH; PORT_InitPins(PORT_C, &tInitStruct); /* LED1: PortD 4: MUX = GPIO output */ tInitStruct.u32PortPins = PORT_PIN_4; PORT_InitPins(PORT_D, &tInitStruct); /* LED2: PortB 28: MUX = GPIO output */ tInitStruct.u32PortPins = PORT_PIN_28; PORT_InitPins(PORT_B, &tInitStruct); } void Bsp_Gpio_Toggle(void) { GPIO_Toggle(PORT_C, PORT_PIN_30); GPIO_Toggle(PORT_D, PORT_PIN_4); GPIO_Toggle(PORT_B, PORT_PIN_28); } static PCC_ClkCtrlType BSP_PCC_Config[USED_PCC_NUMBER] = { {PCC_CLK_PORTB, true, PCC_CLKGATE_SRC_OFF, PCC_CLK_DIV_BY1}, {PCC_CLK_PORTC, true, PCC_CLKGATE_SRC_OFF, PCC_CLK_DIV_BY1}, {PCC_CLK_PORTD, true, PCC_CLKGATE_SRC_OFF, PCC_CLK_DIV_BY1}, }; static void Bsp_SCG_Init(void) { SCG_FoscType tFoscCfg = {0}; SCG_SoscType tSoscCfg = {0}; SCG_FircType tFircCfg = {0}; SCG_SircType tSircCfg = {0}; SCG_Pll0Type tPll0Cfg = {0}; SCG_ClockCtrlType tClockCtrlCfg; SCG_InitClockSrcStatus(); /* initialize SIRC setting */ tSircCfg.bLock = false; tSircCfg.bLpen = false; tSircCfg.bSten = false; tSircCfg.eDivH = SCG_ASYNCCLOCKDIV_BY1; tSircCfg.eDivM = SCG_ASYNCCLOCKDIV_BY4; SCG_SetSIRC(&tSircCfg); /* initialize SOSC setting */ tSoscCfg.bBypass = false; tSoscCfg.bEnable = true; tSoscCfg.bLock = false; tSoscCfg.u32XtalFreq = SOSC_CLOCK_DFT; SCG_SetSOSC(&tSoscCfg); /* initialize FOSC setting */ tFoscCfg.bBypass = false; tFoscCfg.bEnable = true; tFoscCfg.bLock = false; tFoscCfg.eDivH = SCG_ASYNCCLOCKDIV_BY1; tFoscCfg.eDivM = SCG_ASYNCCLOCKDIV_BY4; tFoscCfg.eDivL = SCG_ASYNCCLOCKDIV_BY8; tFoscCfg.u32XtalFreq = FOSC_CLOCK_DFT; SCG_SetFOSC(&tFoscCfg); /* initialize PLL0 clock frequency setting */ /* input frequency as FOSC, currently on board is 24Mhz pre-divider is 4, multiplier is 50. output clock is 24/4*50/2=150Mhz */ tPll0Cfg.bLock = false; tPll0Cfg.bEnable = true; tPll0Cfg.bCm = true; tPll0Cfg.bCmre = true; tPll0Cfg.bSten = true; tPll0Cfg.eSrc = SCG_PLL0SOURCE_FOSC; tPll0Cfg.eDivH = SCG_ASYNCCLOCKDIV_BY1; tPll0Cfg.eDivM = SCG_ASYNCCLOCKDIV_BY2; tPll0Cfg.ePrediv = SCG_PLL0PREDIV_BY4; tPll0Cfg.eMult = SCG_PLL0MULTIPLY_BY50; SCG_SetPLL0(&tPll0Cfg); tClockCtrlCfg.bSysClkMonitor = true; tClockCtrlCfg.eSrc = SCG_CLOCK_SRC_PLL0; tClockCtrlCfg.eClkOutSrc = SCG_CLOCKOUT_SRC_SIRC; tClockCtrlCfg.eDivCore = SCG_CLOCK_DIV_BY1; tClockCtrlCfg.eDivBus = SCG_CLOCK_DIV_BY4; tClockCtrlCfg.eDivSlow = SCG_CLOCK_DIV_BY8; tClockCtrlCfg.eNvmClkSrc = SCG_NVMCLK_SRC_FIRC; SCG_SetClkCtrl(&tClockCtrlCfg); SCG_SetClkOut(&tClockCtrlCfg); /* initialize FIRC setting */ tFircCfg.eDivH = SCG_ASYNCCLOCKDIV_BY1; tFircCfg.eDivM = SCG_ASYNCCLOCKDIV_BY4; tFircCfg.bEnable = true; tFircCfg.bLock = false; SCG_SetFIRC(&tFircCfg); } static void Bsp_PCC_Init(void) { uint8_t i; PCC_InitClockSrcStatus(); for (i = 0U; i < USED_PCC_NUMBER; i++) { PCC_SetPcc(&BSP_PCC_Config[i]); } } void Bsp_CLOCK_Init(void) { Bsp_SCG_Init(); Bsp_PCC_Init(); }Startup_FC4150.S и скрипт линкера FC4150_2M_ram.ld, которые мы можем позаимствовать из проекта, который генерируется FC_IDE или любого примера. Тут следует обратить внимание, что файл имеет расширение .S и содержит в себе директивы препроцессора, поэтому собирать его надо gcc.Startup_FC4150.S
/****************************************** this startup is only adapt to flagchip FC100 with FC IDE Author: Beatfan ******************************************/ .syntax unified .arch armv7-m /**************************************************************/ /******************** set vector table ***********************/ .section .isr_vector .align 2 .globl __isr_vector /* vector table */ __isr_vector: .long __StackTop /* Top of Stack */ .long Reset_Handler /* Reset Handler */ .long NMI_Handler /* NMI Handler */ .long HardFault_Handler /* Hard Fault Handler */ .long MemManage_Handler /* MPU Fault Handler */ .long BusFault_Handler /* Bus Fault Handler */ .long UsageFault_Handler /* Usage Fault Handler */ .long 0 /* Reserved */ .long 0 /* Reserved */ .long 0 /* Reserved */ .long 0 /* Reserved */ .long SVC_Handler /* SVCall Handler */ .long DebugMon_Handler /* Debug Monitor Handler */ .long 0 /* Reserved */ .long PendSV_Handler /* PendSV Handler */ .long SysTick_Handler /* SysTick Handler */ /* External Interrupts*/ .long DMA0_IRQHandler /* DMA channel 0 transfer complete */ .long DMA1_IRQHandler /* DMA channel 1 transfer complete */ .long DMA2_IRQHandler /* DMA channel 2 transfer complete */ .long DMA3_IRQHandler /* DMA channel 3 transfer complete */ .long DMA4_IRQHandler /* DMA channel 4 transfer complete */ .long DMA5_IRQHandler /* DMA channel 5 transfer complete */ .long DMA6_IRQHandler /* DMA channel 6 transfer complete */ .long DMA7_IRQHandler /* DMA channel 7 transfer complete */ .long DMA8_IRQHandler /* DMA channel 8 transfer complete */ .long DMA9_IRQHandler /* DMA channel 9 transfer complete */ .long DMA10_IRQHandler /* DMA channel 10 transfer complete */ .long DMA11_IRQHandler /* DMA channel 11 transfer complete */ .long DMA12_IRQHandler /* DMA channel 12 transfer complete */ .long DMA13_IRQHandler /* DMA channel 13 transfer complete */ .long DMA14_IRQHandler /* DMA channel 14 transfer complete */ .long DMA15_IRQHandler /* DMA channel 15 transfer complete */ .long DMA_Error_IRQHandler /* DMA error interrupt channels 0-15 */ .long MCM_IRQHandler /* FPU sources */ .long FC_IRQHandler /* FC Command complete */ .long LVD_LVW_IRQHandler /* PMC Low voltage detect interrupt */ .long WDOG0_IRQHandler /* interrupt request out before wdg reset out */ .long WDOG1_IRQHandler /* interrupt request out before wdg reset out */ .long FWM_IRQHandler /* FWM output as interrupt */ .long RCM_IRQHandler /* RCM Asynchronous Interrupt */ .long FCIIC0_IRQHandler /* FCIIC0 Interrupt */ .long FCIIC1_IRQHandler /* FCIIC1 Interrupt */ .long FCSPI0_IRQHandler /* FCSPI0 Interrupt */ .long FCSPI1_IRQHandler /* FCSPI1 Interrupt */ .long FCSPI2_IRQHandler /* FCSPI2 Interrupt */ .long FCUART0_RxTx_IRQHandler /* FCUART0 Transmit / Receive Interrupt */ .long FCUART1_RxTx_IRQHandler /* FCUART1 Transmit / Receive Interrupt */ .long FCUART2_RxTx_IRQHandler /* FCUART2 Transmit / Receive Interrupt */ .long ADC0_IRQHandler /* ADC0 interrupt request. */ .long ADC1_IRQHandler /* ADC1 interrupt request. */ .long CMP0_IRQHandler /* CMP0 interrupt request */ .long CMP1_IRQHandler /* CMP1 interrupt request */ .long CMP2_IRQHandler /* CMP2 interrupt request */ .long ERM_fault_IRQHandler /* ERM single/double bit error correction */ .long INTM_IRQHandler /* INTM alarm interrupt */ .long RTC_IRQHandler /* RTC alarm interrupt */ .long RTC_Seconds_IRQHandler /* RTC seconds interrupt */ .long FCPIT0_IRQHandler /* FCPIT0 interrupt */ .long PTIMER0_IRQHandler /* PTIMER0 interrupt */ .long PTIMER1_IRQHandler /* PTIMER1 interrupt */ .long I2S0_IRQHandler /* I2S0 Interrupt */ .long I2S1_IRQHandler /* I2S1 Interrupt */ .long SCG_IRQHandler /* SCG bus interrupt request */ .long AONTIMER_IRQHandler /* AONTIMER interrupt request */ .long PORTA_IRQHandler /* Port A pin detect interrupt */ .long PORTB_IRQHandler /* Port B pin detect interrupt */ .long PORTC_IRQHandler /* Port C pin detect interrupt */ .long PORTD_IRQHandler /* Port D pin detect interrupt */ .long PORTE_IRQHandler /* Port E pin detect interrupt */ .long SWI_IRQHandler /* Software interrupt */ .long QSPI_IRQHandler /* QSPI All interrupts ORed output */ .long RESERVED_55_IRQHandler /* Reserved */ .long RESERVED_56_IRQHandler /* Reserved */ .long RESERVED_57_IRQHandler /* Reserved */ .long RESERVED_58_IRQHandler /* Reserved */ .long RESERVED_59_IRQHandler /* Reserved */ .long CAN0_IRQHandler /* CAN0 Interrupt */ .long CAN1_IRQHandler /* CAN1 Interrupt */ .long CAN2_IRQHandler /* CAN2 Interrupt */ .long CAN3_IRQHandler /* Reserved */ .long CAN4_IRQHandler /* Reserved */ .long CAN5_IRQHandler /* Reserved */ .long FTU0_IRQHandler /* FTU0 all source interrupt */ .long FTU1_IRQHandler /* FTU1 all source interrupt */ .long FTU2_IRQHandler /* FTU2 all source interrupt */ .long FTU3_IRQHandler /* FTU3 all source interrupt */ .long FTU4_IRQHandler /* FTU4 all source interrupt */ .long FTU5_IRQHandler /* FTU5 all source interrupt */ .long FTU6_IRQHandler /* FTU6 all source interrupt */ .long FTU7_IRQHandler /* FTU7 all source interrupt */ .long HSM0_IRQHandler /* Crypto interrupt */ .long TSTAMP0_IRQHandler /* TimerStamp0 interrupt */ .long RESERVED_75_IRQHandler /* Cordic Accelator interrupt */ .long CMU0_IRQHandler /* CMU0 interrupt */ .long CMU1_IRQHandler /* CMU1 interrupt */ .long CMU2_IRQHandler /* CMU2 interrupt */ .long CMU3_IRQHandler /* CMU3 interrupt */ .long ISM0_IRQHandler .long FCSPI3_IRQHandler /* FCSPI3 Interrupt */ .long FCUART3_RxTx_IRQHandler /* FCUART3 Transmit / Receive Interrupt */ .long FCUART4_RxTx_IRQHandler /* FCUART4 Transmit / Receive Interrupt */ .long FCUART5_RxTx_IRQHandler /* FCUART5 Transmit / Receive Interrupt */ .long TSTAMP1_IRQHandler /* TimerStamp1 interrupt */ .long TMU0_IRQHandler /* Temperature sensor monitor interrupt */ .long ENET_Tx0_IRQHandler /* ENET 1588 Timer Interrupt - synchronous */ .long ENET_Tx1_IRQHandler /* ENET Data transfer done */ .long ENET_Rx0_IRQHandler /* ENET Receive Buffer Done for Ring/Queue 0 */ .long ENET_Rx1_IRQHandler /* ENET Receive Buffer Done for Ring/Queue 0 */ .long ENET_System_IRQHandler /* ENET Payload receive error.*/ .long DefaultISR /* 163 */ .long DefaultISR /* 164 */ .long DefaultISR /* 165 */ .long DefaultISR /* 166 */ .long DefaultISR /* 167 */ .long DefaultISR /* 168 */ .long DefaultISR /* 169 */ .long DefaultISR /* 170 */ .long DefaultISR /* 171 */ .long DefaultISR /* 172 */ .long DefaultISR /* 173 */ .long DefaultISR /* 174 */ .long DefaultISR /* 175 */ .long DefaultISR /* 176 */ .long DefaultISR /* 177 */ .long DefaultISR /* 178 */ .long DefaultISR /* 179 */ .long DefaultISR /* 180 */ .long DefaultISR /* 181 */ .long DefaultISR /* 182 */ .long DefaultISR /* 183 */ .long DefaultISR /* 184 */ .long DefaultISR /* 185 */ .long DefaultISR /* 186 */ .long DefaultISR /* 187 */ .long DefaultISR /* 188 */ .long DefaultISR /* 189 */ .long DefaultISR /* 190 */ .long DefaultISR /* 191 */ .long DefaultISR /* 192 */ .long DefaultISR /* 193 */ .long DefaultISR /* 194 */ .long DefaultISR /* 195 */ .long DefaultISR /* 196 */ .long DefaultISR /* 197 */ .long DefaultISR /* 198 */ .long DefaultISR /* 199 */ .long DefaultISR /* 200 */ .long DefaultISR /* 201 */ .long DefaultISR /* 202 */ .long DefaultISR /* 203 */ .long DefaultISR /* 204 */ .long DefaultISR /* 205 */ .long DefaultISR /* 206 */ .long DefaultISR /* 207 */ .long DefaultISR /* 208 */ .long DefaultISR /* 209 */ .long DefaultISR /* 210 */ .long DefaultISR /* 211 */ .long DefaultISR /* 212 */ .long DefaultISR /* 213 */ .long DefaultISR /* 214 */ .long DefaultISR /* 215 */ .long DefaultISR /* 216 */ .long DefaultISR /* 217 */ .long DefaultISR /* 218 */ .long DefaultISR /* 219 */ .long DefaultISR /* 220 */ .long DefaultISR /* 221 */ .long DefaultISR /* 222 */ .long DefaultISR /* 223 */ .long DefaultISR /* 224 */ .long DefaultISR /* 225 */ .long DefaultISR /* 226 */ .long DefaultISR /* 227 */ .long DefaultISR /* 228 */ .long DefaultISR /* 229 */ .long DefaultISR /* 230 */ .long DefaultISR /* 231 */ .long DefaultISR /* 232 */ .long DefaultISR /* 233 */ .long DefaultISR /* 234 */ .long DefaultISR /* 235 */ .long DefaultISR /* 236 */ .long DefaultISR /* 237 */ .long DefaultISR /* 238 */ .long DefaultISR /* 239 */ .long DefaultISR /* 240 */ .long DefaultISR /* 241 */ .long DefaultISR /* 242 */ .long DefaultISR /* 243 */ .long DefaultISR /* 244 */ .long DefaultISR /* 245 */ .long DefaultISR /* 246 */ .long DefaultISR /* 247 */ .long DefaultISR /* 248 */ .long DefaultISR /* 249 */ .long DefaultISR /* 250 */ .long DefaultISR /* 251 */ .long DefaultISR /* 252 */ .long DefaultISR /* 253 */ .long DefaultISR /* 254 */ .long 0xFFFFFFFF /* Reserved for user TRIM value */ .size __isr_vector, . - __isr_vector /**************************************************************/ /************************ set other ***************************/ .text .thumb /* Reset Handler */ .thumb_func .align 2 .globl Reset_Handler .weak Reset_Handler .type Reset_Handler, %function Reset_Handler: cpsid i /* Mask interrupts */ /* Init the rest of the registers */ ldr r1,=0 ldr r2,=0 ldr r3,=0 ldr r4,=0 ldr r5,=0 ldr r6,=0 ldr r7,=0 mov r8,r7 mov r9,r7 mov r10,r7 mov r11,r7 mov r12,r7 /* lock SEC */ ldr r0,=0x4001400C ldr r1,=0x000000AA str r1,[r0,#0] /* disable all wdog*/ ldr r0,=0x40052000 ldr r1,=0x2920 str r1,[r0,#0] ldr r0,=0x40052008 ldr r1,=0xF000 str r1,[r0,#0] ldr r0,=0x40053000 ldr r1,=0x2920 str r1,[r0,#0] ldr r0,=0x40053008 ldr r1,=0xF000 str r1,[r0,#0] /* clear RTC interrupt */ ldr r0,=0x400650f4; ldr r1,=0x40000000; str r1,[r0,#0] ldr r0,=0x4003d000; ldr r1,=0xFFFFFFFF; str r1,[r0,#0] ldr r0,=0x400650f4; ldr r1,=0x00000000; str r1,[r0,#0] /* Initialize the stack pointer */ ldr r0,=__StackTop mov sp,r0 /* sp=r13 */ /* ########################################################################################### */ /* ##################################### RAM Operation ##################################### */ /* if start from flash, do ram initial */ #ifdef START_FROM_FLASH /***************** Clear All RAM ******************/ /* Clear RAM_U. */ ldr r2, =__RAM_L_START__ ldr r4, =__RAM_L_END__ movs r3, #0 b LoopFillZero_RAM_L .align 2 FillZero_RAM_L: str r3, [r2] adds r2, r2, #4 LoopFillZero_RAM_L: cmp r2, r4 bcc FillZero_RAM_L /* Clear RAM_U. */ ldr r2, =__RAM_U_START__ ldr r4, =__RAM_U_END__ movs r3, #0 b LoopFillZero_RAM_U .align 2 FillZero_RAM_U: str r3, [r2] adds r2, r2, #4 LoopFillZero_RAM_U: cmp r2, r4 bcc FillZero_RAM_U #endif /***************** Clear Stack ******************/ /* Clear Stack. */ ldr r2, =__StackLimit ldr r4, =__StackTop movs r3, #0 b LoopFillZero_STACK .align 2 FillZero_STACK: str r3, [r2] adds r2, r2, #4 LoopFillZero_STACK: cmp r2, r4 bcc FillZero_STACK /*************** copy data initial value from Flash *********************/ /* Loop to copy data from read only memory to RAM. The ranges * of copy from/to are specified by following symbols evaluated in * linker script. * __etext: End of code section, i.e., begin of data sections to copy from. * __data_start__/__data_end__: RAM address range that data should be * copied to. Both must be aligned to 4 bytes boundary. */ ldr r1, =__etext ldr r2, =__data_start__ ldr r3, =__data_end__ .align 2 .flash_to_ram_loop: cmp r2, r3 ittt lt ldrlt r0, [r1], #4 strlt r0, [r2], #4 blt .flash_to_ram_loop /*************** copy data initial value from Flash *********************/ /* initial bss data to RAM. The ranges * are specified by following symbols evaluated in * linker script. * __bss_start__/__bss_end__: RAM address range that data should be * copied to. Both must be aligned to 4 bytes boundary. */ ldr r2, =__bss_start__ ldr r3, =__bss_end__ .align 2 .bss_ram_loop: cmp r2, r3 ittt lt ldrlt r0, =0 strlt r0, [r2], #4 blt .bss_ram_loop ldr r1, =__interrupts_start__ ldr r2, =__interrupts_ram_start__ ldr r3, =__interrupts_ram_end__ .align 2 .vector_copy: cmp r2, r3 ittt lt ldrlt r0, [r1], #4 strlt r0, [r2], #4 blt .vector_copy /* ##################################### RAM Operation ##################################### */ /* ########################################################################################### */ /* initial interrupt table to RAM */ ldr r0,=IntMgr_Init blx r0 cpsie i /* Unmask interrupts */ bl main JumpToSelf: b JumpToSelf .pool .size Reset_Handler, . - Reset_Handler .align 1 .thumb_func .weak DefaultISR .type DefaultISR, %function DefaultISR: b DefaultISR .size DefaultISR, . - DefaultISR /* Macro to define default handlers. Default handler * will be weak symbol and just dead loops. They can be * overwritten by other handlers */ .macro def_irq_handler handler_name .weak \handler_name .set \handler_name, DefaultISR .endm /* Exception Handlers */ def_irq_handler NMI_Handler def_irq_handler HardFault_Handler def_irq_handler MemManage_Handler def_irq_handler BusFault_Handler def_irq_handler UsageFault_Handler def_irq_handler SVC_Handler def_irq_handler DebugMon_Handler def_irq_handler PendSV_Handler def_irq_handler SysTick_Handler def_irq_handler DMA0_IRQHandler def_irq_handler DMA1_IRQHandler def_irq_handler DMA2_IRQHandler def_irq_handler DMA3_IRQHandler def_irq_handler DMA4_IRQHandler def_irq_handler DMA5_IRQHandler def_irq_handler DMA6_IRQHandler def_irq_handler DMA7_IRQHandler def_irq_handler DMA8_IRQHandler def_irq_handler DMA9_IRQHandler def_irq_handler DMA10_IRQHandler def_irq_handler DMA11_IRQHandler def_irq_handler DMA12_IRQHandler def_irq_handler DMA13_IRQHandler def_irq_handler DMA14_IRQHandler def_irq_handler DMA15_IRQHandler def_irq_handler DMA_Error_IRQHandler def_irq_handler MCM_IRQHandler def_irq_handler FC_IRQHandler def_irq_handler LVD_LVW_IRQHandler def_irq_handler WDOG0_IRQHandler def_irq_handler WDOG1_IRQHandler def_irq_handler FWM_IRQHandler def_irq_handler RCM_IRQHandler def_irq_handler FCIIC0_IRQHandler def_irq_handler FCIIC1_IRQHandler def_irq_handler FCSPI0_IRQHandler def_irq_handler FCSPI1_IRQHandler def_irq_handler FCSPI2_IRQHandler def_irq_handler FCUART0_RxTx_IRQHandler def_irq_handler FCUART1_RxTx_IRQHandler def_irq_handler FCUART2_RxTx_IRQHandler def_irq_handler ADC0_IRQHandler def_irq_handler ADC1_IRQHandler def_irq_handler CMP0_IRQHandler def_irq_handler CMP1_IRQHandler def_irq_handler CMP2_IRQHandler def_irq_handler ERM_fault_IRQHandler def_irq_handler INTM_IRQHandler def_irq_handler RTC_IRQHandler def_irq_handler RTC_Seconds_IRQHandler def_irq_handler FCPIT0_IRQHandler def_irq_handler PTIMER0_IRQHandler def_irq_handler PTIMER1_IRQHandler def_irq_handler I2S0_IRQHandler def_irq_handler I2S1_IRQHandler def_irq_handler SCG_IRQHandler def_irq_handler AONTIMER_IRQHandler def_irq_handler PORTA_IRQHandler def_irq_handler PORTB_IRQHandler def_irq_handler PORTC_IRQHandler def_irq_handler PORTD_IRQHandler def_irq_handler PORTE_IRQHandler def_irq_handler SWI_IRQHandler def_irq_handler QSPI_IRQHandler def_irq_handler RESERVED_55_IRQHandler def_irq_handler RESERVED_56_IRQHandler def_irq_handler RESERVED_57_IRQHandler def_irq_handler RESERVED_58_IRQHandler def_irq_handler RESERVED_59_IRQHandler def_irq_handler CAN0_IRQHandler def_irq_handler CAN1_IRQHandler def_irq_handler CAN2_IRQHandler def_irq_handler CAN3_IRQHandler def_irq_handler CAN4_IRQHandler def_irq_handler CAN5_IRQHandler def_irq_handler FTU0_IRQHandler def_irq_handler FTU1_IRQHandler def_irq_handler FTU2_IRQHandler def_irq_handler FTU3_IRQHandler def_irq_handler FTU4_IRQHandler def_irq_handler FTU5_IRQHandler def_irq_handler FTU6_IRQHandler def_irq_handler FTU7_IRQHandler def_irq_handler HSM0_IRQHandler def_irq_handler TSTAMP0_IRQHandler def_irq_handler RESERVED_75_IRQHandler def_irq_handler CMU0_IRQHandler def_irq_handler CMU1_IRQHandler def_irq_handler CMU2_IRQHandler def_irq_handler CMU3_IRQHandler def_irq_handler ISM0_IRQHandler def_irq_handler FCSPI3_IRQHandler def_irq_handler FCUART3_RxTx_IRQHandler def_irq_handler FCUART4_RxTx_IRQHandler def_irq_handler FCUART5_RxTx_IRQHandler def_irq_handler TSTAMP1_IRQHandler def_irq_handler TMU0_IRQHandler def_irq_handler ENET_Tx0_IRQHandler def_irq_handler ENET_Tx1_IRQHandler def_irq_handler ENET_Rx0_IRQHandler def_irq_handler ENET_Rx1_IRQHandler def_irq_handler ENET_System_IRQHandler .endFC4150_2M_ram.ld
/* Linker script to place sections and symbol values. Should be used together * with other linker script that defines memory regions FLASH and RAM. * It references following symbols, which must be defined in code: * Reset_Handler : Entry of reset handler * * It defines following symbols, which code can use without definition: * __exidx_start * __exidx_end * __etext * __data_start__ * __preinit_array_start * __preinit_array_end * __init_array_start * __init_array_end * __fini_array_start * __fini_array_end * __data_end__ * __bss_start__ * __bss_end__ * __end__ * end * __HeapLimit * __StackLimit * __StackTop * __stack */ /* Entry Point */ ENTRY(Reset_Handler) __RAM_VECTOR_TABLE_SIZE = 0x0400; HEAP_SIZE = 0x400; STACK_SIZE = 0x400; /* Specify the memory areas */ MEMORY { /* Flash */ FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 2M /* SRAM_L */ RAM_L (RW) : ORIGIN = 0x02000000, LENGTH = 64K /* SRAM_U */ RAM_U (RW) : ORIGIN = 0x20000000, LENGTH = 192K } /* Define output sections */ SECTIONS { /* The program code and other data goes into internal flash */ .text : { . = ALIGN(1024); /* VTOR must be align to 1K */ __VECTOR_TABLE = .; __interrupts_start__ = .; . = ALIGN(4); KEEP(*(.isr_vector)) __interrupts_end__ = .; . = ALIGN(4); *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ *(.init) /* section used in crti.o files */ *(.fini) /* section used in crti.o files */ *(.eh_frame) /* section used in crtbegin.o files */ . = ALIGN(4); } > RAM_U .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } > FLASH __exidx_start = .; .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } > FLASH __exidx_end = .; __etext = .; .interrupts_ram : { . = ALIGN(1024); /* VTOR must be align to 1K */ __VECTOR_RAM = .; __RAM_START = .; __interrupts_ram_start__ = .; /* Create a global symbol at data start. */ *(.m_interrupts_ram) /* This is a user defined section. */ . += __RAM_VECTOR_TABLE_SIZE; . = ALIGN(4); __interrupts_ram_end__ = .; /* Define a global symbol at data end. */ } > RAM_L .data : AT (__etext) { __data_start__ = .; *(.data*) . = ALIGN(4); /* preinit data */ PROVIDE_HIDDEN (__preinit_array_start = .); KEEP(*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); . = ALIGN(4); /* init data */ PROVIDE_HIDDEN (__init_array_start = .); KEEP(*(SORT(.init_array.*))) KEEP(*(.init_array)) PROVIDE_HIDDEN (__init_array_end = .); . = ALIGN(4); /* finit data */ PROVIDE_HIDDEN (__fini_array_start = .); KEEP(*(SORT(.fini_array.*))) KEEP(*(.fini_array)) PROVIDE_HIDDEN (__fini_array_end = .); . = ALIGN(4); /* All data end */ __data_end__ = .; } > RAM_U .bss : { __bss_start__ = .; *(.bss*) *(COMMON) __bss_end__ = .; } > RAM_U .heap : { . = ALIGN(8); __HeapBegin = .; _end = .; end = _end; . += HEAP_SIZE; . = ALIGN(8); __HeapLimit = .; } > RAM_L .stack_dummy : { . = ALIGN(8); __StackLimit = .; . += STACK_SIZE; . = ALIGN(8); __StackTop = .; } > RAM_L __RAM_L_START__ = ORIGIN(RAM_L); __RAM_L_END__ = ORIGIN(RAM_L)+LENGTH(RAM_L)-1; __RAM_U_START__ = ORIGIN(RAM_U); __RAM_U_END__ = ORIGIN(RAM_U)+LENGTH(RAM_U)-1; .ARM.attributes 0 : { *(.ARM.attributes) } ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with STACK") } FC4150_2M_ram.ld, в котором код секции text / rodata / init располагается в SRAM с адреса 0x20000000.openocd -f /usr/share/openocd/scripts/interface/jlink.cfg -f ./openocd/fc4150.cfg -c "init" -c "reset halt" -c "load_image out/main.elf" -c "reg pc [mdw 0x20000004]" -c "reg sp [mdw 0x20000000]" -c "resume"
Заключение
Flagchip производит безопасные микроконтроллеры, которые доступны в РФ и подходят для применения в автомобильной промышленности. Это особенно актуально в текущей ситуации, когда многие компании прекратили поставки собственных микроконтроллеров на наш рынок.
С помощью отладочных плат на базе безопасных микроконтроллеров Flagchip можно достаточно хорошо изучить и опробовать возможности данных чипов и убедиться в возможности сборки на них собственных приложений.
Применение данных микроконтроллеров может существенно повысить надежность и безопасность устройств автомобильной электроники с учетом их соответствия требованиям ISO-26262.
ссылка на оригинал статьи https://habr.com/ru/articles/771894/
Добавить комментарий