GadgetSeed  0.9.6
i2c.c
[詳解]
1 /** @file
2  @brief STM32F7 I2Cドライバ
3 
4  @date 2017.01.20
5  @author Takashi SHUDO
6 
7  PB8 - I2C1_SCL
8  PB9 - I2C1_SDA
9 */
10 
11 #include "sysconfig.h"
12 #include "device.h"
13 #include "interrupt.h"
14 #include "tkprintf.h"
15 #include "device/i2c_ioctl.h"
16 #include "task/event.h"
17 #include "task/mutex.h"
18 #include "task/syscall.h"
19 
20 #include "stm32f7xx_hal.h"
21 #include "stm32f769i_discovery.h"
22 #include "stm32f769i_discovery_ts.h"
23 
24 //#define DEBUGKBITS 0x03
25 #include "dkprintf.h"
26 
27 
28 typedef struct st_i2c_data {
29  struct st_i2c_config config;
30 
31  I2C_HandleTypeDef hi2c;
32 
33  unsigned short seek_addr;
34 } st_i2c_data;
35 
36 static st_i2c_data i2c_prv_data[2];
37 static struct st_mutex i2c_mutex[2];
38 
39 void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
40 {
41 
42  GPIO_InitTypeDef GPIO_InitStruct;
43  if(hi2c->Instance==I2C1) {
44  GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
45  GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
46  GPIO_InitStruct.Pull = GPIO_PULLUP;
47  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
48  GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
49  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
50  __HAL_RCC_I2C1_CLK_ENABLE();
51  } else if(hi2c->Instance==I2C4) {
52  GPIO_InitStruct.Pin = GPIO_PIN_7;
53  GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
54  GPIO_InitStruct.Pull = GPIO_PULLUP;
55  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
56  GPIO_InitStruct.Alternate = GPIO_AF11_I2C4;
57  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
58 
59  GPIO_InitStruct.Pin = GPIO_PIN_12;
60  GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
61  GPIO_InitStruct.Pull = GPIO_PULLUP;
62  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
63  GPIO_InitStruct.Alternate = GPIO_AF4_I2C4;
64  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
65  __HAL_RCC_I2C4_CLK_ENABLE();
66  }
67 }
68 
69 
70 /*
71  *
72  */
73 extern const struct st_device i2c1_device;
74 extern const struct st_device i2c4_device;
75 
76 static void init_i2c(struct st_device *dev)
77 {
78  st_i2c_data *i2c_data = (dev->private_data);
79  I2C_HandleTypeDef *hi2c = &(i2c_data->hi2c);
80 
81  __HAL_RCC_GPIOB_CLK_ENABLE();
82  __HAL_RCC_GPIOD_CLK_ENABLE();
83 
84  if(dev == &i2c1_device) {
85  hi2c->Instance = I2C1;
86  } else if(dev == &i2c4_device) {
87  hi2c->Instance = I2C4;
88  }
89 
90  // hi2c->Init.Timing = DISCOVERY_I2Cx_TIMING;
91  hi2c->Init.Timing = 0x00C0EAFF;
92  hi2c->Init.OwnAddress1 = 0;
93  hi2c->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
94  hi2c->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
95  hi2c->Init.OwnAddress2 = 0;
96  hi2c->Init.OwnAddress2Masks = I2C_OA2_NOMASK;
97  hi2c->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
98  hi2c->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
99  if(HAL_I2C_Init(hi2c) != HAL_OK) {
100  SYSERR_PRINT("I2C Initialize error(%s)\n", dev->name);
101  }
102 #if 1
103  if(HAL_I2CEx_ConfigAnalogFilter(hi2c, I2C_ANALOGFILTER_ENABLE) != HAL_OK) {
104  SYSERR_PRINT("I2C Config error(%s)\n", dev->name);
105  }
106 #endif
107 }
108 
109 static int i2c_register(struct st_device *dev, char *param)
110 {
111  st_i2c_data *i2c_data = (dev->private_data);
112 
113  i2c_data->config.speed = 100;
114  i2c_data->config.address_mode = I2C_ADDR_MODE_7BIT;
115  i2c_data->config.slave_addr = 0x00;
116  i2c_data->config.mem_addr_size = I2C_MEMADD_SIZE_8BIT;
117  i2c_data->seek_addr = 0;
118 
119  init_i2c(dev);
120 
121  return 0;
122 }
123 
124 static int i2c_open(struct st_device *dev)
125 {
126  return 0;
127 }
128 
129 static int i2c_close(struct st_device *dev)
130 {
131  return 0;
132 }
133 
134 static int i2c_read(struct st_device *dev, void *data, unsigned int size)
135 {
136  st_i2c_data *i2c_data = (dev->private_data);
137  I2C_HandleTypeDef *hi2c = &(i2c_data->hi2c);
138  unsigned short slave_addr = i2c_data->config.slave_addr;
139  unsigned short i2c_memadd_size = I2C_MEMADD_SIZE_8BIT;
140  HAL_StatusTypeDef rtn = 0;
141 
142  DKFPRINTF(0x01, "size = %ld\n", size);
143 
144  switch(i2c_data->config.mem_addr_size) {
146  i2c_memadd_size = I2C_MEMADD_SIZE_8BIT;
147  break;
149  i2c_memadd_size = I2C_MEMADD_SIZE_16BIT;
150  break;
151  default:
152  break;
153  }
154 
155  DKPRINTF(0x01, "I2C READ ADDRESS %08X\n", (unsigned int)i2c_data->seek_addr);
156 
157  rtn = HAL_I2C_Mem_Read(hi2c,
158  (slave_addr << 1),
159  i2c_data->seek_addr,
160  i2c_memadd_size,
161  data, size,
162  10/* tick */);
163 
164  if(rtn == HAL_OK) {
165  i2c_data->seek_addr += size;
166  return size;
167  } else {
168  return -1;
169  }
170 }
171 
172 static int i2c_write(struct st_device *dev, const void *data, unsigned int size)
173 {
174  st_i2c_data *i2c_data = (dev->private_data);
175  I2C_HandleTypeDef *hi2c = &(i2c_data->hi2c);
176  unsigned short slave_addr = i2c_data->config.slave_addr;
177  unsigned short i2c_memadd_size = I2C_MEMADD_SIZE_8BIT;
178  HAL_StatusTypeDef rtn = 0;
179 
180  DKFPRINTF(0x01, "size = %d\n", size);
181 
182  switch(i2c_data->config.mem_addr_size) {
184  i2c_memadd_size = I2C_MEMADD_SIZE_8BIT;
185  break;
187  i2c_memadd_size = I2C_MEMADD_SIZE_16BIT;
188  break;
189  default:
190  break;
191  }
192 
193  DKPRINTF(0x01, "I2C WRITE ADDRESS %08X\n", (unsigned int)i2c_data->seek_addr);
194 
195  rtn = HAL_I2C_Mem_Write(hi2c,
196  (slave_addr << 1),
197  i2c_data->seek_addr,
198  i2c_memadd_size,
199  (unsigned char *)data, size,
200  10/* tick */);
201 
202  if(rtn == HAL_OK) {
203  i2c_data->seek_addr += size;
204  return size;
205  } else {
206  return -1;
207  }
208 }
209 
210 static int i2c_set_speed(I2C_TypeDef *i2cx, int speed)
211 {
212  return 0;
213 }
214 
215 static int i2c_ioctl(struct st_device *dev, unsigned int com, unsigned int arg, void *param)
216 {
217  st_i2c_data *i2c_data = (dev->private_data);
218  I2C_TypeDef *i2cx = i2c_data->hi2c.Instance;
219  int rtn = 0;
220 
221  switch(com) {
222  case IOCMD_I2C_SPEED:
223  rtn = i2c_set_speed(i2cx, arg);
224  break;
225 
227  {
228  i2c_data->config.slave_addr = arg;
229  }
230  break;
231 
233  {
234  DKPRINTF(0x01, "I2C IOCTL Memory Address Size %dbit\n",
235  (arg == I2C_MEM_ADDR_SIZE_16BIT) ? 16 : 8);
236  i2c_data->config.mem_addr_size = arg;
237  }
238  break;
239 
240  case IOCMD_I2C_SETCONFIG:
241  {
242  struct st_i2c_config *conf = (struct st_i2c_config *)arg;
243 
244  i2c_data->config.speed = conf->speed;
245  i2c_data->config.address_mode = conf->address_mode;
246  i2c_data->config.slave_addr = conf->slave_addr;
247  i2c_data->config.mem_addr_size = conf->mem_addr_size;
248  }
249  break;
250 
251  default:
252  SYSERR_PRINT("Unknown ioctl(%08lX)\n", com);
253  rtn = -1;
254  break;
255  }
256 
257  return rtn;
258 }
259 
260 static int i2c_seek(struct st_device *dev, int offset, int whence)
261 {
262  st_i2c_data *i2c_data = (dev->private_data);
263 
264  switch(whence) {
265  case SEEK_SET:
266  i2c_data->seek_addr = offset;
267  break;
268 
269  case SEEK_CUR:
270  i2c_data->seek_addr += offset;
271  break;
272 
273  case SEEK_END:
274  default:
275  return -1;
276  }
277 
278  return i2c_data->seek_addr;
279 }
280 
281 static int i2c_suspend(struct st_device *dev)
282 {
283  return 0;
284 }
285 
286 static int i2c_resume(struct st_device *dev)
287 {
288  init_i2c(dev);
289 
290  return 0;
291 }
292 
293 const struct st_device i2c1_device = {
295  .explan = "STM32F7 I2C1 Master",
296  .private_data = (void *)&i2c_prv_data[0],
297  .register_dev = i2c_register,
298  .mutex = &i2c_mutex[0],
299  .open = i2c_open,
300  .close = i2c_close,
301  .read = i2c_read,
302  .write = i2c_write,
303  .ioctl = i2c_ioctl,
304  .seek = i2c_seek,
305  .suspend = i2c_suspend,
306  .resume = i2c_resume,
307 };
308 
309 const struct st_device i2c4_device = {
310  .name = DEF_DEV_NAME_I2C "1",
311  .explan = "STM32F7 I2C4 Master",
312  .private_data = (void *)&i2c_prv_data[1],
313  .mutex = &i2c_mutex[1],
314  .register_dev = i2c_register,
315  .open = i2c_open,
316  .close = i2c_close,
317  .read = i2c_read,
318  .write = i2c_write,
319  .ioctl = i2c_ioctl,
320  .seek = i2c_seek,
321  .suspend = i2c_suspend,
322  .resume = i2c_resume,
323 };
I2Cコンフィグデータ
Definition: i2c_ioctl.h:17
#define IOCMD_I2C_MEMADDRSIZE
Memory Address Size 8bit or 16bit etc
Definition: i2c_ioctl.h:36
struct st_mutex * mutex
デバイス排他アクセス用MUTEX
Definition: device.h:30
void * private_data
ドライバ固有データポインタ
Definition: device.h:29
#define IOCMD_I2C_SPEED
com : 通信速度を設定する, arg : 通信速度(bps)
Definition: i2c_ioctl.h:32
#define I2C_ADDR_MODE_7BIT
I2C 7ビットアドレスモード
Definition: i2c_ioctl.h:20
#define IOCMD_I2C_SETCONFIG
Device Access configration
Definition: i2c_ioctl.h:37
#define I2C_MEM_ADDR_SIZE_16BIT
I2Cスレーブデバイスメモリアドレスサイズは16ビット
Definition: i2c_ioctl.h:27
int suspend(void)
全デバイスを休止状態にする
Definition: device.c:634
#define I2C_MEM_ADDR_SIZE_8BIT
I2Cスレーブデバイスメモリアドレスサイズは8ビット
Definition: i2c_ioctl.h:26
カーネル用機能限定printf
int speed
ビットレート(Kbps)
Definition: i2c_ioctl.h:18
MUTEX
Definition: mutex.h:13
#define IOCMD_I2C_SLAVE_ADDR7
Set Save 7bit Address
Definition: i2c_ioctl.h:33
システムコール
割り込みハンドラ
MUTEX制御
#define DEF_DEV_NAME_I2C
標準I2Cコントローラデバイス名
Definition: i2c_ioctl.h:15
#define SEEK_SET
設定
Definition: device.h:21
int mem_addr_size
I2Cスレーブデバイスメモリアドレスサイズ
Definition: i2c_ioctl.h:28
イベント待ちタスクキューの操作
int resume(void)
全デバイスを活性化する
Definition: device.c:655
デバイスドライバAPI
デバイスドライバ構造体
Definition: device.h:25
I2Cドライバ ioctl 用マクロ定義
カーネル、ドライバ(非タスク)デバッグ用マクロ
int address_mode
未使用(予約)
Definition: i2c_ioctl.h:22
#define SEEK_END
ファイルサイズに加算
Definition: device.h:23
char name[MAX_DEVNAMELRN]
デバイス名文字列
Definition: device.h:26
unsigned int slave_addr
I2Cスレーブデバイスアドレス
Definition: i2c_ioctl.h:24
#define SEEK_CUR
現在値に加算
Definition: device.h:22