Lecture 12: UART Application 10:10 Today we will discuss an application using UART Programming. We will go through all of the steps of application design, locating the documentation, structuring and testing the program, and so on. The specification of the application is the following: "Design an loopback application for UART using a 115200 baudrate with an 8N1 line format. When the input contains the string 'flip', then the strong is absorbed and the color LED will toggle (between all black and all white). When the input contains any other string, it will be copied to the output." 1. Parameter Selection: Baud Rate Setting 2. Application Design - FSM Design - HAL Design - Cyclic Executive Design 3. Application Coding - HAL Coding - FSM Coding - Cyclic Executive Coding 4. Application Testing - Error Handling 10:14 Parameter Selection Baud Rate Setting for 115200 baud. - Documentation? MSP432P4 User Guide Section 24.3.10 - Procedure? We need to determine the period and modulator register following the steps in section 24.3.10 1. N = fbrclk / baudrate N = 3000000 / 115200 N = 26.0416667 N > 16 -> Oversampling Mode 3. UCBRx = INT(N) >> 4 = 1 UCBFRx = INT(N) & 15 = 10 4. UCBRSx = 0x0 - These parameters can be used in a uartConfig construct (see later) 10:22 String Matching How do we build a string matching engine for a UART ? Remember the earlier story on cyclic executive and events: 1/ A cyclic executive can scan for one event and take immediate action. For example: while (1) { if (UART_has_char()) c = read_uart_char(); } 2/ A finite state machine is needed when we wish to detect a SEQUENCE of events matching a string of UART characters is a sequence of events, each corresponding to receiving one UART character. while (1) { if (UART_has_char()) { c = read_uart_char(); process_char(c); // an FSM } } Let's design an FSM to match string 'flip'. Input: The character c received on the UART Output: Nothing Actions: Call to 'putchar' + Call to 'toggleLED'. How many states do we need? We need four states: - idle: We have found no character in the string - has_f: We have found an 'f' character in the string - has_l: We have found an 'l' character in the string - has_i: We have found an 'i' character in the string What state transitions for we need? (We can draw this graphically as a state transition graph) In state idle: if (c == 'f') state = has_f else putchar(c) In state has_f: if (c == 'l') state = has_l else { putchar('f') putchar(c) state = idle } In state has_l: if (c == 'i') state = has_i else { putchar('f') putchar('l') putchar(c) state = idle } In state has_i: if (c == 'p') { toggle_led state = idle } else { putchar('f') putchar('l') putchar('i') putchar(c) state = idle } 10:30 Cycle Executive Design and HAL Design The idea of the HAL (hardware abstraction layer) is to separate low-level hardware details from application logic. Low-level hardware details is everything that is directly written using driverlib functions. Application logic is everything above that. +---------------------------------+ Application + +--> Cyclic Executive | +--> FilterFSM +---------------------------------+ HAL InitUART() InitColorLED() UARTHasChar() ToggleColorLED() UARTGetChar() UARTPutChar() +---------------------------------+ Driverlib +---------------------------------+ Hardware + UART + COLORLED +---------------------------------+ You can get a good idea of what would be included in the HAL by writing the cyclic executive in a manner that feels comfortable and logical in terms of the application. Think of this as a 'top-down' design of your application. For example: int main(void) { InitUART(); // hal function to initialize uart InitColorLED(); // hal function to initialize color led while (1) { if (UARTHasChar()) { // hal function to test if UART received a char c = UARTGetChar(); // hal function to read it FilterFSM(c); // hal function to process the FSM logic } } } To implement the actions of the FSM (FilterFSM), we may need additional HAL functions: UARTPutChar(c) // hal function to send a character using UART ToggleColorLED() // hal function to toggle the color LED The implementation of the HAL will be done using driverlib functions. 10:40 HAL Coding Doing HAL coding is manual intensive - you will have to spend some time reading through various documentation manuals in order to tie everything together, or (in case you receive a HAL function) to fully understand how it works. The relevant documents are: - Driverlib user guide: function calls to peripherals - MSP432P4 user guide: functional description of peripherals - MSP432P4 data sheet: input/output diagram Let's do one example. The InitUART: - should set the baudrate and line format - enable the UART module - make sure it is connected to the microcontroller pins void InitUART() { - initialize UART Module - enable the Module - ensure pin connectivity } -> MANUAL: driverlib page 372 (a) initialize UART Module UART_initModule(EUSCI_A0_BASE, &uartConfig); eUSCI_UART_Config structure follows the table on page 372: selectClockSource EUSCI_A_UART_CLOCKSOURCE_SMCLK, clockPreScalar 1, firstModReg 10, secondModReg 0, parity EUSCI_A_UART_EVEN_PARITY, msborLsbFirst EUSCI_A_UART_LSB_FIRST, numberofStopBits EUSCI_A_UART_ONE_STOP_BIT, uartMode EUSCI_A_UART_MODE, overSampling EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION So we specify: eUSCI_UART_Config uartConfig = { EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source = 3MHz 1, // UCBR 10, // UCBRF 0, // UCBRS EUSCI_A_UART_EVEN_PARITY, // Even Parity EUSCI_A_UART_LSB_FIRST, // LSB First EUSCI_A_UART_ONE_STOP_BIT, // One stop bit EUSCI_A_UART_MODE, // UART mode EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION // Oversampling }; (b) enable UART Module UART_enableModule(EUSCI_A0_BASE); (c) make sure the UART module is connected to IO pins How do we find the pin setting function? We have to consult the MSP432 Data Sheet. This is one of the few occasions where we really have to look at the data sheet, because we find package specific information. Find in data sheet location of UART pins? page 26, pin 6 -> UCA0RXD pin 7 -> UCA0TXD Then we can also find the additional functionalities on those pins on the package fig 4-1 page 8 pin 6 -> P1.2/UCA0RXD/UCA0SOMI pin 7 -> P1.3/UCA0TXD/UCA0SIMO To select the additional functionalities in a pin, there is a GPIO call documented in the driverlib user guide -> MANUAL: driver lib page 150 -> MANUAL: MSP432P4 page 679 (explains 'primary module function') GPIO_setAsPeripheralModuleFunctionInputPin( GPIO_PORT_P1, GPIO_PIN2, GPIO_PRIMARY_MODULE_FUNCTION); GPIO_setAsPeripheralModuleFunctionOutputPin( GPIO_PORT_P1, GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION); 10:45 FSM Coding and Cyclic Executive Coding See example; this is quite straightforward given earlier discussions 10:46 UART Error Handling What can go wrong? Lots of things! The diagnosis is limited to three cases. Each of these cases has a flag in the UART Status Register OVERRUN ERROR: There's a new character received, and the software did not pick up the previous character. In that case, we lost the previously received character in the RECEIVE REGISTER FRAMING ERROR: The value of the stop bit is not as expected! It is expected to be 1, but the receiver found a 0 That means that either the line is dead (always 0), or the baud rate is incorrectly configured, or there is some unexpected noise on the line. In any case, the last received character is lost, because the stop bit is not as expected. PARITY ERROR: The Parity bit is of a different value than expected. The means that the parity is configured incorrectly, or that there is a transmission error. 10:50 Summary of UART Things you should understand: (a) Line Format (b) Baud Rate Generator parameter selection (c) Process of transmitting a byte with UART (d) Process of receiving a byte with UART Things you should be able to do (using C): (a) Configuring UART (b) Sending/Receiving bytes (c) Setting and Changing Baudrate General Useful Stuff (a) Hardware Abstraction Layer (b) Cyclic executive and FSM