stm32h743替代芯片(STM32H723、STM32H743、STM32H750的区别)
1、stm32h743替代芯片
STM32H743/753系列产品集成了工作频率高达480 MHz的Arm® Cortex®-M7内核(具有双精度浮点单元)。
性能
在480 MHz的CPU频率下,从Flash执行程序时,STM32H742系列能够提供2424 CoreMark /1027 DMIPS的性能,利用其L1缓存实现了0等待执行
L1缓存(16 KB的I-缓存 +16 KB的D-缓存)提高外部存储器的执行性能
安全性
STM32H753 MCU包含以下额外安全特性:
加密/哈希硬件加速
STM32H755还支持安全固件安装(SFI)嵌入式安全服务,可在执行初始程序时执行安全验证并保护软件IP
安全启动和安全固件升级(SBSFU)
高能效
多电源域架构可实现将不同的电源域配置为低功耗模式,进而优化功耗效率。
USB调节器提供嵌入式物理接口层(PHY)。
在内核运行模式(关闭外设)下,功耗典型值为275 µA/MHz @VDD = 3.3 V和25 °C
低功耗待机模式下的典型功耗电流为2.43 µA
带RTC的VBAT模式(低功耗模式)下通常为460 nA
图形
LCD-TFT控制器接口支持双层图形
Chrom-ART Accelerator™提高了图形内容创建速度,并为其它应用节省了MCU内核处理带宽
JPEG硬件加速器,可进行快速JPEG编码和解码,从而减轻CPU编解码负荷
片内外设
多达35个通信接口包括FD-CAN、USB 2.0高速/全速、以太网MAC、摄像头接口
可利用带有32位并行接口或双模Quad-SPI串行闪存接口的灵活存储控制器轻松扩展存储器容量
模拟外设:12位DAC,快速16位ADC
16位高精度定时器上的多个16位和32位定时器运行频率高达480 MHz
STM32H743/753 MCU系列提供1到2 MB的Flash存储器,具有以下结构的1 MB SRAM:192 KB的TCM RAM(包括64 KB的ITCM RAM和128 KB的DTCM RAM,用于时间关键型程序和数据),512 KB、288 KB和64 KB的用户SRAM,以及用于在最低功耗模式下保存数据的备份域4 KB SRAM。另外,它提供100至240引脚的BGA和LQFP封装型号。
在智能家居与汽车电子所需芯片中,MCU芯片的占比是最高的,随着智能家居与智能汽车的发展,MCU芯片的需求量被进一步加大,这就要求MCU芯片无论是在技术研发还是在生产数量上都要满足市场的需求,不过,由于MCU市场的供需失衡,自2021年起,ST的部分高端MCU产品开始涨价,许多下游终端厂商为此焦头烂额。
以意法半导体为例,渠道经销商价格飞涨,通过查询IC交易网创新指数得知,其高端芯片型STM32H743XIH6近日涨幅严重,由1017元上涨到2599元,幅度高达155.56%,并且在价格上涨的同时还陷入了缺货状态,交期长达3周。
其另一款芯片STM32H743IIT6价格同样有所上涨,从333.35元上涨到772元,再回落到509元,涨幅高达52.69%。
我们都知道,芯片缺货的后果有多严重。此前全球陷入MCU缺货、涨价危机,导致了部分车企和工业电子企业出现停产的情况,且各大厂商均出现交期严重延长的情况,部分甚至达到了40周以上。
但危机同样代表着机遇。
芯片涨价且交期过长导致国内企业开始面临成本飙升、被迫减产,停产的窘境,为摆脱这一情况,许多国内企业开始尝试用国产芯片替代原来芯片。这就为国内芯片公司迎来了绝佳的发展窗口期。
目前国内已经出现具备较好技术积累和广泛产品布局或具有特殊定位优势的MCU厂商。国产化进程不可逆转,大陆领先MCU厂商有望迎来快速增长期。
此外,如今的下游终端厂商已逐步开始替换,中国本土MCU厂商迎来了机遇期。以先楫半导体为例,其基于RISC-V内核开发的HPM系列国产MCU,与国际厂商产品相比,CPU主频更高,内存更多,易用性更高,成本也更低,外设也较为丰富,集成度更高,更适应本土化应用需求,HPM6700/6400、HPM6300、HPM6200等都可较好与国际大厂兼容,部分实现国产化替代。
接下来就由我爱方案网为大家分享先楫半导体的几款高性能RISC-V MCU芯片。
HPM6700/6400系列芯片
HPM6700/6400 系列产品是先楫半导体推出的高性能高实时 RISC-V MCU 旗舰产品,目前已经量产。与国际竞品相比,HPM6700系列芯片单核运行主频即可达到惊人的816MHz,在CoreMark跑分测试中,HPM6700获得了9220的高分,成功刷新了国际MCU领域的性能记录。
在具体性能方面,HPM6700/6400系列芯片采用RISC-V 内核,支持双精度浮点运算及强大的 DSP 扩展,主频频率创下了MCU 性能新纪录,是目前市场上高性能MCU的理想之选。此外,该系列芯片还配置了高效 L1 缓存和本地存储器,加上 2MB 内置通用SRAM,极大避免了低速外部存储器引发的性能损失。
HPM6700/6400系列芯片还拥有强大的多媒体支持能力和丰富外设接口,其适配的LCD显示控制器可支持高达1366x768 60fps的八图层RGB显示支持,支持图形加速功能,可支持双千兆以太网,IEEE1588,双目摄像头。并具有4个独立的pwm模块,每个模块可生成8通道互补PWM,及16通道普通PWM、3 个 12 位高速 ADC 5MSPS、1 个 16 位高精度 ADC 2MSPS、4 个模拟比较器等多个接口。
在安全性方面,HPM6700/6400系列芯片集成了 AES-128/256, SHA-1/256 加速引擎,支持固件软件签名认证、加密启动和加密执行。
HPM6300系列
先楫半导体推出的HPM6300全系列产品采用晶心Andes D45 RISC-V内核,支持双精度浮点运算。模拟模块包括16bit-ADC,12-bit DAC和模拟比较器,配以多组纳秒级高分辨率PWM,为马达控制和数字电源应用提供强大硬件支持;通讯接口包括了实时以太网,支持IEEE1588,内置PHY的高速USB,多路CAN-FD及丰富的UART,SPI,I2C等接口。(已量产)
HPM6300的主频达到648MHz, 并具有FFA协处理器,能实现FFT/FIR快速计算,具备3个16位的ADC、10/100M以太网等,适合工业自动化、电网等行业应用,如工业自动化领域的伺服驱动器、PLC、工业控制器,电网的DTU、断路器等产品。
不仅在性能方面表现优异,HPM6300同时也是一款高性价比的产品,其高实时性、互联性、16位ADC的特性,一经推出就获得了自动化、电网、新能源客户的认可。目前已在行业头部客户中导入产品设计,在FFT、AI推理性能上超越了传统的DSP。
在工业领域,电机驱动是整个自动化的基础应用,如用于CNC机床、机器人的伺服驱动器,用于新能源汽车的主驱、压缩机驱动等。由于这些行业本身的发展和需求增加,对MCU提出了更高的要求,如高算力、高实时性、16位ADC、单芯片多轴控制等。
另外,HPM6300系列在功耗上进行了深度优化,对于电源管理域进行了更加精细的划分,实现了低至1.5uA的待机功耗,及低至40mA的运行功耗(全速运行coremark,外设时钟关闭),皆低于市场上同类国际品牌的功耗。
HPM6200系列
HPM6200是先楫半导体推出的高性能、高实时、高精度混合信号的通用微控制器系列,为精准控制而生,主要应用领域包括新能源,储能,电动汽车,工业自动化等。(2023Q1量产)
与国际品牌T公司C2000相比,先楫半导体HPM6200系列CPU性能实现了超越。HPM6200主频600MHz,而C2000在200MHz以内;
对比国际品牌S公司的G4系列,HPM6200系列在CPU性能、16位ADC、PLA等性能和功能上实现超越。
性能方面,HPM6200系列芯片主频达到600MHz, 是RISC-V 单双核处理器,带有FPU和DSP,内置4 组8通道增强型 PWM 控制器(8ch/组),提升了系统控制精度,可实现单芯片控制多轴电机或者单芯片实现复杂拓扑的数字电源。同时配备了可编程逻辑阵列 PLA, 3 个 2MSPS 16 位高精度 ADC, 16个模拟输入通道以及4 个模拟比较器和 2 个 1MSPS 12 位 DAC。
此外,HPM6200系列还具备多种通讯接口:1 个内置 PHY 的高速 USB,多达4路CAN-FD, 4 路 LIN 及丰富的 UART、 SPI、I2C 等。
2、STM32H743基于SPI的SD卡驱动开发流程简析
STM32H743以太网驱动调试
硬件环境:
基于STM32H743IIT6自研单板
(1)外部时钟:25MHz
(2)调试串口: PC12 ———> UART5_TX
PD2 ———> UART5_RX
(3)SPI6
PG12 ———> SPI6_MISO
PG13 ———> SPI6_SCK
PG14 ———> SPI6_MOSI
PG8 ———> SPI6_NSS
软件开发环境
RT-Thread Studio
版本: 2.2.6
构建ID: 202211231640
OS: Windows 10, v.10.0, x86_64 / win32
调试串口+以太网
RT-Thread配置
1.jpg
1.jpg
SPI配置
在board.h文件中,参考SPI配置说明依次配置SPI参数
/ -------------------------- SPI CONFIG BEGIN -------------------------- /
/** if you want to use spi bus you can use the following instructions.
STEP 1, open spi driver framework support in the RT-Thread Settings file
STEP 2, define macro related to the spi bus* ```
such as #define BSP_USING_SPI1
STEP 3, copy your spi init function from stm32xxxx_hal_msp.c generated by stm32cubemx to the end of board.c file
such as void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
STEP 4, modify your stm32xxxx_hal_config.h file to support spi peripherals. define macro related to the peripherals
such as #define HAL_SPI_MODULE_ENABLED
/
#define BSP_USING_SPI
/ #define BSP_USING_SPI1*/
/ #define BSP_USING_SPI2 /
/ #define BSP_USING_SPI3 /
/ #define BSP_USING_SPI4 /
/ #define BSP_USING_SPI5 /
#define BSP_USING_SPI6
/ -------------------------- SPI CONFIG END -------------------------- /
在board.c文件中添加HAL_SPI_MspInit函数
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
if(spiHandle->Instance==SPI1)
{
/* USER CODE BEGIN SPI1_MspInit 0 /
/ USER CODE END SPI1_MspInit 0 /
/ * Initializes the peripherals clock
/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI1;
PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/ SPI1 clock enable */
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI1 GPIO Configuration
PG9 ------> SPI1_MISO
PG11 ------> SPI1_SCK
PB5 ------> SPI1_MOSI
/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/ SPI1 interrupt Init /
HAL_NVIC_SetPriority(SPI1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
/ USER CODE BEGIN SPI1_MspInit 1 /
/ USER CODE END SPI1_MspInit 1 */
}
else if(spiHandle->Instance==SPI2)
{
/* USER CODE BEGIN SPI2_MspInit 0 */
/* USER CODE END SPI2_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI2;
PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* SPI2 clock enable */
__HAL_RCC_SPI2_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOI_CLK_ENABLE();
/**SPI2 GPIO Configuration
PB10 ------> SPI2_SCK
PB15 ------> SPI2_MOSI
PI2 ------> SPI2_MISO
*/
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
/* SPI2 interrupt Init */
HAL_NVIC_SetPriority(SPI2_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(SPI2_IRQn);
/* USER CODE BEGIN SPI2_MspInit 1 */
/* USER CODE END SPI2_MspInit 1 */
}
else if(spiHandle->Instance==SPI3)
{
/* USER CODE BEGIN SPI3_MspInit 0 */
/* USER CODE END SPI3_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI3;
PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* SPI3 clock enable */
__HAL_RCC_SPI3_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/**SPI3 GPIO Configuration
PB2 ------> SPI3_MOSI
PC10 ------> SPI3_SCK
PC11 ------> SPI3_MISO
*/
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF7_SPI3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* SPI3 interrupt Init */
HAL_NVIC_SetPriority(SPI3_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(SPI3_IRQn);
/* USER CODE BEGIN SPI3_MspInit 1 */
/* USER CODE END SPI3_MspInit 1 */
}
else if(spiHandle->Instance==SPI4)
{
/* USER CODE BEGIN SPI4_MspInit 0 */
/* USER CODE END SPI4_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI4;
PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_D2PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* SPI4 clock enable */
__HAL_RCC_SPI4_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
/**SPI4 GPIO Configuration
PE2 ------> SPI4_SCK
PE5 ------> SPI4_MISO
PE6 ------> SPI4_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;//GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI4;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/* SPI4 interrupt Init */
HAL_NVIC_SetPriority(SPI4_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(SPI4_IRQn);
/* USER CODE BEGIN SPI4_MspInit 1 */
/* USER CODE END SPI4_MspInit 1 */
}
else if(spiHandle->Instance==SPI5)
{
/* USER CODE BEGIN SPI5_MspInit 0 */
/* USER CODE END SPI5_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI5;
PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_D2PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* SPI5 clock enable */
__HAL_RCC_SPI5_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
/**SPI5 GPIO Configuration
PF7 ------> SPI5_SCK
PF8 ------> SPI5_MISO
PF9 ------> SPI5_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI5;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
/* SPI5 interrupt Init */
HAL_NVIC_SetPriority(SPI5_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(SPI5_IRQn);
/* USER CODE BEGIN SPI5_MspInit 1 */
/* USER CODE END SPI5_MspInit 1 */
}
else if(spiHandle->Instance==SPI6)
{
/* USER CODE BEGIN SPI6_MspInit 0 */
/* USER CODE END SPI6_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI6;
PeriphClkInitStruct.Spi6ClockSelection = RCC_SPI6CLKSOURCE_D3PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* SPI6 clock enable */
__HAL_RCC_SPI6_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
/**SPI6 GPIO Configuration
PG12 ------> SPI6_MISO
PG13 ------> SPI6_SCK
PG14 ------> SPI6_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI6;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/* SPI6 interrupt Init */
HAL_NVIC_SetPriority(SPI6_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(SPI6_IRQn);
/* USER CODE BEGIN SPI6_MspInit 1 */
/* USER CODE END SPI6_MspInit 1 */
}
}
在stm32h7xx_hal_conf.h文件中,打开宏定义:
#define HAL_SPI_MODULE_ENABLED
在drv_spi.c文件的spi_config数组中用到了SPI6_BUS_CONFIG,默认工程是没有的,需要自己添加,可以参考已有的SPI配置
1.jpg
在spi_config.h文件尾部添加SPI6_BUS_CONFIG
#ifdef BSP_USING_SPI6
#ifndef SPI6_BUS_CONFIG
#define SPI6_BUS_CONFIG
{
.Instance = SPI6,
.bus_name = "spi6",
}
#endif /* SPI6_BUS_CONFIG /
#endif / BSP_USING_SPI6 /
//#ifdef BSP_SPI6_TX_USING_DMA
//#ifndef SPI6_TX_DMA_CONFIG
//#define SPI6_TX_DMA_CONFIG
// {
// .dma_rcc = SPI6_TX_DMA_RCC,
// .Instance = SPI6_TX_DMA_INSTANCE,
// .channel = SPI6_TX_DMA_CHANNEL,
// .dma_irq = SPI6_TX_DMA_IRQ,
// }
//#endif / SPI6_TX_DMA_CONFIG /
//#endif / BSP_SPI6_TX_USING_DMA /
//
//#ifdef BSP_SPI6_RX_USING_DMA
//#ifndef SPI6_RX_DMA_CONFIG
//#define SPI6_RX_DMA_CONFIG
// {
// .dma_rcc = SPI6_RX_DMA_RCC,
// .Instance = SPI6_RX_DMA_INSTANCE,
// .channel = SPI6_RX_DMA_CHANNEL,
// .dma_irq = SPI6_RX_DMA_IRQ,
// }
//#endif / SPI6_RX_DMA_CONFIG /
//#endif / BSP_SPI6_RX_USING_DMA */
在dfs_fs.c文件中,添加文件系统默认装载表:
const struct dfs_mount_tbl mount_table[] =
{
{"sd0", "/", "elm", 0, 0},
{0}
};
在driver目录下添加drv_spi_tfcard.c文件
测试
1.jpg
至此完成基于SPI的SD驱动框架。
遗留问题
添加SD后,MPU配置会影响以太网ping的效果,使用下面配置SD卡、以太网均正常
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};
/* Disables the MPU /
HAL_MPU_Disable();
/ * Initializes and configures the Region and the memory to be protected
/
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0x30040000;
MPU_InitStruct.Size = MPU_REGION_SIZE_256B;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/ * Initializes and configures the Region and the memory to be protected
/
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.BaseAddress = 0x30044000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/ Enables the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
使用下面的配置,以太网ping不通
{
MPU_Region_InitTypeDef MPU_InitStruct;
/* Disable the MPU /
HAL_MPU_Disable();
/ Configure the MPU attributes as WT for AXI SRAM /
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x24000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_512KB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0X00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
#ifdef BSP_USING_SDRAM
/ Configure the MPU attributes as WT for SDRAM /
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0xC0000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_32MB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
#endif
#ifdef BSP_USING_ETH
/ Configure the MPU attributes as Device not cacheable
for ETH DMA descriptors and RX Buffers*/
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x30040000;
MPU_InitStruct.Size = MPU_REGION_SIZE_32KB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
#endif
/* Configure the MPU attributes as WT for QSPI /
// MPU_InitStruct.Enable = MPU_REGION_ENABLE;
// MPU_InitStruct.BaseAddress = 0x90000000;
// MPU_InitStruct.Size = MPU_REGION_SIZE_8MB;
// MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
// MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
// MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
// MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
// MPU_InitStruct.Number = MPU_REGION_NUMBER3;
// MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
// MPU_InitStruct.SubRegionDisable = 0X00;
// MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
//
// HAL_MPU_ConfigRegion(&MPU_InitStruct);
/ Enable the MPU /
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
/ Enable CACHE */
SCB_EnableICache();
SCB_EnableDCache();
return RT_EOK;
}
3、STM32H743的FDCAN发送线程卡死的处理方法
芯片型号STM32H743IIT6,测试时发现如果外面没有连接CAN设备,程序调用CAN发送时会一直等待发送反馈,导致相关线程挂起。
分析发现是卡在can.c文件的168行_can_int_tx函数:rt_completion_wait(&(tx_tosnd->completion), RT_WAITING_FOREVER);
rt_inline int _can_int_tx(struct rt_can_device *can, const struct rt_can_msg *data, int msgs)
{
int size;
struct rt_can_tx_fifo *tx_fifo;
RT_ASSERT(can != RT_NULL);
size = msgs;
tx_fifo = (struct rt_can_tx_fifo *) can->can_tx;
RT_ASSERT(tx_fifo != RT_NULL);
while (msgs)
{
rt_base_t level;
rt_uint32_t no;
rt_uint32_t result;
struct rt_can_sndbxinx_list tx_tosnd = RT_NULL;
rt_sem_take(&(tx_fifo->sem), RT_WAITING_FOREVER);
level = rt_hw_interrupt_disable();
tx_tosnd = rt_list_entry(tx_fifo->freelist.next, struct rt_can_sndbxinx_list, list);
RT_ASSERT(tx_tosnd != RT_NULL);
rt_list_remove(&tx_tosnd->list);
rt_hw_interrupt_enable(level);
no = ((rt_uint32_t)tx_tosnd - (rt_uint32_t)tx_fifo->buffer) / sizeof(struct rt_can_sndbxinx_list);
tx_tosnd->result = RT_CAN_SND_RESULT_WAIT;
if (can->ops->sendmsg(can, data, no) != RT_EOK)
{
/ send failed. */
level = rt_hw_interrupt_disable();
rt_list_insert_after(&tx_fifo->freelist, &tx_tosnd->list);
rt_hw_interrupt_enable(level);
rt_sem_release(&(tx_fifo->sem));
continue;
}
can->status.sndchange = 1;
rt_completion_wait(&(tx_tosnd->completion), RT_WAITING_FOREVER);
说明一直在等待完成信号,而发送完成信号的地方在can.c文件的900行rt_hw_can_isr函数:
rt_completion_done(&(tx_fifo->buffer[no].completion));
case RT_CAN_EVENT_TX_DONE:
case RT_CAN_EVENT_TX_FAIL:
{
struct rt_can_tx_fifo *tx_fifo;
rt_uint32_t no;
no = event > > 8;
tx_fifo = (struct rt_can_tx_fifo *) can- >can_tx;
RT_ASSERT(tx_fifo != RT_NULL);
if ((event & 0xff) == RT_CAN_EVENT_TX_DONE)
{
tx_fifo- >buffer[no].result = RT_CAN_SND_RESULT_OK;
}
else
{
tx_fifo- >buffer[no].result = RT_CAN_SND_RESULT_ERR;
}
rt_completion_done(&(tx_fifo- >buffer[no].completion));
break;
}
然后想到如果can总线没有其他设备,CAN发送报文应该属于出错的情况,查看drv_fdcan.c文件中关于几种中断的处理,发现故障后的回调函数里没有调用rt_hw_can_isr。
于是参考HAL_FDCAN_TxBufferCompleteCallback函数的处理方式,对HAL_FDCAN_ErrorCallback进行了如下处理。
void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef *hfdcan)
{
rt_uint32_t tmp_u32Errcount;
rt_uint32_t tmp_u32status;
uint32_t ret = HAL_FDCAN_GetError(hfdcan);
if(hfdcan->Instance == FDCAN1)
{
#ifdef BSP_USING_FDCAN1
//can1
if( (ret & FDCAN_IT_ARB_PROTOCOL_ERROR) &&
(hfdcan->Instance->CCCR & FDCAN_CCCR_INIT_Msk))
{
//hfdcan->Instance->CCCR |= FDCAN_CCCR_CCE_Msk;
hfdcan->Instance->CCCR &= ~FDCAN_CCCR_INIT_Msk;
st_DrvCan1.device.status.errcode = 0xff;
}
else
{
tmp_u32Errcount = st_DrvCan1.fdcanHandle.Instance->ECR;
tmp_u32status = st_DrvCan1.fdcanHandle.Instance->PSR;
st_DrvCan1.device.status.rcverrcnt = (tmp_u32Errcount>>8)&0x000000ff;
st_DrvCan1.device.status.snderrcnt = (tmp_u32Errcount)&0x000000ff;
st_DrvCan1.device.status.lasterrtype = tmp_u32status&0x000000007;
rt_hw_can_isr(&st_DrvCan1.device, RT_CAN_EVENT_TX_FAIL);
}
#endif / BSP_USING_FDCAN1 /
}
else
{
#ifdef BSP_USING_FDCAN2
if( (ret & FDCAN_IT_ARB_PROTOCOL_ERROR) &&
(hfdcan->Instance->CCCR & FDCAN_CCCR_INIT_Msk))
{
//hfdcan->Instance->CCCR |= FDCAN_CCCR_CCE_Msk;
hfdcan->Instance->CCCR &= ~FDCAN_CCCR_INIT_Msk;
st_DrvCan2.device.status.errcode = 0xff;
}
else
{
//can2
tmp_u32Errcount = st_DrvCan2.fdcanHandle.Instance->ECR;
tmp_u32status = st_DrvCan2.fdcanHandle.Instance->PSR;
st_DrvCan2.device.status.rcverrcnt = (tmp_u32Errcount>>8)&0x000000ff;
st_DrvCan2.device.status.snderrcnt = (tmp_u32Errcount)&0x000000ff;
st_DrvCan2.device.status.lasterrtype = tmp_u32status&0x000000007;
rt_hw_can_isr(&st_DrvCan2.device, RT_CAN_EVENT_TX_FAIL);
}
#endif / BSP_USING_FDCAN2 /
}
}
经过测试发现即使CAN总线上没有别的设备,调用发送函数也不会一直等待,而是返回发送失败。
4、STM32H723、STM32H743、STM32H750的区别
STM32H723、STM32H743和STM32H750是STMicroelectronics(意法半导体)推出的三款微控制器产品,它们都属于STM32H7系列,基于ARM Cortex-M7内核,并具备丰富的外设和高性能特性。以下是它们之间的主要区别:
处理器频率:这三款微控制器的处理器频率有所不同。STM32H723的最大频率为550 MHz,STM32H743的最大频率为480 MHz,而STM32H750的最大频率为480 MHz。因此,STM32H723具有稍高的最大处理器频率。
存储器容量:这些微控制器提供不同的闪存和RAM容量选项以适应不同的应用需求。例如,STM32H723提供高达1 MB的闪存和564 KB的RAM,STM32H743提供高达2 MB的闪存和1 MB的RAM,而STM32H750提供128 Kbytes闪存和1MB 的RAM。
封装类型:这些微控制器在封装类型上也有所不同。例如,STM32H723和STM32H743都可提供LQFP、UFBGA、BGA和WLCSP等多种封装选项,而STM32H750主要提供LQFP封装。
特殊功能:这些微控制器在特殊功能和外设上也有区别。例如,STM32H723具备音频和视频处理支持,包括多个I2S接口和视频解码器接口;STM32H743提供更多的USB接口选择,如OTG、Host和Device等;STM32H750则强调了其低功耗特性和更紧凑的封装。
5、STM32H743:高性能处理器
STM32H743是一款高性能处理器,具有强大的处理能力,可满足各种处理要求。它的特点是:高速运行,低功耗,可靠性高,多功能,易于使用,可以用于各种应用场景。本文旨在介绍STM32H743的特点,并分析其在多种应用场景中的优势。
STM32H743的优势
高速运行
STM32H743具有高效率的处理速度,可以满足各种复杂的应用程序的需求。它的处理器核心为Cortex-M7,主频高达400MHz,可以实现高速运行,满足复杂的应用场景。
低功耗
STM32H743的低功耗特性使其可以长时间运行,而不会影响系统的性能。它具有多种低功耗模式,可以有效减少系统的功耗。此外,STM32H743还支持多种外设,可以更好地实现低功耗。
可靠性高
STM32H743具有可靠性高的特点,它的处理器核心采用了多级安全技术,可以有效防止恶意攻击,保护系统的安全性。此外,STM32H743还支持多种外设,可以更好地实现系统的可靠性。
多功能
STM32H743支持多种外设,可以满足各种应用场景的需求。它支持USB、Ethernet、CAN、I2C、SPI等多种接口,可以满足不同类型的设备的连接需求。此外,STM32H743还支持多种外设,可以更好地实现多功能功能。
易于使用
STM32H743采用了高效的软件开发工具,可以更加简单、快捷地完成软件开发。它支持多种开发语言,可以满足不同类型的开发需求。此外,STM32H743还支持各种外设,可以更加便捷地完成软件开发。
STM32H743的应用场景
STM32H743可以用于各种应用场景,其中包括:
智能家居
STM32H743可以用于智能家居系统,可以实现家庭设备的连接、控制和管理。它的高速运行和低功耗特性可以满足智能家居系统的需求,可以更好地实现家庭智能化。
自动驾驶
STM32H743可以用于自动驾驶汽车,可以实现汽车的智能控制。它的高速运行和可靠性高的特性可以满足自动驾驶系统的需求,可以更好地实现汽车的智能化。
工业自动化
STM32H743可以用于工业自动化系统,可以实现多种设备的智能控制。它的高速运行和多功能的特性可以满足工业自动化系统的需求,可以更好地实现工业自动化。
总结
STM32H743是一款高性能处理器,具有强大的处理能力,可满足各种处理要求。它的特点是:高速运行,低功耗,可靠性高,多功能,易于使用,可以用于各种应用场景。它可以用于智能家居、自动驾驶和工业自动化等多种应用场景,可以更好地实现智能化。
责任编辑:David
【免责声明】
1、本文内容、数据、图表等来源于网络引用或其他公开资料,版权归属原作者、原发表出处。若版权所有方对本文的引用持有异议,请联系拍明芯城(marketing@iczoom.com),本方将及时处理。
2、本文的引用仅供读者交流学习使用,不涉及商业目的。
3、本文内容仅代表作者观点,拍明芯城不对内容的准确性、可靠性或完整性提供明示或暗示的保证。读者阅读本文后做出的决定或行为,是基于自主意愿和独立判断做出的,请读者明确相关结果。
4、如需转载本方拥有版权的文章,请联系拍明芯城(marketing@iczoom.com)注明“转载原因”。未经允许私自转载拍明芯城将保留追究其法律责任的权利。
拍明芯城拥有对此声明的最终解释权。