#include "Os.h" #include "t_stdlib.h" #include "prc_sil.h" #include "comuart.h" /* * レジスタオフセット */ #define UART_RXDATA_OFFSET UINT_C(0x00) #define UART_TXDATA_OFFSET UINT_C(0x04) #define UART_STATUS_OFFSET UINT_C(0x08) #define UART_CONTROL_OFFSET UINT_C(0x0c) #define UART_DIVISOR_OFFSET UINT_C(0x10) /* * レジスタビット定義 */ #define UART_STATUS_TRDY UINT_C(0x0040) #define UART_STATUS_RRDY UINT_C(0x0080) #define UART_CONTROL_ITRDY UINT_C(0x0040) #define UART_CONTROL_IRRDY UINT_C(0x0080) /* * UART */ #define RxBUFF_SIZE 256 #define TxBUFF_SIZE 256 static uint8 s_rxbuff[RxBUFF_SIZE]; static uint8 s_txbuff[TxBUFF_SIZE]; static int s_rxbuff_tail; static int s_rxbuff_head; static int s_rxbuff_cnt; static int s_txbuff_tail; static int s_txbuff_head; static int s_txbuff_cnt; static boolean s_do_tx; static void ena_rx_int(void){ sil_wrw_iop((void *) (COMUART_BASE + UART_CONTROL_OFFSET), sil_rew_iop((void *) (COMUART_BASE + UART_CONTROL_OFFSET)) | UART_CONTROL_IRRDY); } static void dis_rx_int(void){ sil_wrw_iop((void *) (COMUART_BASE + UART_CONTROL_OFFSET), sil_rew_iop((void *) (COMUART_BASE + UART_CONTROL_OFFSET)) & ~UART_CONTROL_IRRDY); } static void ena_tx_int(void){ sil_wrw_iop((void *) (COMUART_BASE + UART_CONTROL_OFFSET), sil_rew_iop((void *) (COMUART_BASE + UART_CONTROL_OFFSET)) | UART_CONTROL_ITRDY); } static void dis_tx_int(void){ sil_wrw_iop((void *) (COMUART_BASE + UART_CONTROL_OFFSET), sil_rew_iop((void *) (COMUART_BASE + UART_CONTROL_OFFSET)) & ~UART_CONTROL_ITRDY); } static void comuart_putc(unsigned char c){ sil_wrw_iop((void *) (COMUART_BASE + UART_TXDATA_OFFSET), (uint32) c); } static unsigned char comuart_getc(void){ return((uint8) sil_rew_iop((void *) (COMUART_BASE + UART_RXDATA_OFFSET))); } static boolean comuart_getready(void) { return((sil_rew_iop((void *) (COMUART_BASE + UART_STATUS_OFFSET)) & UART_STATUS_RRDY) != 0U); } static boolean comuart_putready(void) { return((sil_rew_iop((void *) (COMUART_BASE + UART_STATUS_OFFSET)) & UART_STATUS_TRDY) != 0U); } void comuart_pputc(unsigned char c){ while(!(comuart_putready())){} comuart_putc(c); } /* * 初期化 */ void comuart_init(void) { /* * 受信割込み許可 */ ena_rx_int(); } /* * 受信したデータ長 */ int comuart_get_rxcnt(void) { return s_rxbuff_cnt; } /* * 受信 */ boolean comuart_receive(unsigned char *data, int len) { boolean result = TRUE; int loop; SuspendOSInterrupts(); if (s_rxbuff_cnt < len) { result = FALSE; }else { for(loop = 0; loop < len; loop++) { *data++ = s_rxbuff[s_rxbuff_head++]; s_rxbuff_head = s_rxbuff_head % RxBUFF_SIZE; s_rxbuff_cnt--; } } ResumeOSInterrupts(); return result; } /* * 送信 */ boolean comuart_send(const unsigned char *data, int len) { int loop; char c; /* 空きが無ければエラー */ if (s_txbuff_cnt + len > TxBUFF_SIZE) { return FALSE; } /* リングバッファにコピー */ for(loop = 0; loop < len; loop++){ s_txbuff[s_txbuff_tail++] = *data++; s_txbuff_tail = s_txbuff_tail % TxBUFF_SIZE; s_txbuff_cnt++; } if (!(s_do_tx)) { SuspendOSInterrupts(); /* リングバッファから取り出し送信 */ c = s_txbuff[s_txbuff_head++]; s_txbuff_head = s_txbuff_head % TxBUFF_SIZE; s_txbuff_cnt--; s_do_tx = TRUE; comuart_putc(c); ResumeOSInterrupts(); /* 受信割込み許可 */ if(s_txbuff_cnt > 0){ ena_tx_int(); } } return TRUE; } /* * UART2割込みハンドラ */ #define TASK_NONE 0xFFFFFFFF static TaskType COMUartWaitTask = TASK_NONE; /* * 割込みハンドラ */ ISR(COMUART_Interrupt) { char c; if (comuart_putready() != FALSE) { /* 送信処理 */ if (s_txbuff_cnt == 0) { /* バッファが空 */ s_do_tx = FALSE; dis_tx_int(); } else { /* バッファからデータを取り出し出力 */ c = s_txbuff[s_txbuff_head++]; s_txbuff_head = s_txbuff_head % TxBUFF_SIZE; s_txbuff_cnt--; comuart_putc(c); s_do_tx = TRUE; } } if (comuart_getready() != FALSE) { /* 受信処理 */ c = comuart_getc(); if (s_rxbuff_cnt < RxBUFF_SIZE) { s_rxbuff[s_rxbuff_tail++] = c; s_rxbuff_tail = s_rxbuff_tail % RxBUFF_SIZE; s_rxbuff_cnt++; } else { com_error(); } if (COMUartWaitTask != TASK_NONE) { SetEvent(COMUartWaitTask, COMUartEvt); } } } /* * UARTE2のイベント待ち */ void WaitCOMUartEvent(void) { TaskType task_id; GetTaskID(&task_id); COMUartWaitTask = task_id; if(comuart_get_rxcnt() == 0) { WaitEvent(COMUartEvt); ClearEvent(COMUartEvt); } COMUartWaitTask = TASK_NONE; }