Welcome to mirror list, hosted at ThFree Co, Russian Federation.

StHalIic.cpp « Drivers « DevCore « STM32F415APP - github.com/nickshl/DevBoy.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 49d648e9e128517613907b88898d8016258fcb76 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
//******************************************************************************
//  @file StHalIic.cpp
//  @author Nicolai Shlapunov
//
//  @details DevCore: STM32 HAL I2C driver, implementation
//
//  @copyright Copyright (c) 2018, Devtronic & Nicolai Shlapunov
//             All rights reserved.
//
//  @section SUPPORT
//
//   Devtronic invests time and resources providing this open source code,
//   please support Devtronic and open-source hardware/software by
//   donations and/or purchasing products from Devtronic.
//
//******************************************************************************

// *****************************************************************************
// ***   Includes   ************************************************************
// *****************************************************************************
#include "StHalIic.h"

// *****************************************************************************
// ***   This driver can be compiled only if I2C configured in CubeMX   ********
// *****************************************************************************
#ifdef HAL_I2C_MODULE_ENABLED

// *****************************************************************************
// ***   Public: Enable   ******************************************************
// *****************************************************************************
Result StHalIic::Enable()
{
  // Set PE bit
  __HAL_I2C_ENABLE(&hi2c);
  // No errors to return
  return Result::RESULT_OK;
}

// *****************************************************************************
// ***   Public: Disable   *****************************************************
// *****************************************************************************
Result StHalIic::Disable()
{
  // Clear PE bit
  __HAL_I2C_DISABLE(&hi2c);
  // No errors to return
  return Result::RESULT_OK;
}

// *****************************************************************************
// ***   Public: Reset   *******************************************************
// *****************************************************************************
Result StHalIic::Reset()
{
  // Clear PE bit
  CLEAR_BIT(hi2c.Instance->CR1, I2C_CR1_PE);
  // PE must be kept low during at least 3 APB clock cycles in order to
  // perform the software reset. Wait until it actually cleared.
  while(READ_BIT(hi2c.Instance->CR1, I2C_CR1_PE));
  // TODO: make some clock on the SCL line here
  // Set PE bit
  SET_BIT(hi2c.Instance->CR1, I2C_CR1_PE);
  // No errors to return
  return Result::RESULT_OK;
}

// *************************************************************************
// ***   Public: IsDeviceReady   *******************************************
// *************************************************************************
Result StHalIic::IsDeviceReady(uint16_t addr, uint8_t retries)
{
  Result result;
  // Shift address one bit left - HAL blow away LSB, not MSB.
  addr <<= 1U;
  // Check device status
  HAL_StatusTypeDef hal_result = HAL_I2C_IsDeviceReady(&hi2c1, addr, retries, i2c_tx_timeout_ms);
  // Convert operation result to Result
  result = ConvertResult(hal_result);
  // Return result
  return result;
}

// *****************************************************************************
// ***   Public: Transfer   ****************************************************
// *****************************************************************************
Result StHalIic::Transfer(uint16_t addr, uint8_t* tx_buf_ptr, uint32_t tx_size, uint8_t* rx_buf_ptr, uint32_t rx_size)
{
  Result result = Result::ERR_NULL_PTR;

  // Special hack for use HAL_I2C_Mem_Read() function for send Repeated Start if
  // tx_size is 1 or 2 bytes.
  if((tx_buf_ptr != nullptr) && (rx_buf_ptr != nullptr) && ((tx_size == 1U) || (tx_size == 2U)))
  {
    // Variable for store result from the HAL
    HAL_StatusTypeDef hal_result = HAL_OK;

    // Shift address one bit left - HAL blow away LSB, not MSB.
    addr <<= 1U;

    // Transmit data
    hal_result = HAL_I2C_Mem_Read(&hi2c, addr, tx_buf_ptr[0], tx_size, rx_buf_ptr, rx_size, i2c_tx_timeout_ms);

    // Convert operation result to Result
    result = ConvertResult(hal_result);
  }
  else
  {
    if(tx_buf_ptr != nullptr)
    {
      // Transmit data
      result = Write(addr, tx_buf_ptr, tx_size);
    }

    if((rx_buf_ptr != nullptr) && result.IsGood())
    {
      // Clear RX buffer
      for(uint32_t i = 0; i < rx_size; i++)
      {
        rx_buf_ptr[i] = 0;
      }
      // Receive data
      result = Read(addr, rx_buf_ptr, rx_size);
    }
  }

  return result;
}

// *****************************************************************************
// ***   Public: Write   *******************************************************
// *****************************************************************************
Result StHalIic::Write(uint16_t addr, uint8_t* tx_buf_ptr, uint32_t tx_size)
{
  Result result = Result::ERR_NULL_PTR;

  if(tx_buf_ptr != nullptr)
  {
    // Variable for store result from the HAL
    HAL_StatusTypeDef hal_result = HAL_OK;

    // Shift address one bit left - HAL blow away LSB, not MSB.
    addr <<= 1U;

    // Transmit data
    hal_result = HAL_I2C_Master_Transmit(&hi2c, addr, tx_buf_ptr, tx_size, i2c_tx_timeout_ms);

    // Convert operation result to Result
    result = ConvertResult(hal_result);
  }

  return result;
}

// *****************************************************************************
// ***   Public: Read   ********************************************************
// *****************************************************************************
Result StHalIic::Read(uint16_t addr, uint8_t* rx_buf_ptr, uint32_t rx_size)
{
  Result result = Result::ERR_NULL_PTR;

  if(rx_buf_ptr != nullptr)
  {
    // Variable for store result from the HAL
    HAL_StatusTypeDef hal_result = HAL_OK;

    // Shift address one bit left - HAL blow away LSB, not MSB.
    addr <<= 1U;

    // Transmit data
    hal_result = HAL_I2C_Master_Receive(&hi2c, addr, rx_buf_ptr, rx_size, i2c_tx_timeout_ms);

    // Convert operation result to Result
    result = ConvertResult(hal_result);
  }

  return result;
}

// *****************************************************************************
// ***   Public: WriteAsync   **************************************************
// *****************************************************************************
Result StHalIic::WriteAsync(uint16_t addr, uint8_t* tx_buf_ptr, uint32_t tx_size)
{
  Result result = Result::ERR_NOT_IMPLEMENTED;

  // Check DMA handler - if it is nullptr this function not implemented in hardware
  if(hi2c.hdmatx != nullptr)
  {
    // Shift address one bit left - HAL blow away LSB, not MSB.
    addr <<= 1U;
    // Receive data using DMA
    HAL_StatusTypeDef hal_result = HAL_I2C_Master_Transmit_DMA(&hi2c, addr, tx_buf_ptr, tx_size);
    // Convert operation result to Result
    result = ConvertResult(hal_result);
  }

  return result;
}

// *****************************************************************************
// ***   Public: ReadAsync   ***************************************************
// *****************************************************************************
Result StHalIic::ReadAsync(uint16_t addr, uint8_t* rx_buf_ptr, uint32_t rx_size)
{
  Result result = Result::ERR_NOT_IMPLEMENTED;

  // Check DMA handler - if it is nullptr this function not implemented in hardware
  if(hi2c.hdmarx != nullptr)
  {
    // Shift address one bit left - HAL blow away LSB, not MSB.
    addr <<= 1U;
    // Receive data using DMA
    HAL_StatusTypeDef hal_result = HAL_I2C_Master_Receive_DMA(&hi2c, addr, rx_buf_ptr, rx_size);
    // Convert operation result to Result
    result = ConvertResult(hal_result);
  }

  return result;
}

// *****************************************************************************
// ***   Public: Transfer   ****************************************************
// *****************************************************************************
bool StHalIic::IsBusy(void)
{
   return (hi2c.State != HAL_I2C_STATE_READY);
}

// *****************************************************************************
// ***   Private: ConvertResult   **********************************************
// *****************************************************************************
Result StHalIic::ConvertResult(HAL_StatusTypeDef hal_result)
{
  Result result = Result::RESULT_OK;

  // Convert operation result to Result
  switch(hal_result)
  {
    case HAL_OK:
      result = Result::RESULT_OK;
      break;

    case HAL_ERROR:
      result = Result::ERR_I2C_GENERAL;
      break;

    case HAL_BUSY:
      result = Result::ERR_I2C_BUSY;
      break;

    case HAL_TIMEOUT:
      result = Result::ERR_I2C_TIMEOUT;
      break;

    default:
      result = Result::ERR_SPI_UNKNOWN;
      break;
  }

  // Return result
  return result;
}

#endif