GadgetSeed  0.9.6
32f469i-disc_sd.c
[詳解]
1 /** @file
2  @brief SD ドライバ 32F469IDISCOVERY
3 
4  @date 2018.08.18
5  @author Takashi SHUDO
6 */
7 
8 #include "sysconfig.h"
9 #include "tkprintf.h"
10 #include "timer.h"
11 #include "device.h"
12 #include "str.h"
13 #include "interrupt.h"
14 #include "device/sd_ioctl.h"
15 #include "task/syscall.h"
16 
17 #include "stm32469i_discovery_sd.h"
18 
19 #define ENABLE_SD_DMA /// DMA転送を使用する
20 #define SD_TIMEOUT (3*1000)
21 
22 //#define DEBUGKBITS 0x13
23 #include "dkprintf.h"
24 
25 
26 #ifdef ENABLE_SD_DMA
27 extern SD_HandleTypeDef uSdHandle;
28 
29 static struct st_event dma_rx_evt;
30 static struct st_event dma_tx_evt;
31 
32 static int flg_dma_rx_cmp = 0;
33 static int flg_dma_tx_cmp = 0;
34 static int flg_sd_cmp = 0;
35 
36 void BSP_SD_ReadCpltCallback(void)
37 {
38  DKFPRINTF(0x02, "\n");
39 
40  flg_dma_rx_cmp = 1;
41 }
42 
43 void BSP_SD_WriteCpltCallback(void)
44 {
45  DKFPRINTF(0x02, "\n");
46 
47  flg_dma_tx_cmp = 1;
48 }
49 
50 /* DMA2 Stream0 */
51 static void inthdr_sd_dma_rx(unsigned int intnum, void *sp)
52 {
53  DKFPRINTF(0x02, "intnum=%d\n", intnum);
54 
55  HAL_DMA_IRQHandler(uSdHandle.hdmarx);
56 
57  DKFPRINTF(0x02, "end\n");
58 
59  if(flg_sd_cmp != 0) {
60  DKFPRINTF(0x02, "event wakeup dma_rx_evt\n");
61  flg_sd_cmp = 0;
62  event_wakeup_ISR(sp, &dma_rx_evt, 0);
63  }
64 }
65 
66 /* DMA2 Stream5 */
67 static void inthdr_sd_dma_tx(unsigned int intnum, void *sp)
68 {
69  DKFPRINTF(0x02, "intnum=%d\n", intnum);
70 
71  HAL_DMA_IRQHandler(uSdHandle.hdmatx);
72 
73  DKFPRINTF(0x02, "end\n");
74 
75  if(flg_sd_cmp != 0) {
76  DKFPRINTF(0x02, "event wakeup dma_tx_evt\n");
77  flg_sd_cmp = 0;
78  event_wakeup_ISR(sp, &dma_tx_evt, 0);
79  }
80 }
81 
82 static void inthdr_sd(unsigned int intnum, void *sp)
83 {
84  DKFPRINTF(0x02, "intnum=%d\n", intnum);
85 
86  HAL_SD_IRQHandler(&uSdHandle);
87 
88  DKFPRINTF(0x02, "end\n");
89 
90  if(flg_dma_rx_cmp != 0) {
91  flg_dma_rx_cmp = 0;
92  DKFPRINTF(0x02, "event wakeup dma_rx_evt\n");
93  event_wakeup_ISR(sp, &dma_rx_evt, 0);
94  } else {
95  flg_sd_cmp = 1;
96  }
97 
98  if(flg_dma_tx_cmp != 0) {
99  flg_dma_tx_cmp = 0;
100  DKFPRINTF(0x02, "event wakeup dma_tx_evt\n");
101  event_wakeup_ISR(sp, &dma_tx_evt, 0);
102  } else {
103  flg_sd_cmp = 1;
104  }
105 }
106 #endif //ENABLE_SD_DMA
107 
108 static int sd_register(struct st_device *dev, char *param)
109 {
110  unsigned char stat;
111 
112  stat = BSP_SD_Init();
113 
114  if(stat != HAL_OK) {
115  SYSERR_PRINT("SD Initialize error(%d)\n", (int)stat);
116  return -1;
117  }
118 
119 #ifdef ENABLE_SD_DMA
120  //BSP_SD_ITConfig();
121 
122  eventqueue_register_ISR(&dma_rx_evt, "sddmarx", 0, 0, 0);
123  HAL_NVIC_SetPriority(SD_DMAx_Rx_IRQn, 0, 0); // 割り込みプライオリティは最低(0)
124  register_interrupt(IRQ2VECT(SD_DMAx_Rx_IRQn), inthdr_sd_dma_rx);
125 
126  eventqueue_register_ISR(&dma_tx_evt, "sddmatx", 0, 0, 0);
127  HAL_NVIC_SetPriority(SD_DMAx_Tx_IRQn, 0, 0); // 割り込みプライオリティは最低(0)
128  register_interrupt(IRQ2VECT(SD_DMAx_Tx_IRQn), inthdr_sd_dma_tx);
129 
130  HAL_NVIC_SetPriority(SDIO_IRQn, 0, 0); // 割り込みプライオリティは最低(0)
131  register_interrupt(IRQ2VECT(SDIO_IRQn), inthdr_sd);
132 #endif //ENABLE_SD_DMA
133 
134  return 0;
135 }
136 
137 static int sd_unregister(struct st_device *dev)
138 {
139 #ifdef ENABLE_SD_DMA
140  unregister_interrupt(IRQ2VECT(SD_DMAx_Rx_IRQn));
141  unregister_interrupt(IRQ2VECT(SD_DMAx_Tx_IRQn));
142  unregister_interrupt(IRQ2VECT(SDIO_IRQn));
143 #endif //ENABLE_SD_DMA
144 
145  return 0;
146 }
147 
148 static int sd_open(struct st_device *dev)
149 {
150  DKFPRINTF(0x01, "dev=%p\n", dev);
151 
152  return 0;
153 }
154 
155 static int sd_close(struct st_device *dev)
156 {
157  DKFPRINTF(0x01, "dev=%p\n", dev);
158 
159  return 0;
160 }
161 
162 static uint32_t sdbuf[BLOCKSIZE];
163 
164 static int sd_block_read(struct st_device *dev, void *data, unsigned int sector, unsigned int blkcount)
165 {
166  unsigned char res;
167 #ifdef ENABLE_SD_DMA
168  int tout;
169 #endif
170 
171  DKFPRINTF(0x01, "dev=%p, data=%p, sector=%u, blkcount=%u\n", dev, data, sector, blkcount);
172 
173 #ifdef ENABLE_SD_DMA
174  if((unsigned int)data & 0x3) {
175  DKFPRINTF(0x08, "data=%p\n", data);
176  /*
177  4のN倍アドレス以外のメモリアドレスにDMAで書き込みを行うとデータ化けが起きる
178  暫定対策として、DMAではSRAMに転送してからSDRAMにコピーする
179  */
180  int i;
181  for(i=0; i<blkcount; i++) {
182  flg_dma_rx_cmp = 0;
183  flg_sd_cmp = 0;
184  res = BSP_SD_ReadBlocks_DMA((uint32_t *)sdbuf, sector+i, 1);
185  if(res != MSD_OK) {
186  SYSERR_PRINT("BSP_SD_ReadBlocks_DMA(%d)\n", res);
187  goto rd_error;
188  }
189 
190  tout = event_wait(&dma_rx_evt, 0, SD_TIMEOUT);
191  if(tout == 0) {
192  SYSERR_PRINT("event_wait dma_rx_evt timeout(res = %d)\n", res);
193  }
194 
195  res = BSP_SD_GetCardState();
196  if(res == SD_TRANSFER_OK) {
197  memorycopy(data, (const void *)sdbuf, BLOCKSIZE);
198  data += BLOCKSIZE;
199  res = MSD_OK;
200  } else {
201  SYSERR_PRINT("BSP_SD_GetCardState error(%d)\n", res);
202  res = MSD_ERROR;
203  break;
204  }
205  }
206  } else {
207  flg_dma_rx_cmp = 0;
208  flg_sd_cmp = 0;
209 
210  res = BSP_SD_ReadBlocks_DMA((uint32_t *)data, sector, blkcount);
211  if(res != MSD_OK) {
212  SYSERR_PRINT("BSP_SD_ReadBlocks_DMA(%d)\n", res);
213  goto rd_error;
214  }
215 
216  tout = event_wait(&dma_rx_evt, 0, SD_TIMEOUT);
217  if(tout == 0) {
218  SYSERR_PRINT("event_wait dma_rx_evt timeout(res = %d)\n", res);
219  }
220 
221  res = BSP_SD_GetCardState();
222  if(res == SD_TRANSFER_OK) {
223  //
224  } else {
225  SYSERR_PRINT("BSP_SD_GetCardState error(%d)\n", res);
226  res = MSD_ERROR;
227  }
228  }
229 rd_error:
230 #else
231  disable_interrupt(); /// @todo 割込を禁止しないと SD_FLAG_RXOVERR エラーとなる。解析する。
232  res = BSP_SD_ReadBlocks((uint32_t *)data, sector, blkcount, SD_TIMEOUT);
233  enable_interrupt();
234 #endif
235 
236  if(res == MSD_OK) {
237  KXDUMP(0x04, data, blkcount * BLOCKSIZE);
238  return blkcount;
239  } else {
240  SYSERR_PRINT("Block read(data=%p, sector=%u, size=%d) error %u\n", data, sector, blkcount, res);
241  return 0;
242  }
243 }
244 
245 static int sd_block_write(struct st_device *dev, const void *data, unsigned int sector, unsigned int blkcount)
246 {
247  unsigned char res = 0;
248 #ifdef ENABLE_SD_DMA
249  int tout;
250 #endif
251 
252  DKFPRINTF(0x01, "dev=%p, data=%p, sector=%u, blkcount=%u\n", dev, data, sector, blkcount);
253 
254 #ifdef ENABLE_SD_DMA
255  flg_dma_tx_cmp = 0;
256  flg_sd_cmp = 0;
257 
258  res = BSP_SD_WriteBlocks_DMA((uint32_t *)data, sector, blkcount);
259 
260  tout = event_wait(&dma_tx_evt, 0, SD_TIMEOUT);
261  if(tout == 0) {
262  SYSERR_PRINT("event_wait dma_tx_evt timeout(res = %d)\n", res);
263  }
264 
265  tout = get_kernel_time() + SD_TIMEOUT;
266  while(tout > get_kernel_time()) {
267  res = BSP_SD_GetCardState();
268  if(res == SD_TRANSFER_OK) {
269  break;
270  }
271  }
272  if(res != SD_TRANSFER_OK) {
273  SYSERR_PRINT("BSP_SD_GetCardState error(%d)\n", res);
274  }
275 #else
276  if((unsigned int)data & 0x3) {
277  DKFPRINTF(0x10, "data=%p\n", data);
278  int i, j;
279  for(j=0; j<blkcount; j++) {
280  unsigned char *sp = (unsigned char *)data + (j * BLOCKSIZE);
281  unsigned char *dp = (unsigned char *)sdbuf;
282  for(i=0; i<BLOCKSIZE; i++) {
283  *dp = *sp;
284  dp ++;
285  sp ++;
286  }
287  disable_interrupt();
288  res = BSP_SD_WriteBlocks(sdbuf, sector+j, 1, SD_TIMEOUT);
289  enable_interrupt();
290 
291  while(BSP_SD_GetCardState() != SD_TRANSFER_OK) {
292  ;
293  }
294  }
295  } else {
296  disable_interrupt();
297  res = BSP_SD_WriteBlocks((uint32_t *)data, sector, blkcount, SD_TIMEOUT);
298  enable_interrupt();
299 
300  while(BSP_SD_GetCardState() != SD_TRANSFER_OK) {
301  ;
302  }
303  }
304 #endif
305 
306  if(res == SD_TRANSFER_OK) {
307  return blkcount;
308  } else {
309  SYSERR_PRINT("Block write(data=%p, sector=%u, size=%d) error %u\n", data, sector, blkcount, res);
310  return 0;
311  }
312 }
313 
314 static int sd_ioctl(struct st_device *dev, unsigned int com, unsigned int arg, void *param)
315 {
316  HAL_SD_CardInfoTypeDef cardInfo;
317  int rt = 0;
318 
319  DKFPRINTF(0x01, "dev=%p, com=%08x, arg=%08x, param=%p\n", dev, com, arg, param);
320 
321  BSP_SD_GetCardInfo(&cardInfo);
322 
323  DKPRINTF(0x02, "CardType = %u\n", cardInfo.CardType);
324  DKPRINTF(0x02, "CardVersion = %u\n", cardInfo.CardVersion);
325  DKPRINTF(0x02, "Class = %u\n", cardInfo.Class);
326  DKPRINTF(0x02, "RelCardAdd = %u\n", cardInfo.RelCardAdd);
327  DKPRINTF(0x02, "BlockNbr = %u\n", cardInfo.BlockNbr);
328  DKPRINTF(0x02, "BlockSize = %u\n", cardInfo.BlockSize);
329  DKPRINTF(0x02, "LogBlockNbr = %u\n", cardInfo.LogBlockNbr);
330  DKPRINTF(0x02, "LogBlockSize = %u\n", cardInfo.LogBlockSize);
331 
332  switch(com) {
334  {
335 #if FF_MAX_SS != FF_MIN_SS
336  rt = (int)cardInfo.BlockNbr;
337 #else
338  rt = (int)cardInfo.LogBlockNbr;
339 #endif
340  }
341  break;
342 
344  {
345 #if FF_MAX_SS != FF_MIN_SS
346  rt = (int)cardInfo.BlockSize;
347 #else
348  rt = (int)cardInfo.LogBlockSize;
349 #endif
350  }
351  break;
352 
354  {
355  rt = (int)cardInfo.BlockSize;
356  }
357  break;
358 
359  default:
360  SYSERR_PRINT("Unknow command %08lX arg %08lX\n", com, arg);
361  return 0;
362  }
363 
364  return rt;
365 }
366 
367 static int sd_sync(struct st_device *dev)
368 {
369  return 0;
370 }
371 
372 static int sd_suspend(struct st_device *dev)
373 {
374  int rt = 0;
375 
376  return rt;
377 }
378 
379 static int sd_resume(struct st_device *dev)
380 {
381  int rt = 0;
382 
383  return rt;
384 }
385 
386 
387 const struct st_device sd_device = {
389  .explan = "32F469IDISCOVERY SD Card Storage",
390  .register_dev = sd_register,
391  .unregister_dev = sd_unregister,
392  .open = sd_open,
393  .close = sd_close,
394  .block_read = sd_block_read,
395  .block_write = sd_block_write,
396  .ioctl = sd_ioctl,
397  .sync = sd_sync,
398  .suspend = sd_suspend,
399  .resume = sd_resume,
400 };
#define IOCMD_SD_GET_SECTOR_COUNT
セクタ数を取得する
Definition: sd_ioctl.h:17
#define IOCMD_SD_GET_BLOCK_SIZE
消去ブロックサイズを取得する
Definition: sd_ioctl.h:19
文字列処理
#define DEF_DEV_NAME_SD
標準ストレージデバイス名(MMC,SD等)
Definition: sd_ioctl.h:15
カーネルタイマ
void eventqueue_register_ISR(struct st_event *evtque, const char *name, void *args, unsigned int arg_size, int arg_count)
イベントキューを登録する
Definition: event.c:36
void event_wakeup_ISR(void *sp, struct st_event *evtque, void *arg)
イベントキューにイベントを登録し、イベント待ちタスクを起動する
Definition: task.c:923
#define IOCMD_SD_GET_SECTOR_SIZE
1セクタサイズを取得する
Definition: sd_ioctl.h:18
カーネル用機能限定printf
イベント
Definition: event.h:15
void * memorycopy(void *dest, const void *src, unsigned int count)
メモリコピー
Definition: str.c:760
システムコール
割り込みハンドラ
ストレージデバイスドライバ ioctl 用マクロ定義
unsigned long long get_kernel_time(void)
カーネル時間を取得する
Definition: timer.c:192
デバイスドライバAPI
デバイスドライバ構造体
Definition: device.h:25
カーネル、ドライバ(非タスク)デバッグ用マクロ
char name[MAX_DEVNAMELRN]
デバイス名文字列
Definition: device.h:26
int event_wait(struct st_event *evtque, void *argp, unsigned int timeout)
タスクをイベント待ち状態にする
Definition: syscall_api.c:364