You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
5.7 KiB

4 years ago
  1. /*
  2. * uart.c
  3. *
  4. * Created on: Aug 5, 2019
  5. * Author: Cristian Fatu
  6. * Implements basic UART functionality, over Uart Lite linux driver, using termios.
  7. * After booting linux, a device like "/dev/ttyUL1" must be present.
  8. * These functions work in both canonic and not canonic modes.
  9. * In the canonic communication mode, the received chars can be retrieved by read only after \n is detected.
  10. * In the non canonic communication mode, the received chars can be retrieved by read as they are received.
  11. */
  12. #include "uart.hpp"
  13. #include <fcntl.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <termios.h>
  18. /*
  19. Parameters:
  20. struct UartDevice* dev - pointer to the UartDevice struct
  21. unsigned char canonic - communication mode
  22. 1 - canonic communication (chars are only received after \n is detected).
  23. 0 - non canonic communication (chars are received as they arrive over UART).
  24. Return value:
  25. UART_FAILURE -1 failure
  26. UART_SUCCESS 0 success
  27. Description:
  28. Initializes the UART device.
  29. When calling the function, the device name (usually "/dev/ttyUL1") must be filled in dev->name and the baud rate must be filled in dev->rate.
  30. The canonic function parameter indicates communication mode (canonic or not).
  31. In the canonic communication mode, the received chars can be retrieved by read only after \n is detected.
  32. In the non canonic communication mode, the received chars can be retrieved by read as they are received, as the non canonic mode is configured with no wait.
  33. */
  34. int uartStart(struct UartDevice* dev, unsigned char canonic) {
  35. struct termios* tty;
  36. int fd;
  37. int rc;
  38. fd = open(dev->name, O_RDWR | O_NOCTTY);
  39. if (fd < 0) {
  40. printf("%s: failed to open file descriptor for file %s\r\n", __func__, dev->name);
  41. return UART_FAILURE;
  42. }
  43. tty = (struct termios*)calloc(1, sizeof(*dev->tty));
  44. if (!tty) {
  45. printf("%s: failed to allocate tty instance\r\n", __func__);
  46. return UART_FAILURE;
  47. }
  48. // memset(tty, 0, sizeof(struct termios));
  49. /*
  50. BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
  51. CRTSCTS : output hardware flow control (only used if the cable has
  52. all necessary lines. See sect. 7 of Serial-HOWTO)
  53. CS8 : 8n1 (8bit,no parity,1 stopbit)
  54. CLOCAL : local connection, no modem contol
  55. CREAD : enable receiving characters
  56. */
  57. // tty->c_cflag = dev->rate | CRTSCTS | CS8 | CLOCAL | CREAD;
  58. tty->c_cflag = dev->rate | CS8 | CLOCAL | CREAD;
  59. if (canonic) {
  60. // canonic
  61. /*
  62. IGNPAR : ignore bytes with parity errors
  63. ICRNL : map CR to NL (otherwise a CR input on the other computer
  64. will not terminate input)
  65. otherwise make device raw (no other input processing)
  66. */
  67. tty->c_iflag = IGNPAR | ICRNL;
  68. /*
  69. ICANON : enable canonical input
  70. disable all echo functionality, and don't send signals to calling program
  71. */
  72. tty->c_lflag = ICANON;
  73. } else {
  74. // not canonic
  75. /*
  76. IGNPAR : ignore bytes with parity errorsc_cc[VTIME]
  77. */
  78. tty->c_iflag = IGNPAR;
  79. /* set input mode (non-canonical, no echo,...) */
  80. tty->c_lflag = 0;
  81. /* Do not wait for data */
  82. tty->c_cc[VTIME] = 0; /* inter-character timer unused */
  83. tty->c_cc[VMIN] = 0; /* blocking read until 5 chars received */
  84. }
  85. /*
  86. Raw output.
  87. */
  88. tty->c_oflag = 0;
  89. /* Flush port */
  90. tcflush(fd, TCIFLUSH);
  91. /* Apply attributes */
  92. rc = tcsetattr(fd, TCSANOW, tty);
  93. if (rc) {
  94. printf("%s: failed to set TCSANOW attr\r\n", __func__);
  95. return UART_FAILURE;
  96. }
  97. dev->fd = fd;
  98. dev->tty = tty;
  99. return UART_SUCCESS;
  100. }
  101. /*
  102. Parameters:
  103. struct UartDevice* dev - pointer to the UartDevice struct
  104. char *data - pointer to the array of chars to be sent over UART
  105. int size
  106. positive value - number of chars to be sent over UART
  107. -1 - indicates that all the chars until string terminator \0 will be sent
  108. Return value:
  109. number of chars sent over UART
  110. Description:
  111. This function sends a number of chars over UART.
  112. If the size function parameter is -1 then all the characters until string terminator \0 will be sent.
  113. */
  114. int uartSend(struct UartDevice* dev, char* data, int size) {
  115. int sent = 0;
  116. if (size == -1) {
  117. size = strlen(data);
  118. }
  119. sent = write(dev->fd, data, size);
  120. #ifdef DEBUG
  121. printf("%s: sent %d characters\r\n", __func__, sent);
  122. #endif
  123. return sent;
  124. }
  125. /*
  126. Parameters:
  127. struct UartDevice* dev - pointer to the UartDevice struct
  128. char *data - pointer to the array of chars to hold the cars revceived over UART
  129. int size_max - the maximum number of characters to be received
  130. Return value:
  131. number of chars received over UART
  132. Description:
  133. This function receives characters over UART.
  134. In the canonic communication mode, the received chars will be retrieved by read only after \n is detected.
  135. In the non canonic communication mode, the received chars will be retrieved by read as they are received, as the non canonic mode is configured with no wait.
  136. */
  137. int uartReceive(struct UartDevice* dev, char* data, int size_max) {
  138. int received = 0;
  139. #ifdef DEBUG
  140. // printf("%s: receiving characters %d\r\n", __func__, size_max);
  141. #endif
  142. received = read(dev->fd, data, size_max - 1);
  143. data[received] = '\0';
  144. #ifdef DEBUG
  145. // if(received > 0)
  146. // printf("%s: received %d characters\r\n", __func__, received);
  147. // else
  148. // printf("%s: r%d/%d\r\n", __func__, received, size_max);
  149. #endif
  150. return received;
  151. }
  152. int uartStop(struct UartDevice* dev) {
  153. free(dev->tty);
  154. return UART_SUCCESS;
  155. }