【前言】
I3C做为I2C的“升级版本”,他不但在速度上有很高的提升,而且也不限于以前的marster/slave模式。本篇将对I3C的Controller 的配置进行分析。
【实验环境】
STM32CubeMX 6.12
【开发板】
NUCLEO-STM32H503
【配置步骤】
一、Hardware Specific Timing Constraints(硬件特定时间约束)约定SDA上升时间为350ns。
这个参数与Bus Timing Activiy相互配合,通过与I3C时钟来计算影响Timing Register 1中的SDA_HD位。用于I3C中角色变换SDA需要上拉保持的时间。
在用户手册RM0492中有这样的计算公式:
SDA hold time = (SDA_HD + 0.5) x tI3CCLK
二、Bus Characteristic
1、在这个配置选项中有3个可配置选项:
①Bus usage可以选择I3C pure bus、Mixed I3C and I2C。即为纯I3C总线,或者同时可以使用I2C或者I3C。
②Frequency I3C Controller 总线频率,打开后会默认为1250Khz,可以通过手工录入指定的频率。
③I3C Duty Cycle即占空比。默认配置为50%。
2、这三个参数配置好后,会自动计算出Timi Register 0的参数。如下图所示:
在寄存器的位置如下:
三、Bus Timing Activity
1、SDA Hold Time 可以选择 与输入时钟的0.5倍或者1.5倍。这个选项修改后,会自动计算生成Timing Register 1的配置值。
2、Wait Time 可以选择Own Controller Activity State0-3。
这个配置为位Timing Register 1 9:8 ASNCR[1:0]:新控制器的活动状态(当13C充当活动控制器时)此字段指示作为新目标访问前的等待时间。只有当I3C充当控制器时,才能修改此字段。
3、Bus Free Duration 其作用如下:
主要的作用为I3C为作为Controller角色时的时序要求,遵循MIPI协议要求。
4、Bus Idle Duration: 超过指定配置时间后,总线视为Idle状态。
经设置后,生成Timing Register 1如下:
四、Basic Configration
此次作为Controller选不进行配置
五、Advanced Configuration
配置Transmit Fifo Threshold 与Recive Fifo Threshold可以选择Threshold 4 bytes以及Threshold 1 bytes。
配置如下图所示:
【中断】
开启I3C1 event interrupt 以及 I3C1 error interrup:
生成工程后,在mdk的工程中可见配置如下:
/* I3C1 init function */ void MX_I3C1_Init(void) { /* USER CODE BEGIN I3C1_Init 0 */ /* USER CODE END I3C1_Init 0 */ I3C_FifoConfTypeDef sFifoConfig = {0}; I3C_CtrlConfTypeDef sCtrlConfig = {0}; /* USER CODE BEGIN I3C1_Init 1 */ /* USER CODE END I3C1_Init 1 */ hi3c1.Instance = I3C1; hi3c1.Mode = HAL_I3C_MODE_CONTROLLER; hi3c1.Init.CtrlBusCharacteristic.SDAHoldTime = HAL_I3C_SDA_HOLD_TIME_1_5; hi3c1.Init.CtrlBusCharacteristic.WaitTime = HAL_I3C_OWN_ACTIVITY_STATE_0; hi3c1.Init.CtrlBusCharacteristic.SCLPPLowDuration = 0x77; hi3c1.Init.CtrlBusCharacteristic.SCLI3CHighDuration = 0x4f; hi3c1.Init.CtrlBusCharacteristic.SCLODLowDuration = 0x77; hi3c1.Init.CtrlBusCharacteristic.SCLI2CHighDuration = 0x00; hi3c1.Init.CtrlBusCharacteristic.BusFreeDuration = 0x32; hi3c1.Init.CtrlBusCharacteristic.BusIdleDuration = 0xf8; if (HAL_I3C_Init(&hi3c1) != HAL_OK) { Error_Handler(); } /** Configure FIFO */ sFifoConfig.RxFifoThreshold = HAL_I3C_RXFIFO_THRESHOLD_1_4; sFifoConfig.TxFifoThreshold = HAL_I3C_TXFIFO_THRESHOLD_1_4; sFifoConfig.ControlFifo = HAL_I3C_CONTROLFIFO_DISABLE; sFifoConfig.StatusFifo = HAL_I3C_STATUSFIFO_DISABLE; if (HAL_I3C_SetConfigFifo(&hi3c1, &sFifoConfig) != HAL_OK) { Error_Handler(); } /** Configure controller */ sCtrlConfig.DynamicAddr = 0; sCtrlConfig.StallTime = 0x00; sCtrlConfig.HotJoinAllowed = DISABLE; sCtrlConfig.ACKStallState = DISABLE; sCtrlConfig.CCCStallState = DISABLE; sCtrlConfig.TxStallState = DISABLE; sCtrlConfig.RxStallState = DISABLE; sCtrlConfig.HighKeeperSDA = DISABLE; if (HAL_I3C_Ctrl_Config(&hi3c1, &sCtrlConfig) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN I3C1_Init 2 */ /* USER CODE END I3C1_Init 2 */ } void HAL_I3C_MspInit(I3C_HandleTypeDef* i3cHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; if(i3cHandle->Instance==I3C1) { /* USER CODE BEGIN I3C1_MspInit 0 */ /* USER CODE END I3C1_MspInit 0 */ /** Initializes the peripherals clock */ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I3C1; PeriphClkInitStruct.I3c1ClockSelection = RCC_I3C1CLKSOURCE_PCLK1; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { Error_Handler(); } /* I3C1 clock enable */ __HAL_RCC_I3C1_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); /**I3C1 GPIO Configuration PB10 ------> I3C1_SDA PC8 ------> I3C1_SCL */ GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF8_I3C1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF3_I3C1; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /* USER CODE BEGIN I3C1_MspInit 1 */ /* USER CODE END I3C1_MspInit 1 */ } }
I3C的配置在官方示例中有,但是要深入进解他的配置含义还需要配合数据手册才能明白他的含义。