STS_RR_R125/TOF/App/X-WL55_WLE5_53L0X.c

252 lines
8.0 KiB
C

/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file X-WL55_WLE5_53L0X.c
* @author Yunhorn (r) Technology Limited Application Team
* @brief implement X-WL55_WLE5_53L0X BSP
******************************************************************************
* @attention
*
* Copyright (c) 2023 Yunhorn Technology Limited.
* Copyright (c) 2023 Shenzhen Yunhorn Technology Co., Ltd.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
#include <string.h>
#include "X-WL55_WLE5_53L0X.h"
#include "stm32wlxx_hal.h"
#include "main.h"
#ifndef HAL_I2C_MODULE_ENABLED
#define HAL_I2C_MODULE_ENABLED
#pragma message("hal conf should enable i2c")
#endif
/* when not customized by application define dummy one */
#ifndef XNUCLEO53L1A1_GetI2cBus
/**
* macro that can be overloaded by user to enforce i2c sharing in RTOS context
*/
#define XNUCLEO53L1A1_GetI2cBus(...) (void)0
#endif
#ifndef XNUCLEO53L1A1_PutI2cBus
/** macro can be overloaded by user to enforce i2c sharing in RTOS context
*/
# define XNUCLEO53L1A1_PutI2cBus(...) (void)0
#endif
/****************************************************
*@defgroup XNUCLEO53L1A1_globals
*@{
*/
/**
* i2c handle to be use of all i2c access
* end user shall provide it to
* can be @a XNUCLEO53L1A1_I2C1Configure() @sa XNUCLEO53L1A1_usage
* @warning do not use any XNUCLEO53L1A1_xxx prior to a first init with valid i2c handle
*/
I2C_HandleTypeDef XNUCLEO53L1A1_hi2c;
/**
* Expansion board i2c bus recovery
*
* We may get reset in middle of an i2c access (h/w reset button, debug or f/w load)
* hence some agent on bus may be in middle of a transaction and can create issue or even prevent starting (SDA is low)
* this routine does use gpio to manipulate and recover i2c bus line in all cases.
*/
static void _I2cFailRecover(){
GPIO_InitTypeDef GPIO_InitStruct;
int i, nRetry=0;
// We can't assume bus state based on SDA and SCL state (we may be in a data or NAK bit so SCL=SDA=1)
// by setting SDA high and toggling SCL at least 10 time we ensure whatever agent and state
// all agent should end up seeing a "stop" and bus get back to an known idle i2c bus state
PME_ON;
// Enable I/O
__GPIOA_CLK_ENABLE();
HAL_GPIO_WritePin(I2C2_SCL_PORT, I2C2_SCL_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(I2C2_SDA_PORT, I2C2_SDA_PIN, GPIO_PIN_SET);
GPIO_InitStruct.Pin = I2C2_SCL_PIN|I2C2_SDA_PIN ;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(I2C2_SDA_PORT, &GPIO_InitStruct);
//TODO we could do this faster by not using HAL delay 1ms for clk timing
do{
for( i=0; i<10; i++){
HAL_GPIO_WritePin(I2C2_SCL_PORT, I2C2_SCL_PIN, GPIO_PIN_RESET);
HAL_Delay(1);
HAL_GPIO_WritePin(I2C2_SCL_PORT, I2C2_SCL_PIN, GPIO_PIN_SET);
HAL_Delay(1);
}
// if( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9) == 0 ){
// static int RetryRecover;
// RetryRecover++;
// }
}while(HAL_GPIO_ReadPin(I2C2_SDA_PORT, I2C2_SDA_PIN) == 0 && nRetry++<7);
if( HAL_GPIO_ReadPin(I2C2_SDA_PORT, I2C2_SDA_PIN) == 0 ){
__GPIOA_CLK_ENABLE();
//We are still in bad i2c state warm user by blinking led but stay here
GPIO_InitStruct.Pin = LED1_Pin ;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(LED1_GPIO_Port, &GPIO_InitStruct);
do{
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
HAL_Delay(33);
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
HAL_Delay(33);
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
HAL_Delay(33);
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
HAL_Delay(33*20);
}while(0);
}
}
int XWL55_WLE5_53L0X_I2C2Configure() {
int status;
GPIO_InitTypeDef GPIO_InitStruct;
_I2cFailRecover();
/* Peripheral clock enable */
__GPIOA_CLK_ENABLE();
__I2C2_CLK_ENABLE();
/**I2C1 GPIO Configuration\n
PB8 ------> I2C1_SCL\n
PB9 ------> I2C1_SDA
*I2C2 GPIO configuration
PA12 -------> I2C2_SCL
PA11 -------> I2C2_SDA
*/
GPIO_InitStruct.Pin = I2C2_SCL_PIN | I2C2_SDA_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C2;
HAL_GPIO_Init(I2C2_SDA_PORT, &GPIO_InitStruct);
XNUCLEO53L1A1_hi2c.Instance = I2C2;
//XNUCLEO53L1A1_hi2c.Init.Timing = 0x00300F38; /* set 400KHz fast mode i2c*/
//XNUCLEO53L1A1_hi2c.Init.Timing = I2C2_FAST_400K; //UPDATE 2024-07-09
XNUCLEO53L1A1_hi2c.Init.Timing = I2C2_STANDARD_100K; // UPDATE 2024-07-12
//XNUCLEO53L1A1_hi2c.Init.Timing = 0x2010091A; //0x2010091A = 400K Fast Mode, 0x20303E5D, 100K Standard mode, 0x20000209 Fast Mode Plus, 1Mbps
XNUCLEO53L1A1_hi2c.Init.OwnAddress1 = 0;
XNUCLEO53L1A1_hi2c.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
XNUCLEO53L1A1_hi2c.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
XNUCLEO53L1A1_hi2c.Init.OwnAddress2 = 0;
XNUCLEO53L1A1_hi2c.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
XNUCLEO53L1A1_hi2c.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
status = HAL_I2C_Init(&XNUCLEO53L1A1_hi2c);
return status;
}
int XWL55_WLE5_53L0X_SetIntrStateId(int EnableIntr, int DevNo)
{
int status;
IRQn_Type IntrNo;
int IntrPin;
switch (DevNo){
case 1:
IntrNo = VL53L0X_GPIO1_L_INTx;
IntrPin= VL53L0X_GPIO1_L_GPIO_PIN;
break;
case 0:
IntrNo = VL53L0X_GPIO1_C_INTx;
IntrPin= VL53L0X_GPIO1_C_GPIO_PIN;
break;
case 2:
IntrNo = VL53L0X_GPIO1_R_INTx;
IntrPin= VL53L0X_GPIO1_R_GPIO_PIN;
break;
default:
break;
}
/*
IntrNo = VL53L0X_GPIO1_C_INTx;
IntrPin= VL53L0X_GPIO1_C_GPIO_PIN;
*/
status = 0;
if( EnableIntr ){
__HAL_GPIO_EXTI_CLEAR_IT(IntrPin);
NVIC_ClearPendingIRQ(IntrNo);
HAL_NVIC_EnableIRQ(IntrNo);
/**
* @note When enabling interrupt end user shall check actual state of the line and soft trigger event if active
* Alternatively user can use API and device feature to clear device Interrupt status to possibly generates a new edge.
* on shared pin configuration this must be repeated for all device.
* The same shall be done after clearing a condition in device and interrupt remain active.
*/
}
else{
HAL_NVIC_DisableIRQ(IntrNo);
__HAL_GPIO_EXTI_CLEAR_IT(IntrPin);
NVIC_ClearPendingIRQ(IntrNo);
}
return status;
}
int XWL55_WLE5_53L0X_Init(void)
{
int status;
status = XWL55_WLE5_53L0X_I2C2Configure();
return status;
}
void XWL55_WLE5_53L0X_ResetId(uint8_t DevNo, int state)
{
switch(DevNo) {
case XNUCLEO53L0X_LEFT:
#if defined(TOF_2)
HAL_GPIO_WritePin(TOF_L_XSHUT_GPIO_Port, TOF_L_XSHUT_Pin, ((state == 1)?GPIO_PIN_SET:GPIO_PIN_RESET));
#endif
break;
#if defined(TOF_1)
case XNUCLEO53L0X_CENTER:
HAL_GPIO_WritePin(TOF_C_XSHUT_GPIO_Port, TOF_C_XSHUT_Pin, ((state == 1)?GPIO_PIN_SET:GPIO_PIN_RESET));
break;
#endif
case XNUCLEO53L0X_RIGHT:
#if defined(TOF_3)
HAL_GPIO_WritePin(TOF_R_XSHUT_GPIO_Port, TOF_R_XSHUT_Pin, ((state == 1)?GPIO_PIN_SET:GPIO_PIN_RESET));
#endif
break;
default:
break;
}
}
/**
*
* @} X-WL55_WLE5_53L0X_top
*/