Platform drivers for Mbed.
Dependents: EVAL-CN0535-FMCZ EVAL-CN0535-FMCZ EVAL-AD568x-AD569x EVAL-AD7606 ... more
uart.cpp
00001 /***************************************************************************//** 00002 * @file uart.cpp 00003 * @brief Implementation of UART Mbed platform driver interfaces 00004 ******************************************************************************** 00005 * Copyright (c) 2021 Analog Devices, Inc. 00006 * All rights reserved. 00007 * 00008 * This software is proprietary to Analog Devices, Inc. and its licensors. 00009 * By using this software you agree to the terms of the associated 00010 * Analog Devices Software License Agreement. 00011 *******************************************************************************/ 00012 00013 /******************************************************************************/ 00014 /***************************** Include Files **********************************/ 00015 /******************************************************************************/ 00016 #include <stdio.h> 00017 #include <mbed.h> 00018 #include <USBCDC.h> 00019 00020 // Platform drivers needs to be C-compatible to work with other drivers 00021 #ifdef __cplusplus 00022 extern "C" 00023 { 00024 #endif // _cplusplus 00025 00026 #include "error.h" 00027 #include "delay.h" 00028 #include "uart.h" 00029 #include "uart_extra.h" 00030 00031 /******************************************************************************/ 00032 /************************ Macros/Constants ************************************/ 00033 /******************************************************************************/ 00034 00035 /* Max size for USB CDC packet during transmit/receive */ 00036 #define USB_CDC_MAX_PACKET_SIZE (64) 00037 00038 /* Max allowed length of USB serial number in characters */ 00039 #define USB_SERIAL_NUM_MAX_LENGTH (100) 00040 00041 /******************************************************************************/ 00042 /*************************** Types Declarations *******************************/ 00043 /******************************************************************************/ 00044 00045 /* Derived USBCDC class to access protected members of USBCDC class */ 00046 class platform_usbcdc :public USBCDC 00047 { 00048 private: 00049 uint8_t usb_iserial_descriptor[(USB_SERIAL_NUM_MAX_LENGTH * 2) + 2]; 00050 00051 public : 00052 /* Call parent class (USBCDC) constructor explicitly */ 00053 platform_usbcdc(bool connect_blocking, uint16_t vendor_id, uint16_t product_id, 00054 const char *serial_number) 00055 : USBCDC(connect_blocking, vendor_id, product_id) 00056 { 00057 uint8_t usb_iserial_len; // USB serial number length 00058 uint8_t i, j = 0; 00059 00060 usb_iserial_len = strlen(serial_number); 00061 if (usb_iserial_len > USB_SERIAL_NUM_MAX_LENGTH) { 00062 usb_iserial_len = USB_SERIAL_NUM_MAX_LENGTH; 00063 } 00064 00065 this->usb_iserial_descriptor[j++] = (usb_iserial_len * 2) + 2; /* bLength */ 00066 this->usb_iserial_descriptor[j++] = STRING_DESCRIPTOR; /* bDescriptorType */ 00067 00068 /* bString iSerial */ 00069 for (i = 0; i < usb_iserial_len; i++) { 00070 this->usb_iserial_descriptor[j++] = serial_number[i]; 00071 this->usb_iserial_descriptor[j++] = 0; 00072 } 00073 } 00074 00075 /* Override the virtual function that sets the USB serial number 00076 * The custom (user provided) USB serial number is passed through this function */ 00077 virtual const uint8_t *string_iserial_desc() 00078 { 00079 return this->usb_iserial_descriptor; 00080 } 00081 00082 void change_terminal_connection(bool connect_status); 00083 bool data_received(uint32_t rx_size); 00084 bool data_transmited(void); 00085 }; 00086 00087 /******************************************************************************/ 00088 /************************ Functions Definitions *******************************/ 00089 /******************************************************************************/ 00090 00091 /** 00092 * @brief Change the terminal connection status (for non-terminal) based USB interface 00093 * @param connect_status- new connection status 00094 * @note This functions is used to change the terminal connection status of USB client 00095 * interface which is different than the 'console terminal'. The console terminals acknowledge 00096 * back to USB host when USB connection is opened on the console terminal and Mbed USBCDC 00097 * class automatically changes the '_terminal_connected' status accordingly. However, for 00098 * custom PC applications (non terminal), the terminal connection status needs to be changed 00099 * manually. The '_terminal_connected' is protected member of USBCDC parent class and thus can 00100 * be accessed through 'platform_usbcdc' derived class using below function. 00101 */ 00102 void platform_usbcdc::change_terminal_connection(bool connect_status) 00103 { 00104 _terminal_connected = connect_status; 00105 } 00106 00107 00108 /** 00109 * @brief Check if new USB data is received/available 00110 * @param bytes[in] - Number of expected bytes to be received 00111 * @return true if expected number of bytes received, else false 00112 */ 00113 bool platform_usbcdc::data_received(uint32_t bytes) 00114 { 00115 volatile static uint32_t *rx_size = &_rx_size; 00116 00117 if (*rx_size >= bytes) { 00118 return true; 00119 } else { 00120 return false; 00121 } 00122 } 00123 00124 00125 /** 00126 * @brief Check if old USB data was transmitted 00127 * @return true if transmit not in progress, else false 00128 */ 00129 bool platform_usbcdc::data_transmited(void) 00130 { 00131 volatile static bool *tx_in_progress = &_tx_in_progress; 00132 00133 if (*tx_in_progress) { 00134 return false; 00135 } else { 00136 return true; 00137 } 00138 } 00139 00140 00141 /** 00142 * @brief Read data from UART device. 00143 * @param desc - Instance of UART. 00144 * @param data - Pointer to buffer containing data. 00145 * @param bytes_number - Number of bytes to read. 00146 * @return SUCCESS in case of success, FAILURE otherwise. 00147 */ 00148 int32_t uart_read(struct uart_desc *desc, uint8_t *data, uint32_t bytes_number) 00149 { 00150 uint8_t cnt; 00151 mbed::UnbufferedSerial *uart; // pointer to UnbufferedSerial/UART instance 00152 platform_usbcdc *usb_cdc_dev; // Pointer to usb cdc device class instance 00153 uint32_t size_rd; 00154 00155 if (desc && data) { 00156 if (((mbed_uart_desc *)(desc->extra))->uart_port) { 00157 if (((mbed_uart_desc *)desc->extra)->virtual_com_enable) { 00158 usb_cdc_dev = (platform_usbcdc *)((mbed_uart_desc *)( 00159 desc->extra))->uart_port; 00160 00161 while (!usb_cdc_dev->data_received(bytes_number)) { 00162 /* Wait until new data is available */ 00163 } 00164 00165 /* Change terminal connection status manually */ 00166 usb_cdc_dev->change_terminal_connection(true); 00167 00168 usb_cdc_dev->receive_nb(data, bytes_number, &size_rd); 00169 } else { 00170 uart = (UnbufferedSerial *)(((mbed_uart_desc *)(desc->extra))->uart_port); 00171 00172 for (cnt = 0; cnt < bytes_number; cnt++) { 00173 uart->read(data + cnt, 1); 00174 } 00175 } 00176 00177 return bytes_number; 00178 } 00179 } 00180 00181 return FAILURE; 00182 } 00183 00184 00185 /** 00186 * @brief Write data to UART device. 00187 * @param desc - Instance of UART. 00188 * @param data - Pointer to buffer containing data. 00189 * @param bytes_number - Number of bytes to read. 00190 * @return SUCCESS in case of success, FAILURE otherwise. 00191 */ 00192 int32_t uart_write(struct uart_desc *desc, const uint8_t *data, 00193 uint32_t bytes_number) 00194 { 00195 mbed::UnbufferedSerial *uart; // pointer to UnbufferedSerial/UART instance 00196 platform_usbcdc *usb_cdc_dev; // Pointer to usb cdc device class instance 00197 uint32_t d_sz; 00198 uint32_t indx = 0; 00199 00200 if (desc && data) { 00201 if (((mbed_uart_desc *)(desc->extra))->uart_port) { 00202 if (((mbed_uart_desc *)desc->extra)->virtual_com_enable) { 00203 usb_cdc_dev = (platform_usbcdc *)((mbed_uart_desc *)( 00204 desc->extra))->uart_port; 00205 00206 while (bytes_number) { 00207 while (!usb_cdc_dev->data_transmited()) { 00208 /* Wait until old data is transmitted */ 00209 } 00210 00211 /* Make sure packet size is less than max CDC packet size during data transmit */ 00212 d_sz = (bytes_number > (USB_CDC_MAX_PACKET_SIZE - 1)) ? 00213 (USB_CDC_MAX_PACKET_SIZE - 1) : 00214 bytes_number; 00215 00216 /* Change terminal connection status manually */ 00217 usb_cdc_dev->change_terminal_connection(true); 00218 00219 usb_cdc_dev->send_nb((uint8_t *)&data[indx], d_sz, &d_sz); 00220 00221 bytes_number -= d_sz; 00222 indx += d_sz; 00223 } 00224 00225 return bytes_number; 00226 } else { 00227 uart = (UnbufferedSerial *)(((mbed_uart_desc *)(desc->extra))->uart_port); 00228 return uart->write(data, bytes_number); 00229 } 00230 } 00231 } 00232 00233 return FAILURE; 00234 } 00235 00236 00237 /** 00238 * @brief Submit reading buffer to the UART driver. 00239 * 00240 * Buffer is used until bytes_number bytes are read. 00241 * @param desc: Descriptor of the UART device 00242 * @param data: Buffer where data will be read 00243 * @param bytes_number: Number of bytes to be read. 00244 * @return \ref SUCCESS in case of success, \ref FAILURE otherwise. 00245 */ 00246 int32_t uart_read_nonblocking(struct uart_desc *desc, 00247 uint8_t *data, 00248 uint32_t bytes_number) 00249 { 00250 mbed::UnbufferedSerial *uart; // pointer to UnbufferedSerial/UART instance 00251 00252 if (desc) { 00253 if (((mbed_uart_desc *)(desc->extra))->uart_port) { 00254 uart = (UnbufferedSerial *)(((mbed_uart_desc *)(desc->extra))->uart_port); 00255 00256 if (data) { 00257 for (size_t i = 0; i < bytes_number; i++) { 00258 if (uart->readable() > 0) { 00259 uart->read(&data[i], 1); 00260 } 00261 } 00262 00263 return bytes_number; 00264 } 00265 } 00266 } 00267 00268 return FAILURE; 00269 } 00270 00271 00272 /** 00273 * @brief Submit writting buffer to the UART driver. 00274 * 00275 * Data from the buffer is sent over the UART, the function returns imediatly. 00276 * @param desc: Descriptor of the UART device 00277 * @param data: Buffer where data will be written 00278 * @param bytes_number: Number of bytes to be written. 00279 * @return \ref SUCCESS in case of success, \ref FAILURE otherwise. 00280 */ 00281 int32_t uart_write_nonblocking(struct uart_desc *desc, 00282 const uint8_t *data, 00283 uint32_t bytes_number) 00284 { 00285 mbed::UnbufferedSerial *uart; // pointer to UnbufferedSerial/UART instance 00286 00287 if (desc) { 00288 if (((mbed_uart_desc *)(desc->extra))->uart_port) { 00289 uart = (UnbufferedSerial *)(((mbed_uart_desc *)(desc->extra))->uart_port); 00290 00291 if (data) { 00292 for (size_t i = 0; i < bytes_number; i++) { 00293 uart->write(&data[i], 1); 00294 } 00295 00296 return bytes_number; 00297 } 00298 } 00299 } 00300 00301 return FAILURE; 00302 } 00303 00304 00305 /** 00306 * @brief Initialize the UART communication peripheral. 00307 * @param desc - The UART descriptor. 00308 * @param param - The structure that contains the UART parameters. 00309 * @return SUCCESS in case of success, FAILURE otherwise. 00310 */ 00311 int32_t uart_init(struct uart_desc **desc, struct uart_init_param *param) 00312 { 00313 mbed::UnbufferedSerial *uart; // Pointer to new UnbufferedSerial/UART instance 00314 platform_usbcdc *usb_cdc_dev; // Pointer to usb cdc device class instance 00315 mbed_uart_desc *mbed_desc; // Pointer to mbed uart descriptor 00316 uart_desc *new_desc; // UART new descriptor 00317 00318 if (desc && param && param->extra) { 00319 // Create the UART description object for the device 00320 new_desc = (uart_desc *)malloc(sizeof(uart_desc)); 00321 if (!new_desc) { 00322 goto err_new_desc; 00323 } 00324 00325 new_desc->baud_rate = param->baud_rate; 00326 00327 if (((mbed_uart_init_param *)param->extra)->virtual_com_enable) { 00328 // Create a new instance of platform_usbcdc class 00329 usb_cdc_dev = new platform_usbcdc(false, 00330 ((mbed_uart_init_param *)param->extra)->vendor_id, 00331 ((mbed_uart_init_param *)param->extra)->product_id, 00332 ((mbed_uart_init_param *)param->extra)->serial_number); 00333 if (!usb_cdc_dev) { 00334 goto err_usb_cdc_dev; 00335 } 00336 } else { 00337 // Create and configure a new instance of UnbufferedSerial/UART port 00338 uart = new UnbufferedSerial( 00339 (PinName)(((mbed_uart_init_param *)param->extra)->uart_tx_pin), 00340 (PinName)(((mbed_uart_init_param *)param->extra)->uart_rx_pin), 00341 (int)param->baud_rate); 00342 00343 if (!uart) { 00344 goto err_uart; 00345 } 00346 } 00347 00348 // Create a new mbed descriptor to store new UART instances 00349 mbed_desc = (mbed_uart_desc *)malloc(sizeof(mbed_uart_desc)); 00350 if (!mbed_desc) { 00351 goto err_mbed_desc; 00352 } 00353 00354 if (((mbed_uart_init_param *)param->extra)->virtual_com_enable) { 00355 mbed_desc->uart_port = (platform_usbcdc *)usb_cdc_dev; 00356 00357 /* Establish connection with the USB CDC communication port */ 00358 usb_cdc_dev->connect(); 00359 mdelay(2000); 00360 } else { 00361 mbed_desc->uart_port = (UnbufferedSerial *)uart; 00362 } 00363 00364 mbed_desc->virtual_com_enable = ((mbed_uart_init_param *) 00365 param->extra)->virtual_com_enable; 00366 new_desc->extra = (mbed_uart_desc *)mbed_desc; 00367 *desc = new_desc; 00368 00369 return SUCCESS; 00370 } 00371 00372 err_mbed_desc: 00373 if (uart) { 00374 free(uart); 00375 } 00376 if (usb_cdc_dev) { 00377 free(usb_cdc_dev); 00378 } 00379 err_uart: 00380 err_usb_cdc_dev: 00381 free(new_desc); 00382 err_new_desc: 00383 // Nothing to free 00384 00385 return FAILURE; 00386 } 00387 00388 00389 /** 00390 * @brief Free the resources allocated by uart_init(). 00391 * @param desc - The UART descriptor. 00392 * @return SUCCESS in case of success, FAILURE otherwise. 00393 */ 00394 int32_t uart_remove(struct uart_desc *desc) 00395 { 00396 if (desc) { 00397 // Free the UART port object 00398 if (((mbed_uart_desc *)desc->extra)->virtual_com_enable) { 00399 if ((platform_usbcdc *)((mbed_uart_desc *)desc->extra)->uart_port) 00400 delete((platform_usbcdc *)(platform_usbcdc *)((mbed_uart_desc *) 00401 desc->extra)->uart_port); 00402 } else { 00403 if ((UnbufferedSerial *)(((mbed_uart_desc *)(desc->extra))->uart_port)) { 00404 delete((UnbufferedSerial *)(((mbed_uart_desc *)(desc->extra))->uart_port)); 00405 } 00406 } 00407 00408 // Free the UART extra descriptor object 00409 if ((mbed_uart_desc *)(desc->extra)) { 00410 free((mbed_uart_desc *)(desc->extra)); 00411 } 00412 00413 // Free the UART descriptor object 00414 free(desc); 00415 00416 return SUCCESS; 00417 } 00418 00419 return FAILURE; 00420 } 00421 00422 00423 /** 00424 * @brief Get number of UART errors. 00425 * @param desc - The UART descriptor. 00426 * @return number of errors. 00427 */ 00428 uint32_t uart_get_errors(struct uart_desc *desc) 00429 { 00430 if (desc) { 00431 // Unused variable - fix compiler warning 00432 } 00433 00434 return SUCCESS; 00435 } 00436 00437 #ifdef __cplusplus // Closing extern c 00438 } 00439 #endif // _cplusplus
Generated on Wed Jul 13 2022 14:37:51 by 1.7.2