252 lines
8.0 KiB
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
|
|
*/
|