1 /*!
2  * \file      i2c-board.c
3  *
4  * \brief     Target board I2C driver implementation
5  *
6  * \copyright Revised BSD License, see section \ref LICENSE.
7  *
8  * \code
9  *                ______                              _
10  *               / _____)             _              | |
11  *              ( (____  _____ ____ _| |_ _____  ____| |__
12  *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
13  *               _____) ) ____| | | || |_| ____( (___| | | |
14  *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
15  *              (C)2013-2017 Semtech
16  *
17  * \endcode
18  *
19  * \author    Miguel Luis ( Semtech )
20  *
21  * \author    Gregory Cristian ( Semtech )
22  */
23 #include "stm32l0xx.h"
24 #include "utilities.h"
25 #include "board-config.h"
26 #include "i2c-board.h"
27 
28 /*!
29  *  The value of the maximal timeout for I2C waiting loops
30  */
31 #define TIMEOUT_MAX                                 0x8000
32 
33 static I2C_HandleTypeDef I2cHandle = { 0 };
34 
35 static I2cAddrSize I2cInternalAddrSize = I2C_ADDR_SIZE_8;
36 
I2cMcuInit(I2c_t * obj,I2cId_t i2cId,PinNames scl,PinNames sda)37 void I2cMcuInit( I2c_t *obj, I2cId_t i2cId, PinNames scl, PinNames sda )
38 {
39     __HAL_RCC_I2C1_CLK_DISABLE( );
40     __HAL_RCC_I2C1_CLK_ENABLE( );
41     __HAL_RCC_I2C1_FORCE_RESET( );
42     __HAL_RCC_I2C1_RELEASE_RESET( );
43 
44     obj->I2cId = i2cId;
45 
46     I2cHandle.Instance  = ( I2C_TypeDef * )I2C1_BASE;
47 
48     GpioInit( &obj->Scl, scl, PIN_ALTERNATE_FCT, PIN_OPEN_DRAIN, PIN_NO_PULL, GPIO_AF4_I2C1 );
49     GpioInit( &obj->Sda, sda, PIN_ALTERNATE_FCT, PIN_OPEN_DRAIN, PIN_NO_PULL, GPIO_AF4_I2C1 );
50 }
51 
I2cMcuFormat(I2c_t * obj,I2cMode mode,I2cDutyCycle dutyCycle,bool I2cAckEnable,I2cAckAddrMode AckAddrMode,uint32_t I2cFrequency)52 void I2cMcuFormat( I2c_t *obj, I2cMode mode, I2cDutyCycle dutyCycle, bool I2cAckEnable, I2cAckAddrMode AckAddrMode, uint32_t I2cFrequency )
53 {
54     __HAL_RCC_I2C1_CLK_ENABLE( );
55 
56     if( I2cFrequency == 100000 )
57     {
58         I2cHandle.Init.Timing = 0x00707CBB;
59     }
60     else if( I2cFrequency == 400000 )
61     {
62         I2cHandle.Init.Timing = 0x00300F38;
63     }
64 
65     I2cHandle.Init.OwnAddress1 = 0;
66     I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
67     I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
68     I2cHandle.Init.OwnAddress2 = 0;
69     I2cHandle.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
70     I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
71     I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
72 
73     HAL_I2C_Init( &I2cHandle );
74 
75     HAL_I2CEx_ConfigAnalogFilter( &I2cHandle, I2C_ANALOGFILTER_ENABLE );
76     HAL_I2CEx_ConfigDigitalFilter( &I2cHandle, 0 );
77 }
78 
I2cMcuResetBus(I2c_t * obj)79 void I2cMcuResetBus( I2c_t *obj )
80 {
81     __HAL_RCC_I2C1_CLK_DISABLE( );
82     __HAL_RCC_I2C1_CLK_ENABLE( );
83     __HAL_RCC_I2C1_FORCE_RESET( );
84     __HAL_RCC_I2C1_RELEASE_RESET( );
85 
86     GpioInit( &obj->Scl, I2C_SCL, PIN_ALTERNATE_FCT, PIN_OPEN_DRAIN, PIN_NO_PULL, GPIO_AF4_I2C1 );
87     GpioInit( &obj->Sda, I2C_SDA, PIN_ALTERNATE_FCT, PIN_OPEN_DRAIN, PIN_NO_PULL, GPIO_AF4_I2C1 );
88 
89     I2cMcuFormat( obj, MODE_I2C, I2C_DUTY_CYCLE_2, true, I2C_ACK_ADD_7_BIT, 400000 );
90 }
91 
I2cMcuDeInit(I2c_t * obj)92 void I2cMcuDeInit( I2c_t *obj )
93 {
94 
95     HAL_I2C_DeInit( &I2cHandle );
96 
97     __HAL_RCC_I2C1_FORCE_RESET();
98     __HAL_RCC_I2C1_RELEASE_RESET();
99     __HAL_RCC_I2C1_CLK_DISABLE( );
100 
101     GpioInit( &obj->Scl, obj->Scl.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
102     GpioInit( &obj->Sda, obj->Sda.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
103 }
104 
I2cSetAddrSize(I2c_t * obj,I2cAddrSize addrSize)105 void I2cSetAddrSize( I2c_t *obj, I2cAddrSize addrSize )
106 {
107     I2cInternalAddrSize = addrSize;
108 }
109 
I2cMcuWriteBuffer(I2c_t * obj,uint8_t deviceAddr,uint8_t * buffer,uint16_t size)110 LmnStatus_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint8_t *buffer, uint16_t size )
111 {
112     LmnStatus_t status = LMN_STATUS_ERROR;
113 
114     status = ( HAL_I2C_Master_Transmit( &I2cHandle, deviceAddr, buffer, size, 2000 ) == HAL_OK ) ? LMN_STATUS_OK : LMN_STATUS_ERROR;
115 
116     return status;
117 }
118 
I2cMcuReadBuffer(I2c_t * obj,uint8_t deviceAddr,uint8_t * buffer,uint16_t size)119 LmnStatus_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint8_t *buffer, uint16_t size )
120 {
121     LmnStatus_t status = LMN_STATUS_ERROR;
122 
123     status = ( HAL_I2C_Master_Receive( &I2cHandle, deviceAddr, buffer, size, 2000 ) == HAL_OK ) ? LMN_STATUS_OK : LMN_STATUS_ERROR;
124 
125     return status;
126 }
127 
I2cMcuWriteMemBuffer(I2c_t * obj,uint8_t deviceAddr,uint16_t addr,uint8_t * buffer,uint16_t size)128 LmnStatus_t I2cMcuWriteMemBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *buffer, uint16_t size )
129 {
130     LmnStatus_t status = LMN_STATUS_ERROR;
131     uint16_t memAddSize = 0;
132 
133     if( I2cInternalAddrSize == I2C_ADDR_SIZE_8 )
134     {
135         memAddSize = I2C_MEMADD_SIZE_8BIT;
136     }
137     else
138     {
139         memAddSize = I2C_MEMADD_SIZE_16BIT;
140     }
141     status = ( HAL_I2C_Mem_Write( &I2cHandle, deviceAddr, addr, memAddSize, buffer, size, 2000 ) == HAL_OK ) ? LMN_STATUS_OK : LMN_STATUS_ERROR;
142 
143     return status;
144 }
145 
I2cMcuReadMemBuffer(I2c_t * obj,uint8_t deviceAddr,uint16_t addr,uint8_t * buffer,uint16_t size)146 LmnStatus_t I2cMcuReadMemBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *buffer, uint16_t size )
147 {
148     LmnStatus_t status = LMN_STATUS_ERROR;
149     uint16_t memAddSize = 0;
150 
151     if( I2cInternalAddrSize == I2C_ADDR_SIZE_8 )
152     {
153         memAddSize = I2C_MEMADD_SIZE_8BIT;
154     }
155     else
156     {
157         memAddSize = I2C_MEMADD_SIZE_16BIT;
158     }
159     status = ( HAL_I2C_Mem_Read( &I2cHandle, deviceAddr, addr, memAddSize, buffer, size, 2000 ) == HAL_OK ) ? LMN_STATUS_OK : LMN_STATUS_ERROR;
160 
161     return status;
162 }
163 
I2cMcuWaitStandbyState(I2c_t * obj,uint8_t deviceAddr)164 LmnStatus_t I2cMcuWaitStandbyState( I2c_t *obj, uint8_t deviceAddr )
165 {
166     LmnStatus_t status = LMN_STATUS_ERROR;
167 
168     status = ( HAL_I2C_IsDeviceReady( &I2cHandle, deviceAddr, 300, 4096 ) == HAL_OK ) ? LMN_STATUS_OK : LMN_STATUS_ERROR;
169 
170     return status;
171 }
172