RT-AICHIP-sample
serial.c
[詳解]
1 /*----------------------------------------------------------------------------
2  * Name: serial.c
3  * Purpose: serial port handling for LPC134x
4  * Version: V1.10
5  *----------------------------------------------------------------------------
6  * This software is supplied "AS IS" without any warranties, express,
7  * implied or statutory, including but not limited to the implied
8  * warranties of fitness for purpose, satisfactory quality and
9  * noninfringement. Keil extends you a royalty-free right to reproduce
10  * and distribute executable files created using this software for use
11  * on NXP Semiconductors LPC microcontroller devices only. Nothing else
12  * gives you the right to use this software.
13  *
14  * Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
15  *---------------------------------------------------------------------------*/
16 #include "LPC13xx.h" // LPC13xx definitions
17 #include "type.h"
18 #include "serial.h"
19 
20 
21 /*----------------------------------------------------------------------------
22  Defines for ring buffers
23  *---------------------------------------------------------------------------*/
24 #define SER_BUF_SIZE (128) // serial buffer in bytes (power 2)
25 #define SER_BUF_MASK (SER_BUF_SIZE-1ul) // buffer size mask
26 
27 /* Buffer read / write macros */
28 #define SER_BUF_RESET(serBuf) (serBuf.rdIdx = serBuf.wrIdx = 0)
29 #define SER_BUF_WR(serBuf, dataIn) (serBuf.data[SER_BUF_MASK & serBuf.wrIdx++] = (dataIn))
30 #define SER_BUF_RD(serBuf) (serBuf.data[SER_BUF_MASK & serBuf.rdIdx++])
31 #define SER_BUF_EMPTY(serBuf) (serBuf.rdIdx == serBuf.wrIdx)
32 #define SER_BUF_FULL(serBuf) (serBuf.rdIdx == serBuf.wrIdx+1)
33 #define SER_BUF_COUNT(serBuf) (SER_BUF_MASK & (serBuf.wrIdx - serBuf.rdIdx))
34 
35 // buffer type
36 typedef struct __SER_BUF_T {
37  unsigned char data[SER_BUF_SIZE];
38  unsigned int wrIdx;
39  unsigned int rdIdx;
40 } SER_BUF_T;
41 
42 unsigned long ser_txRestart; // NZ if TX restart is required
43 unsigned short ser_lineState; // ((msr << 8) | (lsr))
44 SER_BUF_T ser_out; // Serial data buffers
46 
47 /*----------------------------------------------------------------------------
48  open the serial port
49  *---------------------------------------------------------------------------*/
50 void ser_OpenPort (void) {
51 
52  NVIC_DisableIRQ(UART_IRQn);
53 
54  LPC_IOCON->PIO1_6 &= ~0x07; /* UART I/O config */
55  LPC_IOCON->PIO1_6 |= 0x01; /* UART RXD */
56  LPC_IOCON->PIO1_7 &= ~0x07;
57  LPC_IOCON->PIO1_7 |= 0x01; /* UART TXD */
58  /* Enable UART clock */
59  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);
60  LPC_SYSCON->UARTCLKDIV = 0x1; /* divided by 1 */
61  return;
62 }
63 
64 /*----------------------------------------------------------------------------
65  close the serial port
66  *---------------------------------------------------------------------------*/
67 void ser_ClosePort (void) {
68  LPC_IOCON->PIO1_6 &= ~0x07; /* UART I/O config */
69  LPC_IOCON->PIO1_7 &= ~0x07;
70 
71  /* Disable the interrupt in the VIC and UART controllers */
72  LPC_UART->IER = 0;
73  NVIC_DisableIRQ(UART_IRQn);
74  return;
75 }
76 
77 /*----------------------------------------------------------------------------
78  initialize the serial port
79  *---------------------------------------------------------------------------*/
80 void ser_InitPort (unsigned long baudrate, unsigned int databits,
81  unsigned int parity, unsigned int stopbits) {
82 
83  uint8_t lcr_p, lcr_s, lcr_d;
84  uint32_t dll;
85  uint32_t Fdiv;
86 
87  switch (databits) {
88  case 5: // 5 Data bits
89  lcr_d = 0x00;
90  break;
91  case 6: // 6 Data bits
92  lcr_d = 0x01;
93  break;
94  case 7: // 7 Data bits
95  lcr_d = 0x02;
96  break;
97  case 8: // 8 Data bits
98  default:
99  lcr_d = 0x03;
100  break;
101  }
102 
103  switch (stopbits) {
104  case 1: // 1,5 Stop bits
105  case 2: // 2 Stop bits
106  lcr_s = 0x04;
107  break;
108  case 0: // 1 Stop bit
109  default:
110  lcr_s = 0x00;
111  break;
112  }
113 
114  switch (parity) {
115  case 1: // Parity Odd
116  lcr_p = 0x08;
117  break;
118  case 2: // Parity Even
119  lcr_p = 0x18;
120  break;
121  case 3: // Parity Mark
122  lcr_p = 0x28;
123  break;
124  case 4: // Parity Space
125  lcr_p = 0x38;
126  break;
127  case 0: // Parity None
128  default:
129  lcr_p = 0x00;
130  break;
131  }
132 
133  SER_BUF_RESET(ser_out); // reset out buffer
134  SER_BUF_RESET(ser_in); // reset in buffer
135 
136  /* Note that the pclk is 24,0 MHz. (48.0 MHz / 2) */
137  /* 24 MHz PCLK generates also rates for 115200, 57600 baud */
138  Fdiv = LPC_SYSCON->UARTCLKDIV;
139  dll = (((SystemCoreClock/LPC_SYSCON->SYSAHBCLKDIV)/Fdiv)/16)/baudrate ; /*baud rate */
140  LPC_UART->FDR = 0; // Fractional divider not used
141  LPC_UART->LCR = 0x80 | lcr_d | lcr_p | lcr_s; // Data bits, Parity, Stop bit
142  LPC_UART->DLL = dll; // Baud Rate depending on PCLK
143  LPC_UART->DLM = (dll >> 8); // High divisor latch
144  LPC_UART->LCR = 0x00 | lcr_d | lcr_p | lcr_s; // DLAB = 0
145  LPC_UART->IER = 0x03; // Enable TX/RX interrupts
146 
147  LPC_UART->FCR = 0x07; /* Enable and reset TX and RX FIFO. */
148  ser_txRestart = 1; // TX fifo is empty
149 
150  /* Enable the UART Interrupt */
151  NVIC_EnableIRQ(UART_IRQn);
152  return;
153 }
154 
155 /*----------------------------------------------------------------------------
156  read data from serial port
157  *---------------------------------------------------------------------------*/
158 int ser_Read (char *buffer, const int *length) {
159  int bytesToRead, bytesRead;
160 
161  /* Read *length bytes, block if *bytes are not avaialable */
162  bytesToRead = *length;
163  bytesToRead = (bytesToRead < (*length)) ? bytesToRead : (*length);
164  bytesRead = bytesToRead;
165 
166  while (bytesToRead--) {
167  while (SER_BUF_EMPTY(ser_in)); // Block until data is available if none
168  *buffer++ = SER_BUF_RD(ser_in);
169  }
170  return (bytesRead);
171 }
172 
173 /*----------------------------------------------------------------------------
174  write data to the serial port
175  *---------------------------------------------------------------------------*/
176 int ser_Write (const char *buffer, int *length) {
177  int bytesToWrite, bytesWritten;
178 
179  // Write *length bytes
180  bytesToWrite = *length;
181  bytesWritten = bytesToWrite;
182 
183  while (!SER_BUF_EMPTY(ser_out)); // Block until space is available if none
184  while (bytesToWrite) {
185  SER_BUF_WR(ser_out, *buffer++); // Read Rx FIFO to buffer
186  bytesToWrite--;
187  }
188 
189  if (ser_txRestart) {
190  ser_txRestart = 0;
191  LPC_UART->THR = SER_BUF_RD(ser_out); // Write to the Tx Register
192  }
193 
194  return (bytesWritten);
195 }
196 
197 /*----------------------------------------------------------------------------
198  check if character(s) are available at the serial interface
199  *---------------------------------------------------------------------------*/
200 void ser_AvailChar (int *availChar) {
201 
202  *availChar = SER_BUF_COUNT(ser_in);
203 
204 }
205 
206 /*----------------------------------------------------------------------------
207  read the line state of the serial port
208  *---------------------------------------------------------------------------*/
209 void ser_LineState (unsigned short *lineState) {
210 
211  *lineState = ser_lineState;
212  ser_lineState = 0;
213 
214 }
215 
216 /*----------------------------------------------------------------------------
217  serial port 1 interrupt
218  *---------------------------------------------------------------------------*/
219 /*
220 void UART_IRQHandler(void)
221 {
222  volatile unsigned long iir;
223 
224  iir = LPC_UART->IIR;
225 
226  if ((iir & 0x4) || (iir & 0xC)) { // RDA or CTI pending
227  while (LPC_UART->LSR & 0x01) { // Rx FIFO is not empty
228  SER_BUF_WR(ser_in, LPC_UART->RBR); // Read Rx FIFO to buffer
229  }
230  }
231  if ((iir & 0x2)) { // TXMIS pending
232  if (SER_BUF_COUNT(ser_out) != 0) {
233  LPC_UART->THR = SER_BUF_RD(ser_out); // Write to the Tx FIFO
234  ser_txRestart = 0;
235  }
236  else {
237  ser_txRestart = 1;
238  }
239  }
240  ser_lineState = LPC_UART->LSR & 0x1E; // update linestate
241  return;
242 }
243 */
244 
unsigned char data[SER_BUF_SIZE]
Definition: serial.c:37
void ser_InitPort(unsigned long baudrate, unsigned int databits, unsigned int parity, unsigned int stopbits)
Definition: serial.c:80
#define SER_BUF_COUNT(serBuf)
Definition: serial.c:33
#define SER_BUF_RESET(serBuf)
Definition: serial.c:28
void ser_ClosePort(void)
Definition: serial.c:67
#define SER_BUF_RD(serBuf)
Definition: serial.c:30
int ser_Read(char *buffer, const int *length)
Definition: serial.c:158
void ser_OpenPort(void)
Definition: serial.c:50
struct __SER_BUF_T SER_BUF_T
unsigned int rdIdx
Definition: serial.c:39
SER_BUF_T ser_in
Definition: serial.c:45
unsigned long ser_txRestart
Definition: serial.c:42
unsigned char uint8_t
Definition: type.h:27
SER_BUF_T ser_out
Definition: serial.c:44
#define SER_BUF_EMPTY(serBuf)
Definition: serial.c:31
void ser_LineState(unsigned short *lineState)
Definition: serial.c:209
unsigned int wrIdx
Definition: serial.c:38
#define SER_BUF_WR(serBuf, dataIn)
Definition: serial.c:29
unsigned short ser_lineState
Definition: serial.c:43
void ser_AvailChar(int *availChar)
Definition: serial.c:200
#define SER_BUF_SIZE
Definition: serial.c:24
int ser_Write(const char *buffer, int *length)
Definition: serial.c:176
unsigned int uint32_t
Definition: type.h:29