📄 uart.c
字号:
// This file is part of MANTIS OS, Operating System// See http://mantis.cs.colorado.edu///// Copyright (C) 2003,2004,2005 University of Colorado, Boulder//// This program is free software; you can redistribute it and/or// modify it under the terms of the mos license (see file LICENSE)/* Project Mantis File: uart.c Authors: Jeff Rose Date: 03-01-04 Operation in both com mode, using the MOS com layer and a raw mode are supported at compilation time. In order to turn on raw mode (off by default), #define RAW_MODE_UARTX, where X is the UART you want to be in raw mode. This used to be a runtime option, but it can be implemented more efficiently as a compile time option. In raw mode, if you know you will only be accessing the UART from a single thread, you may use the *_nolock functions, which will not lock a mutex when accessing the UART.*/#include "mos.h"#ifndef PLATFORM_LINUX#include "msched.h"#include "uart.h"#include "sem.h"#include "com.h"#include "mutex.h"#include "plat_dep.h"#ifdef PLATFORM_TELOSB#include "plat_clock.h"#endif#if defined(UART) || !defined(SCONS)/* Receive states and state variables. */#define STATE_SEND_PREAMBLE 0#define STATE_SEND_SIZE 1#define STATE_SEND_DATA 2/* Send states and state variables. */#define STATE_RECV_IDLE 0#define STATE_RECV_PREAMBLE 1#define STATE_RECV_SIZE 2#define STATE_RECV_DATA 3static void (*tx_state0)(void);static void (*rx_state0)(void);static void (*tx_state1)(void);static void (*rx_state1)(void);/* Buf pointers & indices for sending and receiving. *//** @brief Buf pointer for receiving and sending. */static comBuf *rx_buf0;static comBuf *tx_buf0;static comBuf *rx_buf1;static comBuf *tx_buf1;static uint8_t rx_index0;static uint8_t tx_index0;static uint8_t tx_index1;static uint8_t rx_index1;/** @brief A thread pointer to keep the id of a blocked send thread. */static mos_sem_t tx_sem0;static mos_sem_t tx_sem1;static mos_sem_t rx_sem0;static mos_sem_t rx_sem1;#ifdef NEED_RAW_MODEstatic uint8_t rx_raw_max0;static uint8_t *rx_raw_buf0;static uint8_t tx_raw_max0;static uint8_t *tx_raw_buf0;static uint8_t rx_raw_max1;static uint8_t *tx_raw_buf1;static uint8_t tx_raw_max1;static uint8_t *rx_raw_buf1;#endif#ifdef ARCH_AVR#define UART_ENABLE_RX_INT0() (UCSR0B |= (1 << RXCIE0) | (1 << RXEN0))#define UART_ENABLE_RX_INT1() (UCSR1B |= (1 << RXCIE1) | (1 << RXEN1))#define UART_DISABLE_RX_INT0() (UCSR0B &= ~((1 << RXCIE0) | (1 << RXEN0)))#define UART_DISABLE_RX_INT1() (UCSR1B &= ~((1 << RXCIE1) | (1 << RXEN1)))#define UART_ENABLE_TX_INT0() (UCSR0B |= (1 << TXEN0) | (1 << UDRIE0))#define UART_ENABLE_TX_INT1() (UCSR1B |= (1 << TXEN1) | (1 << UDRIE1))#define UART_DISABLE_TX_INT0() (UCSR0B &= ~((1 << TXEN0) | (1 << UDRIE0)))#define UART_DISABLE_TX_INT1() (UCSR1B &= ~((1 << TXEN1) | (1 << UDRIE1)))#define TX_REG0 UDR0#define RX_REG0 UDR0#define TX_REG1 UDR1#define RX_REG1 UDR1#elif defined(PLATFORM_TELOSB)#define UART_ENABLE_RX_INT0() (IE1 |= URXIE0)#define UART_ENABLE_RX_INT1() (IE2 |= URXIE1)#define UART_DISABLE_RX_INT0() (IE1 &= ~URXIE0)#define UART_DISABLE_RX_INT1() (IE2 &= ~URXIE1)#define UART_ENABLE_TX_INT0() (IE1 |= UTXIE0)#define UART_ENABLE_TX_INT1() (IE2 |= UTXIE1)#define UART_DISABLE_TX_INT0() (IE1 &= ~UTXIE0)#define UART_DISABLE_TX_INT1() (IE2 &= ~UTXIE1)#define TX_REG0 U0TXBUF#define TX_REG1 U1TXBUF#define RX_REG0 U0RXBUF#define RX_REG1 U1RXBUF/*#define CMOD_1(baud) (DESIRED_FREQ / ((baud) - (BAUD_DIV(baud))))#define M0_1(baud) ((CMOD_1(baud) + CMOD_1(baud)))#define M1_1(baud) ((M0_1(baud)) + (CMOD_1(baud)))#define M2_1(baud) ((M1_1(baud)) + (CMOD_1(baud)))#define M3_1(baud) ((M2_1(baud)) + (CMOD_1(baud)))#define M4_1(baud) ((M3_1(baud)) + (CMOD_1(baud)))#define M5_1(baud) ((M4_1(baud)) + (CMOD_1(baud)))#define M6_1(baud) ((M5_1(baud)) + (CMOD_1(baud)))#define M7_1(baud) ((M6_1(baud)) + (CMOD_1(baud)))#define C0_1(baud) (uint8_t)((int)(M0_1(baud)) ? (BV(0)) : 0)#define C1_1(baud) (uint8_t)(((int)(M1_1(baud)) - (int)(M0_1(baud))) ? (BV(1)) : 0)#define C2_1(baud) (uint8_t)(((int)(M2_1(baud)) - (int)(M1_1(baud))) ? (BV(2)) : 0)#define C3_1(baud) (uint8_t)(((int)(M3_1(baud)) - (int)(M2_1(baud))) ? (BV(3)) : 0)#define C4_1(baud) (uint8_t)(((int)(M4_1(baud)) - (int)(M3_1(baud))) ? (BV(4)) : 0)#define C5_1(baud) (uint8_t)(((int)(M5_1(baud)) - (int)(M4_1(baud))) ? (BV(5)) : 0)#define C6_1(baud) (uint8_t)(((int)(M6_1(baud)) - (int)(M5_1(baud))) ? (BV(6)) : 0)#define C7_1(baud) (uint8_t)(((int)(M7_1(baud)) - (int)(M6_1(baud))) ? (BV(7)) : 0)#define BAUD_MOD(baud) (uint8_t)((C7_1(baud)) + (C6_1(baud)) + (C5_1(baud)) + \ (C4_1(baud)) + (C3_1(baud)) + (C2_1(baud)) + \ (C1_1(baud)) + (C0_1(baud)))#define BAUD_DIV(baud) (uint16_t)(DESIRED_FREQ / (baud))*/#else#error This platform needs a UART implementation#endif// here are the prototypes of the functions in the state machinesstatic void rx_state_preamble0(void);static void tx_state_preamble0(void);static void rx_state_size0(void);static void tx_state_size0(void);static void rx_state_data0(void);static void tx_state_data0(void);static void rx_state_preamble1(void);static void tx_state_preamble1(void);static void rx_state_size1(void);static void tx_state_size1(void);static void rx_state_data1(void);static void tx_state_data1(void);#ifdef NEED_RAW_MODEstatic void rx_raw0(void);static void tx_raw0(void);static void rx_raw1(void);static void tx_raw1(void);#define uart_read_helper(uart_num, buf, count) \ uint8_t ret = 0; \ mos_mutex_lock(&if_send_mutexes[IFACE_SERIAL + uart_num]); \ rx_raw_max##uart_num = count; \ rx_index##uart_num = 0; \ rx_raw_buf##uart_num = buf; \ UART_ENABLE_RX_INT##uart_num(); \ mos_sem_wait(&rx_sem##uart_num); \ UART_DISABLE_RX_INT##uart_num(); \ ret = rx_index##uart_num; \ mos_mutex_unlock(&if_send_mutexes[IFACE_SERIAL + uart_num]); \ return ret;#define uart_read_nolock_helper(uart_num, buf, count) \ uint8_t ret = 0; \ rx_raw_max##uart_num = count; \ rx_index##uart_num = 0; \ rx_raw_buf##uart_num = buf; \ UART_ENABLE_RX_INT##uart_num(); \ mos_sem_wait(&rx_sem##uart_num); \ UART_DISABLE_RX_INT##uart_num(); \ ret = rx_index##uart_num; \ return ret;#define uart_write_helper(uart_num, buf, count) \ uint8_t ret = 0; \ mos_mutex_lock(&if_send_mutexes[IFACE_SERIAL + uart_num]); \ tx_raw_max##uart_num = count; \ tx_index##uart_num = 0; \ tx_raw_buf##uart_num = buf; \ UART_ENABLE_TX_INT##uart_num(); \ mos_sem_wait(&tx_sem##uart_num); \ UART_DISABLE_TX_INT##uart_num(); \ ret = tx_index##uart_num; \ mos_mutex_unlock(&if_send_mutexes[IFACE_SERIAL + uart_num]); \ return ret;#define uart_write_nolock_helper(uart_num, buf, count) \ uint8_t ret = 0; \ tx_raw_max##uart_num = count; \ tx_index##uart_num = 0; \ tx_raw_buf##uart_num = buf; \ UART_ENABLE_TX_INT##uart_num(); \ mos_sem_wait(&tx_sem##uart_num); \ UART_DISABLE_TX_INT##uart_num(); \ ret = tx_index##uart_num; \ return ret;uint8_t uart_read0(uint8_t *buf, uint8_t count){ uart_read_helper(0, buf, count);}uint8_t uart_read_nolock0(uint8_t *buf, uint8_t count){ uart_read_nolock_helper(0, buf, count);}uint8_t uart_write0(uint8_t *buf, uint8_t count){ uart_write_helper(0, buf, count);}uint8_t uart_write_nolock0(uint8_t *buf, uint8_t count){ uart_write_nolock_helper(0, buf, count);}uint8_t uart_read1(uint8_t *buf, uint8_t count){ uart_read_helper(1, buf, count); }uint8_t uart_read_nolock1(uint8_t *buf, uint8_t count){ uart_read_nolock_helper(1, buf, count);}uint8_t uart_write1(uint8_t *buf, uint8_t count){ uart_write_helper(1, buf, count);}uint8_t uart_write_nolock1(uint8_t *buf, uint8_t count){ uart_write_nolock_helper(1, buf, count);}#endif#ifdef ARCH_AVRstatic void uart_set_baud(uint8_t uart_num, uint16_t baud_rate){ if(uart_num == UART0) { UBRR0H = (uint8_t)(baud_rate >> 8); UBRR0L = (uint8_t)(baud_rate); } else { UBRR1H = (uint8_t)(baud_rate >> 8); UBRR1L = (uint8_t)(baud_rate); }}void uart_init(void){ // Setup the default baud rate uart_set_baud(UART0, DEFAULT_BAUD_RATE); uart_set_baud(UART1, DEFAULT_BAUD_RATE); // async, no parity, 8 bits#ifdef CLOCK_SPEED_4_0 UCSR0A |= (1 << U2X); UCSR1A |= (1 << U2X);#endif UCSR0C = (3 << UCSZ00); UCSR1C = (1 << UCSZ11) | (1 << UCSZ10); // Turn off the transmitter and receiver by default UCSR0B = 0; UCSR1B = 0; mos_sem_init(&tx_sem0, 0); mos_sem_init(&tx_sem1, 0); mos_sem_init(&rx_sem0, 0); mos_sem_init(&rx_sem1, 0); rx_state0 = rx_state_preamble0; tx_state0 = tx_state_preamble0; com_swap_bufs(IFACE_SERIAL, (comBuf *)NULL, &rx_buf0); rx_state1 = rx_state_preamble1; tx_state1 = tx_state_preamble1; com_swap_bufs(IFACE_SERIAL2, (comBuf *)NULL, &rx_buf1);}#elif defined(PLATFORM_TELOSB)#define uart_set_baud(uart_num, baud_rate) { \ if(uart_num == UART0) { \ UMCTL0 = UMCTL_INIT; \ UBR10 = UBR1_INIT; \ UBR00 = UBR0_INIT; \ } else { \ UMCTL1 = UMCTL_INIT; \ UBR11 = UBR1_INIT; \ UBR01 = UBR0_INIT; \ } \ } void uart_init(void){ // enter reset mode U0CTL = SWRST; U1CTL = SWRST; // 8 bit data, no parity U0CTL |= CHAR; U1CTL |= CHAR; // source off SMCLK U0TCTL = SSEL_2; U1TCTL = SSEL_2; uart_set_baud(UART0, DEFAULT_BAUD_RATE); uart_set_baud(UART1, DEFAULT_BAUD_RATE); // enable modules ME1 |= UTXE0 | URXE0; ME2 |= UTXE1 | URXE1; // init recv control registers U0RCTL = 0; U1RCTL = 0; // set peripheral mode for uart tx/rx pins P3SEL |= (1 << 4) | (1 << 5); P3SEL |= (1 << 6) | (1 << 7); // enable interrupts (still in reset state) IE1 |= URXIE0; IE2 |= URXIE1; mos_sem_init(&rx_sem0, 0); mos_sem_init(&rx_sem1, 0); mos_sem_init(&tx_sem0, 0); mos_sem_init(&tx_sem1, 0); rx_state0 = rx_state_preamble0; tx_state0 = tx_state_preamble0; com_swap_bufs(IFACE_SERIAL, (comBuf *)NULL, &rx_buf0); rx_state1 = rx_state_preamble1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -