]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/PIC18_WizC/serial/serial.c
f65f5954a7cfba11a26673a49b870ce67827ddc8
[freertos] / FreeRTOS / Demo / PIC18_WizC / serial / serial.c
1 /*\r
2  * FreeRTOS Kernel V10.0.0\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software. If you wish to use our Amazon\r
14  * FreeRTOS name, please do so in a fair use way that does not cause confusion.\r
15  *\r
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
18  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
19  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
22  *\r
23  * http://www.FreeRTOS.org\r
24  * http://aws.amazon.com/freertos\r
25  *\r
26  * 1 tab == 4 spaces!\r
27  */\r
28 \r
29 /*\r
30 Changes from V3.0.0\r
31         + ISRcode removed. Is now pulled inline to reduce stack-usage.\r
32 \r
33 Changes from V3.0.1\r
34 */\r
35 \r
36 /* BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER. */\r
37 \r
38 /* Scheduler header files. */\r
39 #include "FreeRTOS.h"\r
40 #include "task.h"\r
41 #include "queue.h"\r
42 \r
43 #include "serial.h"\r
44 \r
45 /* Hardware pin definitions. */\r
46 #define serTX_PIN                               bTRC6\r
47 #define serRX_PIN                               bTRC7\r
48 \r
49 /* Bit/register definitions. */\r
50 #define serINPUT                                ( 1 )\r
51 #define serOUTPUT                               ( 0 )\r
52 #define serINTERRUPT_ENABLED    ( 1 )\r
53 \r
54 /* All ISR's use the PIC18 low priority interrupt. */\r
55 #define serLOW_PRIORITY                 ( 0 )\r
56 \r
57 /*-----------------------------------------------------------*/\r
58 \r
59 /* Queues to interface between comms API and interrupt routines. */\r
60 QueueHandle_t xRxedChars; \r
61 QueueHandle_t xCharsForTx;\r
62 portBASE_TYPE xHigherPriorityTaskWoken;\r
63 \r
64 /*-----------------------------------------------------------*/\r
65 \r
66 xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned char ucQueueLength )\r
67 {\r
68         unsigned short usSPBRG;\r
69         \r
70         /* Create the queues used by the ISR's to interface to tasks. */\r
71         xRxedChars = xQueueCreate( ucQueueLength, ( unsigned portBASE_TYPE ) sizeof( char ) );\r
72         xCharsForTx = xQueueCreate( ucQueueLength, ( unsigned portBASE_TYPE ) sizeof( char ) );\r
73 \r
74         portENTER_CRITICAL();\r
75 \r
76         /* Setup the IO pins to enable the USART IO. */\r
77         serTX_PIN       = serINPUT;             // YES really! See datasheet\r
78         serRX_PIN       = serINPUT;\r
79 \r
80         /* Set the TX config register. */\r
81         TXSTA = 0b00100000;\r
82                 //        ||||||||--bit0: TX9D  = n/a\r
83                 //        |||||||---bit1: TRMT  = ReadOnly\r
84                 //        ||||||----bit2: BRGH  = High speed\r
85                 //        |||||-----bit3: SENDB = n/a\r
86                 //        ||||------bit4: SYNC  = Asynchronous mode\r
87                 //        |||-------bit5: TXEN  = Transmit enable\r
88                 //        ||--------bit6: TX9   = 8-bit transmission\r
89                 //        |---------bit7: CSRC  = n/a\r
90 \r
91         /* Set the Receive config register. */\r
92         RCSTA = 0b10010000;\r
93                 //        ||||||||--bit0: RX9D  = ReadOnly\r
94                 //        |||||||---bit1: OERR  = ReadOnly\r
95                 //        ||||||----bit2: FERR  = ReadOnly\r
96                 //        |||||-----bit3: ADDEN = n/a\r
97                 //        ||||------bit4: CREN  = Enable receiver\r
98                 //        |||-------bit5: SREN  = n/a\r
99                 //        ||--------bit6: RX9   = 8-bit reception\r
100                 //        |---------bit7: SPEN  = Serial port enabled\r
101 \r
102         /* Calculate the baud rate generator value.\r
103            We use low-speed (BRGH=0), the formula is\r
104            SPBRG = ( ( FOSC / Desired Baud Rate ) / 64 ) - 1 */\r
105         usSPBRG = ( ( APROCFREQ / ulWantedBaud ) / 64 ) - 1;\r
106         if( usSPBRG > 255 )\r
107         {\r
108                 SPBRG = 255;\r
109         }\r
110         else\r
111         {\r
112                 SPBRG = usSPBRG;\r
113         }\r
114 \r
115         /* Set the serial interrupts to use the same priority as the tick. */\r
116         bTXIP = serLOW_PRIORITY;\r
117         bRCIP = serLOW_PRIORITY;\r
118 \r
119         /* Enable the Rx interrupt now, the Tx interrupt will get enabled when\r
120         we have data to send. */\r
121         bRCIE = serINTERRUPT_ENABLED;\r
122         \r
123         portEXIT_CRITICAL();\r
124 \r
125         /* Unlike other ports, this serial code does not allow for more than one\r
126         com port.  We therefore don't return a pointer to a port structure and \r
127         can     instead just return NULL. */\r
128         return NULL;\r
129 }\r
130 /*-----------------------------------------------------------*/\r
131 \r
132 xComPortHandle xSerialPortInit( eCOMPort ePort, eBaud eWantedBaud, eParity eWantedParity, eDataBits eWantedDataBits, eStopBits eWantedStopBits, unsigned char ucBufferLength )\r
133 {\r
134         /* This is not implemented in this port.\r
135         Use xSerialPortInitMinimal() instead. */\r
136         return NULL;\r
137 }\r
138 /*-----------------------------------------------------------*/\r
139 \r
140 portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, char *pcRxedChar, TickType_t xBlockTime )\r
141 {\r
142         /* Get the next character from the buffer.  Return false if no characters\r
143         are available, or arrive before xBlockTime expires. */\r
144         if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )\r
145         {\r
146                 return ( char ) pdTRUE;\r
147         }\r
148 \r
149         return ( char ) pdFALSE;\r
150 }\r
151 /*-----------------------------------------------------------*/\r
152 \r
153 portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, char cOutChar, TickType_t xBlockTime )\r
154 {\r
155         /* Return false if after the block time there is no room on the Tx queue. */\r
156         if( xQueueSend( xCharsForTx, ( const void * ) &cOutChar, xBlockTime ) != ( char ) pdPASS )\r
157         {\r
158                 return pdFAIL;\r
159         }\r
160 \r
161         /* Turn interrupt on - ensure the compiler only generates a single \r
162         instruction for this. */\r
163         bTXIE = serINTERRUPT_ENABLED;\r
164 \r
165         return pdPASS;\r
166 }\r
167 /*-----------------------------------------------------------*/\r
168 \r
169 void vSerialClose( xComPortHandle xPort )\r
170 {\r
171         /* Not implemented for this port.\r
172         To implement, turn off the interrupts and delete the memory\r
173         allocated to the queues. */\r
174 }\r