]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/drv/sci.c
rpp_sci_printk / _printkb - modified (functional part moved to drv sci.c)
[pes-rpp/rpp-lib.git] / rpp / src / drv / sci.c
1 #include "drv/drv.h"
2
3 void drv_sci_init()
4 {
5     // Low level init
6     sciInit();
7 }
8
9 void drv_sci_set_baudrate(uint32_t baud)
10 {
11     // Set baudrate
12     sciSetBaudrate(sciREG, baud);
13 }
14
15 /** Declared in ti_drv_sci.c */
16 extern tBuffer sciOutBuffer;
17 extern tBuffer sciInBuffer;
18
19 uint16_t drv_sci_available()
20 {
21     return (uint16_t)uxQueueMessagesWaiting(sciInBuffer.buf);
22 }
23
24
25 int8_t drv_sci_receive(uint32_t amount, uint8_t* buffer, portTickType wait)
26 {
27     if(sciInBuffer.buf == NULL) {
28         return FAILURE;
29     }
30
31     if(xSemaphoreTake(sciInBuffer.mutex, wait) != pdTRUE) {
32         return FAILURE;
33     }
34
35     // If non block mode, return if not enough data is available
36     if(wait == 0) {
37         if(drv_sci_available() < amount) {
38             xSemaphoreGive(sciInBuffer.mutex);
39             return FAILURE;
40         }
41     }
42
43     int i = 0;
44     unsigned portBASE_TYPE status;
45     while(i < amount) {
46         status = xQueueReceive(sciInBuffer.buf, &buffer[i], wait);
47         if(status != pdTRUE) {
48             xSemaphoreGive(sciInBuffer.mutex);
49             return FAILURE;
50         }
51         i++;
52     }
53
54     xSemaphoreGive(sciInBuffer.mutex);
55     return SUCCESS;
56 }
57
58 static int crlf_conv(uint8_t ch_in, uint8_t *ch_out)
59 {
60         static bool was_cr = false;
61         if (ch_in == '\n' && !was_cr) {
62                 *ch_out = '\r';
63                 was_cr = true;
64                 return 0; // Retry the same char next time
65         }
66         *ch_out = ch_in;
67         was_cr = (ch_in == '\r');
68         return 1; // Move to the next character
69 }
70
71 int8_t drv_sci_send_imm(uint32_t length, uint8_t* data)
72 {
73         uint8_t ch;
74     while(length > 0) {
75         int ofs = crlf_conv(*data, &ch);
76         length -= ofs;
77         data += ofs;
78         while(!(sciREG->FLR & SCI_TX_INT)); /* wait till previous char was sent */
79         sciREG->TD = ch;
80     }
81     return ERR_OK;
82 }
83
84 int8_t drv_sci_send_try_append(uint32_t length, uint8_t* data)
85 {
86         uint8_t ch;
87
88     if(sciOutBuffer.buf == NULL) {
89         return FAILURE;
90     }
91
92     portBASE_TYPE ret = pdTRUE;
93     while(length > 0) {
94         int ofs = crlf_conv(*data, &ch);
95         length -= ofs;
96         data += ofs;
97
98         if(!sciOutBuffer.flags & BUF_TRANSFER_IN_PROGRESS) {
99                 if (!sciOutBuffer.flags & BUF_TRANSFER_IN_PROGRESS) {
100                     sciOutBuffer.flags |= BUF_TRANSFER_IN_PROGRESS;
101                     sciREG->SETINT = SCI_TX_INT;    // Start new transfer by sending first byte
102                     sciREG->TD     = ch;
103                     continue;
104                 }
105         }
106
107         ret = xQueueSendToBackFromISR(sciOutBuffer.buf, (void*)&ch, NULL);
108         if(ret != pdTRUE) {
109             break;
110         }
111         ret = length;
112     }
113     return ret;
114 }
115
116 int8_t drv_sci_send(uint32_t length, uint8_t* data, portTickType wait)
117 {
118         uint8_t ch;
119     if(sciOutBuffer.buf == NULL) {
120         return FAILURE;
121     }
122
123     if(xSemaphoreTake(sciOutBuffer.mutex, wait) != pdTRUE) {
124         return FAILURE;
125     }
126
127     portBASE_TYPE ret = pdTRUE;
128     while(length > 0) {
129         int ofs = crlf_conv(*data, &ch);
130         length -= ofs;
131         data += ofs;
132
133         if(!sciOutBuffer.flags & BUF_TRANSFER_IN_PROGRESS) {
134                 taskENTER_CRITICAL();
135                 if (!sciOutBuffer.flags & BUF_TRANSFER_IN_PROGRESS) {
136                     sciOutBuffer.flags |= BUF_TRANSFER_IN_PROGRESS;
137                     sciREG->SETINT = SCI_TX_INT;    // Start new transfer by sending first byte
138                     sciREG->TD     = ch;
139                     taskEXIT_CRITICAL();
140                     continue;
141                 }
142                 taskEXIT_CRITICAL();
143         }
144
145         ret = xQueueSend(sciOutBuffer.buf, (void*)&ch, wait);
146         if(ret != pdTRUE) {
147             xSemaphoreGive(sciOutBuffer.mutex);
148             return FAILURE;
149         }
150     }
151
152     xSemaphoreGive(sciOutBuffer.mutex);
153     return SUCCESS;
154 }
155
156
157 int8_t drv_sci_flush_buffer(tBuffer* buffer)
158 {
159     if(uxQueueMessagesWaiting(buffer->buf) == 0) {
160         return FAILURE;
161     }
162     xSemaphoreTake(buffer->mutex, portMAX_DELAY);
163     // FIXME: FreeRTOS 7.0.2 doesn't have xQueueReset
164     //xQueueReset(buffer->buf);
165     // FIXME Workaround
166     uint8_t dummy = 0;
167     while(uxQueueMessagesWaiting(buffer->buf) > 0) {
168         xQueueReceive(buffer->buf, &dummy, 0);
169     }
170     ////////////////////
171     xSemaphoreGive(buffer->mutex);
172     return SUCCESS;
173 }
174
175 int8_t drv_sci_flush(boolean_t buf)
176 {
177     if(buf) {
178         return drv_sci_flush_buffer(&sciInBuffer);
179     }
180     return drv_sci_flush_buffer(&sciOutBuffer);
181 }