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

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

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 13.2 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
179
180void put_hex(char a, int val)
181{
182 int i, j;
183 target_fput_log(a);
184 target_fput_log(' ');
185 for(i = 28 ; i >= 0 ; i-= 4){
186 j = (val >> i) & 0xf;;
187 if(j > 9)
188 j += ('A'-10);
189 else
190 j += '0';
191 target_fput_log(j);
192 }
193 target_fput_log('\n');
194}
195
196/*
197 * SIOドライバの初期化
198 */
199void
200sio_initialize(intptr_t exinf)
201{
202 SIOPCB *p_siopcb;
203 uint_t i;
204
205 /*
206 * シリアルI/Oポート管理ブロックの初期化
207 */
208 for (p_siopcb = siopcb_table, i = 0; i < TNUM_SIOP; p_siopcb++, i++) {
209 p_siopcb->p_siopinib = &(siopinib_table[i]);
210 p_siopcb->opnflg = false;
211 }
212}
213
214
215/*
216 * シリアルI/Oポートのオープン
217 */
218SIOPCB *
219sio_opn_por(ID siopid, intptr_t exinf)
220{
221 SIOPCB *p_siopcb;
222 const SIOPINIB *p_siopinib;
223 bool_t opnflg;
224 ER ercd;
225 unsigned long base;
226 uint32_t divisor, threshold, tmp;
227 uint8_t dlh, dll, dlf;
228
229 p_siopcb = get_siopcb(siopid);
230 p_siopinib = p_siopcb->p_siopinib;
231
232 /*
233 * オープンしたポートがあるかをopnflgに読んでおく.
234 */
235 opnflg = p_siopcb->opnflg;
236
237 p_siopcb->exinf = exinf;
238 base = p_siopinib->base;
239 if(base == 0) /* no uart port */
240 goto sio_opn_exit;
241
242 /*
243 * ハードウェアの初期化
244 */
245 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), p_siopinib->clk);
246
247 sil_wrw_mem((uint32_t *)(base+TOFF_UART_IER), 0x00000000);
248 sil_dly_nse(10000);
249
250 threshold = (sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_CLK_SEL0)) & SYSCTL_CLK_SEL0_APB0_CLK_SEL) >> 3;
251 divisor = (get_clock_aclk() / (threshold+1)) / BPS_SETTING;
252 dlh = divisor >> 12;
253 dll = (divisor - (dlh << 12)) / __UART_BRATE_CONST;
254 dlf = divisor - (dlh << 12) - dll * __UART_BRATE_CONST;
255
256 /* Set UART registers */
257 sil_orw_mem((uint32_t *)(base+TOFF_UART_LCR), UART_LCR_DMD);
258 sil_wrw_mem((uint32_t *)(base+TOFF_UART_DLH), dlh);
259 sil_wrw_mem((uint32_t *)(base+TOFF_UART_DLL), dll);
260 sil_wrw_mem((uint32_t *)(base+TOFF_UART_DLF), dlf);
261 sil_wrw_mem((uint32_t *)(base+TOFF_UART_LCR), 0x00);
262 sil_wrw_mem((uint32_t *)(base+TOFF_UART_LCR), (UART_WordLength_8b | UART_StopBits_1 | UART_Parity_No));
263 sil_andw_mem((uint32_t *)(base+TOFF_UART_LCR), UART_LCR_DMD);
264 sil_orw_mem((uint32_t *)(base+TOFF_UART_IER), UART_IER_THRE);
265 sil_wrw_mem((uint32_t *)(base+TOFF_UART_FCR),
266 (UART_RECEIVE_FIFO1 << 6 | UART_SEND_FIFO8 << 4 | 0x1 << 3 | 0x1));
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 ip = sil_rew_mem((uint32_t *)(base+TOFF_UART_IIR)) & 0x0F;
321 uint32_t tmp;
322
323 if(ip == UART_IIR_RECEIVE || ip == UART_IIR_CTIMEOUT){
324 sio_irdy_rcv(p_siopcb->exinf);
325 }
326 else if(ip == UART_IIR_SEND){
327 sio_irdy_snd(p_siopcb->exinf);
328 }
329 else{
330 tmp = sil_rew_mem((uint32_t *)(base+TOFF_UART_LSR));
331 tmp = sil_rew_mem((uint32_t *)(base+TOFF_UART_USR));
332 tmp = sil_rew_mem((uint32_t *)(base+TOFF_UART_MSR));
333 }
334 (void)(tmp);
335}
336
337/*
338 * シリアルI/Oポートへの文字送信
339 */
340Inline bool_t
341sio_putready(SIOPCB* p_siopcb)
342{
343 uint32_t lsr = sil_rew_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_LSR));
344
345 if((lsr & UART_LSR_TFL) == 0){
346 return 1;
347 }
348 return 0;
349}
350
351bool_t
352sio_snd_chr(SIOPCB *p_siopcb, char c)
353{
354 if(sio_putready(p_siopcb)){
355 sil_wrw_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_THR), (uint32_t)c);
356 return true;
357 }
358 return false;
359}
360
361/*
362 * シリアルI/Oポートからの文字受信
363 */
364int_t
365sio_rcv_chr(SIOPCB *p_siopcb)
366{
367 int_t c = -1;
368
369 if((sil_rew_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_LSR)) & UART_LSR_RFL) != 0){
370 c = sil_rew_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_RBR)) & 0xFF;
371 }
372 return c;
373}
374
375/*
376 * シリアルI/Oポートからのコールバックの許可
377 */
378void
379sio_ena_cbr(SIOPCB *p_siopcb, uint_t cbrtn)
380{
381 switch (cbrtn) {
382 case SIO_RDY_SND:
383 sil_orw_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_IER), UART_IER_TIE);
384 break;
385 case SIO_RDY_RCV:
386 sil_orw_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_IER), UART_IER_RIE);
387 break;
388 }
389}
390
391/*
392 * シリアルI/Oポートからのコールバックの禁止
393 */
394void
395sio_dis_cbr(SIOPCB *p_siopcb, uint_t cbrtn)
396{
397 switch (cbrtn) {
398 case SIO_RDY_SND:
399 sil_andw_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_IER), UART_IER_TIE);
400 break;
401 case SIO_RDY_RCV:
402 sil_andw_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_IER), UART_IER_RIE);
403 break;
404 }
405}
406
407/*
408 * 1文字出力(ポーリングでの出力)
409 */
410void sio_pol_snd_chr(int8_t c, ID siopid)
411{
412 unsigned long base = siopinib_table[INDEX_PORT(siopid)].base;
413
414 sil_wrw_mem((uint32_t *)(base+TOFF_UART_THR), (uint32_t)c);
415 while(0 != (sil_rew_mem((uint32_t *)(base+TOFF_UART_LSR)) & UART_LSR_TFL));
416
417 /*
418 * 出力が完全に終わるまで待つ
419 */
420 volatile int n = SYS_CLOCK/BPS_SETTING;
421 while(n--);
422}
423
424/*
425 * ターゲットのシリアル初期化
426 */
427void target_uart_init(ID siopid)
428{
429 const SIOPINIB *p_siopinib;
430 unsigned long base;
431 uint32_t divisor, threshold;
432 uint8_t dlh, dll, dlf;
433
434 p_siopinib = &siopinib_table[INDEX_PORT(siopid)];
435 base = p_siopinib->base;
436
437 /*
438 * ハードウェアの初期化
439 */
440 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), p_siopinib->clk);
441
442 threshold = (sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_CLK_SEL0)) & SYSCTL_CLK_SEL0_APB0_CLK_SEL) >> 3;
443 divisor = (get_clock_aclk() / (threshold+1)) / BPS_SETTING;
444 dlh = divisor >> 12;
445 dll = (divisor - (dlh << 12)) / __UART_BRATE_CONST;
446 dlf = divisor - (dlh << 12) - dll * __UART_BRATE_CONST;
447
448 /* Set UART registers */
449 sil_orw_mem((uint32_t *)(base+TOFF_UART_LCR), UART_LCR_DMD);
450 sil_wrw_mem((uint32_t *)(base+TOFF_UART_DLH), dlh);
451 sil_wrw_mem((uint32_t *)(base+TOFF_UART_DLL), dll);
452 sil_wrw_mem((uint32_t *)(base+TOFF_UART_DLF), dlf);
453 sil_wrw_mem((uint32_t *)(base+TOFF_UART_LCR), 0x00);
454 sil_wrw_mem((uint32_t *)(base+TOFF_UART_LCR), (UART_WordLength_8b | UART_StopBits_1 | UART_Parity_No));
455 sil_andw_mem((uint32_t *)(base+TOFF_UART_LCR), UART_LCR_DMD);
456 sil_orw_mem((uint32_t *)(base+TOFF_UART_IER), UART_IER_THRE);
457 sil_wrw_mem((uint32_t *)(base+TOFF_UART_FCR),
458 (UART_RECEIVE_FIFO1 << 6 | UART_SEND_FIFO8 << 4 | 0x1 << 3 | 0x1));
459
460 fpioa_set_function(uartpin[p_siopinib->com][1], p_siopinib->rxfunc);
461 fpioa_set_function(uartpin[p_siopinib->com][0], p_siopinib->txfunc);
462 sil_dly_nse(10000);
463}
Note: See TracBrowser for help on using the repository browser.