source: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_serial.c@ 458

Last change on this file since 458 was 458, checked in by coas-nagasima, 4 years ago

SPIとSerial、KPUの動作を改善

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 13.6 KB
Line 
1/*
2 * TOPPERS/ASP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Advanced Standard Profile Kernel
5 *
6 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7 * Toyohashi Univ. of Technology, JAPAN
8 * Copyright (C) 2005-2011 by Embedded and Real-Time Systems Laboratory
9 * Graduate School of Information Science, Nagoya Univ., JAPAN
10 * Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
11 *
12 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
13 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
14 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
15 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
16 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
17 * スコード中に含まれていること.
18 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
19 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
20 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
21 * の無保証規定を掲載すること.
22 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
23 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
24 * と.
25 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
26 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
27 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
28 * 報告すること.
29 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
30 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
31 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
32 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
33 * 免責すること.
34 *
35 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
36 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
37 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
38 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
39 * の責任を負わない.
40 *
41 * @(#) $Id$
42 */
43
44/*
45 * シリアルI/Oデバイス(SIO)ドライバ(K210用)
46 */
47
48#include <kernel.h>
49#include <t_syslog.h>
50#include "target_stddef.h"
51#include "target_serial.h"
52#include "target_syssvc.h"
53
54/*
55 * SIL関数のマクロ定義
56 */
57#define sil_orw_mem(a, b) sil_wrw_mem((a), sil_rew_mem(a) | (b))
58#define sil_andw_mem(a, b) sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
59
60/*
61 * レジスタ設定値
62 */
63#define INDEX_PORT(x) ((x)-1)
64#define GET_SIOPCB(x) (&siopcb_table[INDEX_PORT(x)])
65
66#define __UART_BRATE_CONST 16
67
68#ifndef COM0
69#define COM0 0
70#endif
71
72/*
73 * ビット長パラメータ
74 */
75#define UART_WordLength_5B 0x00000000
76#define UART_WordLength_6B 0x00000001
77#define UART_WordLength_7B 0x00000002
78#define UART_WordLength_8b 0x00000003
79
80/*
81 * ストップビットパラメータ
82 */
83#define UART_StopBits_1 0x00000000
84#define UART_StopBits_1_5 UART_LCR_STB
85
86/*
87 * パリティパラメータ
88 */
89#define UART_Parity_No 0x00000000
90#define UART_Parity_Odd UART_LCR_PARITY
91#define UART_Parity_Even (UART_LCR_PARITY | UART_LCR_PEVEN)
92
93/*
94 * 送信FIFO
95 */
96#define UART_SEND_FIFO0 0
97#define UART_SEND_FIFO2 1
98#define UART_SEND_FIFO4 2
99#define UART_SEND_FIFO8 3
100
101/*
102 * 受信FIFO
103 */
104#define UART_RECEIVE_FIFO1 0
105#define UART_RECEIVE_FIFO4 1
106#define UART_RECEIVE_FIFO8 2
107#define UART_RECEIVE_FIFO14 3
108
109/*
110 * シリアルI/Oポート初期化ブロックの定義
111 */
112typedef struct sio_port_initialization_block {
113 uint64_t base;
114 INTNO intno_usart;
115 uint32_t clk;
116 uint8_t txfunc;
117 uint8_t rxfunc;
118 uint8_t com;
119} SIOPINIB;
120
121/*
122 * シリアルI/Oポート管理ブロックの定義
123 */
124struct sio_port_control_block {
125 const SIOPINIB *p_siopinib; /* シリアルI/Oポート初期化ブロック */
126 intptr_t exinf; /* 拡張情報 */
127 bool_t opnflg; /* オープン済みフラグ */
128};
129
130/*
131 * シリアルI/Oポート初期化ブロック
132 */
133const SIOPINIB siopinib_table[TNUM_SIOP] = {
134 {(uint32_t)TADR_UART1_BASE, (INTNO)IRQ_VECTOR_UART1, SYSCTL_CLK_EN_PERI_UART1_CLK_EN, FUNC_UART1_TX, FUNC_UART1_RX, COM0},
135#if TNUM_SIOP >= 2
136 {(uint32_t)TADR_UART3_BASE, (INTNO)IRQ_VECTOR_UART3, SYSCTL_CLK_EN_PERI_UART3_CLK_EN, FUNC_UART3_TX, FUNC_UART3_RX, COM0 ^ 1}
137#endif
138};
139
140/*
141 * FPIOA番号テーブル
142 */
143static uint8_t uartpin[2][2] = {
144 {5, 4}, /* com0 tx, rx */
145 {6, 7}, /* com1 tx, rx */
146};
147
148/*
149 * シリアルI/Oポート管理ブロックのエリア
150 */
151SIOPCB siopcb_table[TNUM_SIOP];
152
153/*
154 * シリアルI/OポートIDから管理ブロックを取り出すためのマクロ
155 */
156#define INDEX_SIOP(siopid) ((uint_t)((siopid)-1))
157#define get_siopcb(siopid) (&(siopcb_table[INDEX_SIOP(siopid)]))
158
159extern uint32_t get_pll_clock(uint8_t no);
160extern ER fpioa_set_function(int number, uint8_t function);
161
162/*
163 * PLL0クロックを取得
164 */
165static uint32_t
166get_clock_aclk(void)
167{
168 uint32_t clk_sel0 = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE + TOFF_CLK_SEL0));
169 uint32_t select = clk_sel0 & SYSCTL_CLK_SEL0_ACLK_SEL;
170 uint32_t source = 0;
171
172 if (select == 0)
173 source = SYSCTRL_CLOCK_FREQ_IN0;
174 else if (select == 1)
175 source = get_pll_clock(0) / (2UL << ((clk_sel0 & SYSCTL_CLK_SEL0_ACLK_SDIVISER) >> 1));
176 return source;
177}
178
179void put_hex(char a, int val)
180{
181 int i, j;
182 target_fput_log(a);
183 target_fput_log(' ');
184 for (i = 28; i >= 0; i -= 4) {
185 j = (val >> i) & 0xf;
186 if (j > 9)
187 j += ('A' - 10);
188 else
189 j += '0';
190 target_fput_log(j);
191 }
192 target_fput_log('\n');
193}
194
195/*
196 * SIOドライバの初期化
197 */
198void
199sio_initialize(intptr_t exinf)
200{
201 SIOPCB *p_siopcb;
202 uint_t i;
203
204 /*
205 * シリアルI/Oポート管理ブロックの初期化
206 */
207 for (p_siopcb = siopcb_table, i = 0; i < TNUM_SIOP; p_siopcb++, i++) {
208 p_siopcb->p_siopinib = &(siopinib_table[i]);
209 p_siopcb->opnflg = false;
210 }
211}
212
213/*
214 * シリアルI/Oポートのオープン
215 */
216SIOPCB *
217sio_opn_por(ID siopid, intptr_t exinf)
218{
219 SIOPCB *p_siopcb;
220 const SIOPINIB *p_siopinib;
221 bool_t opnflg;
222 ER ercd;
223 unsigned long base;
224 uint32_t divisor, threshold, tmp;
225 uint8_t dlh, dll, dlf;
226
227 p_siopcb = get_siopcb(siopid);
228 p_siopinib = p_siopcb->p_siopinib;
229
230 /*
231 * オープンしたポートがあるかをopnflgに読んでおく.
232 */
233 opnflg = p_siopcb->opnflg;
234
235 p_siopcb->exinf = exinf;
236 base = p_siopinib->base;
237 if (base == 0) /* no uart port */
238 goto sio_opn_exit;
239
240 /*
241 * ハードウェアの初期化
242 */
243 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE + TOFF_SYSCTL_CLK_EN_PERI), p_siopinib->clk);
244
245 sil_wrw_mem((uint32_t *)(base + TOFF_UART_IER), 0x00000000);
246 sil_dly_nse(10000);
247
248 threshold = (sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE + TOFF_CLK_SEL0)) & SYSCTL_CLK_SEL0_APB0_CLK_SEL) >> 3;
249 divisor = (get_clock_aclk() / (threshold + 1)) / BPS_SETTING;
250 dlh = divisor >> 12;
251 dll = (divisor - (dlh << 12)) / __UART_BRATE_CONST;
252 dlf = divisor - (dlh << 12) - dll * __UART_BRATE_CONST;
253
254 /* Set UART registers */
255 sil_orw_mem((uint32_t *)(base + TOFF_UART_LCR), UART_LCR_DMD);
256 sil_wrw_mem((uint32_t *)(base + TOFF_UART_DLH), dlh);
257 sil_wrw_mem((uint32_t *)(base + TOFF_UART_DLL), dll);
258 sil_wrw_mem((uint32_t *)(base + TOFF_UART_DLF), dlf);
259 sil_wrw_mem((uint32_t *)(base + TOFF_UART_LCR), 0x00);
260 sil_wrw_mem((uint32_t *)(base + TOFF_UART_LCR), (UART_WordLength_8b | UART_StopBits_1 | UART_Parity_No));
261 sil_andw_mem((uint32_t *)(base + TOFF_UART_LCR), UART_LCR_DMD);
262 sil_orw_mem((uint32_t *)(base + TOFF_UART_IER), UART_IER_THRE);
263 sil_wrw_mem((uint32_t *)(base + TOFF_UART_FCR),
264 (UART_RECEIVE_FIFO14 << 6 | UART_SEND_FIFO8 << 4 /*| 0x1 << 3 DMA mode?*/ | 0x1 /*FIFO enable?*/));
265 sil_andw_mem((uint32_t *)(base + TOFF_UART_MCR), (1 << 6) | 3);
266 sil_wrw_mem((uint32_t *)(base + TOFF_UART_TCR), 0x00);
267
268 fpioa_set_function(uartpin[p_siopinib->com][1], p_siopinib->rxfunc);
269 fpioa_set_function(uartpin[p_siopinib->com][0], p_siopinib->txfunc);
270 sil_orw_mem((uint32_t *)(base + TOFF_UART_IER), UART_IER_RIE);
271 tmp = sil_rew_mem((uint32_t *)(p_siopcb->p_siopinib->base + TOFF_UART_RBR));
272 p_siopcb->opnflg = true;
273 (void)(tmp);
274
275 /*
276 * シリアルI/O割込みのマスクを解除する.
277 */
278 if (!opnflg) {
279 ercd = ena_int(p_siopinib->intno_usart);
280 assert(ercd == E_OK);
281 }
282 sil_dly_nse(20000);
283
284sio_opn_exit:;
285 return (p_siopcb);
286}
287
288/*
289 * シリアルI/Oポートのクローズ
290 */
291void
292sio_cls_por(SIOPCB *p_siopcb)
293{
294 const SIOPINIB *p_siopinib;
295
296 p_siopinib = p_siopcb->p_siopinib;
297 /*
298 * シリアルI/O割込みをマスクする.
299 */
300 if ((p_siopcb->opnflg)) {
301 dis_int(p_siopinib->intno_usart);
302 }
303
304 /*
305 * シリアル停止
306 */
307 sil_wrw_mem((uint32_t *)(p_siopinib->base + TOFF_UART_IER), 0x00000000);
308 sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE + TOFF_SYSCTL_CLK_EN_PERI), p_siopinib->clk);
309 p_siopcb->opnflg = false;
310}
311
312/*
313 * SIOの割込みサービスルーチン
314 */
315void
316sio_isr(intptr_t exinf)
317{
318 SIOPCB *p_siopcb = get_siopcb(exinf);
319 unsigned long base = p_siopcb->p_siopinib->base;
320 uint32_t tmp;
321
322 for (;;) {
323 uint32_t ip = sil_rew_mem((uint32_t *)(base + TOFF_UART_IIR)) & 0x0F;
324
325 if (ip == 1) {
326 break;
327 }
328 else if (ip == UART_IIR_RECEIVE || ip == UART_IIR_CTIMEOUT) {
329 sio_irdy_rcv(p_siopcb->exinf);
330 }
331 else if (ip == UART_IIR_SEND) {
332 sio_irdy_snd(p_siopcb->exinf);
333 }
334 else {
335 tmp = sil_rew_mem((uint32_t *)(base + TOFF_UART_LSR));
336 tmp = sil_rew_mem((uint32_t *)(base + TOFF_UART_USR));
337 tmp = sil_rew_mem((uint32_t *)(base + TOFF_UART_MSR));
338 }
339 (void)(tmp);
340 }
341}
342
343/*
344 * シリアルI/Oポートへの文字送信
345 */
346Inline bool_t
347sio_putready(SIOPCB *p_siopcb)
348{
349 uint32_t lsr = sil_rew_mem((uint32_t *)(p_siopcb->p_siopinib->base + TOFF_UART_LSR));
350
351 if ((lsr & UART_LSR_TFL) == 0) {
352 return 1;
353 }
354 return 0;
355}
356
357bool_t
358sio_snd_chr(SIOPCB *p_siopcb, char c)
359{
360 if (sio_putready(p_siopcb)) {
361 sil_wrw_mem((uint32_t *)(p_siopcb->p_siopinib->base + TOFF_UART_THR), (uint32_t)c);
362 return true;
363 }
364 return false;
365}
366
367/*
368 * シリアルI/Oポートからの文字受信
369 */
370int_t
371sio_rcv_chr(SIOPCB *p_siopcb)
372{
373 int_t c = -1;
374
375 if ((sil_rew_mem((uint32_t *)(p_siopcb->p_siopinib->base + TOFF_UART_LSR)) & UART_LSR_RFL) != 0) {
376 c = sil_rew_mem((uint32_t *)(p_siopcb->p_siopinib->base + TOFF_UART_RBR)) & 0xFF;
377 }
378 return c;
379}
380
381/*
382 * シリアルI/Oポートからのコールバックの許可
383 */
384void
385sio_ena_cbr(SIOPCB *p_siopcb, uint_t cbrtn)
386{
387 switch (cbrtn) {
388 case SIO_RDY_SND:
389 sil_orw_mem((uint32_t *)(p_siopcb->p_siopinib->base + TOFF_UART_IER), UART_IER_TIE);
390 break;
391 case SIO_RDY_RCV:
392 sil_orw_mem((uint32_t *)(p_siopcb->p_siopinib->base + TOFF_UART_IER), UART_IER_RIE);
393 break;
394 }
395}
396
397/*
398 * シリアルI/Oポートからのコールバックの禁止
399 */
400void
401sio_dis_cbr(SIOPCB *p_siopcb, uint_t cbrtn)
402{
403 switch (cbrtn) {
404 case SIO_RDY_SND:
405 sil_andw_mem((uint32_t *)(p_siopcb->p_siopinib->base + TOFF_UART_IER), UART_IER_TIE);
406 break;
407 case SIO_RDY_RCV:
408 sil_andw_mem((uint32_t *)(p_siopcb->p_siopinib->base + TOFF_UART_IER), UART_IER_RIE);
409 break;
410 }
411}
412
413/*
414 * 1文字出力(ポーリングでの出力)
415 */
416void sio_pol_snd_chr(int8_t c, ID siopid)
417{
418 unsigned long base = siopinib_table[INDEX_PORT(siopid)].base;
419
420 sil_wrw_mem((uint32_t *)(base + TOFF_UART_THR), (uint32_t)c);
421 while (0 != (sil_rew_mem((uint32_t *)(base + TOFF_UART_LSR)) & UART_LSR_TFL))
422 ;
423
424 /*
425 * 出力が完全に終わるまで待つ
426 */
427 volatile int n = SYS_CLOCK / BPS_SETTING;
428 while (n--)
429 ;
430}
431
432/*
433 * ターゲットのシリアル初期化
434 */
435void target_uart_init(ID siopid)
436{
437 const SIOPINIB *p_siopinib;
438 unsigned long base;
439 uint32_t divisor, threshold;
440 uint8_t dlh, dll, dlf;
441
442 p_siopinib = &siopinib_table[INDEX_PORT(siopid)];
443 base = p_siopinib->base;
444
445 /*
446 * ハードウェアの初期化
447 */
448 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE + TOFF_SYSCTL_CLK_EN_PERI), p_siopinib->clk);
449
450 threshold = (sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE + TOFF_CLK_SEL0)) & SYSCTL_CLK_SEL0_APB0_CLK_SEL) >> 3;
451 divisor = (get_clock_aclk() / (threshold + 1)) / BPS_SETTING;
452 dlh = divisor >> 12;
453 dll = (divisor - (dlh << 12)) / __UART_BRATE_CONST;
454 dlf = divisor - (dlh << 12) - dll * __UART_BRATE_CONST;
455
456 /* Set UART registers */
457 sil_orw_mem((uint32_t *)(base + TOFF_UART_LCR), UART_LCR_DMD);
458 sil_wrw_mem((uint32_t *)(base + TOFF_UART_DLH), dlh);
459 sil_wrw_mem((uint32_t *)(base + TOFF_UART_DLL), dll);
460 sil_wrw_mem((uint32_t *)(base + TOFF_UART_DLF), dlf);
461 sil_wrw_mem((uint32_t *)(base + TOFF_UART_LCR), 0x00);
462 sil_wrw_mem((uint32_t *)(base + TOFF_UART_LCR), (UART_WordLength_8b | UART_StopBits_1 | UART_Parity_No));
463 sil_andw_mem((uint32_t *)(base + TOFF_UART_LCR), UART_LCR_DMD);
464 sil_orw_mem((uint32_t *)(base + TOFF_UART_IER), UART_IER_THRE);
465 sil_wrw_mem((uint32_t *)(base + TOFF_UART_FCR),
466 (UART_RECEIVE_FIFO14 << 6 | UART_SEND_FIFO8 << 4 /*| 0x1 << 3 DMA mode?*/ | 0x1 /*FIFO enable?*/));
467 sil_andw_mem((uint32_t *)(base + TOFF_UART_MCR), (1 << 6) | 3);
468 sil_wrw_mem((uint32_t *)(base + TOFF_UART_TCR), 0x00);
469
470 fpioa_set_function(uartpin[p_siopinib->com][1], p_siopinib->rxfunc);
471 fpioa_set_function(uartpin[p_siopinib->com][0], p_siopinib->txfunc);
472 sil_dly_nse(10000);
473}
Note: See TracBrowser for help on using the repository browser.