📄 eval_rtos.c
字号:
* assuming MCU clock mode is set to "X1" and BDRCON reg bit SPD is 1 (x6 speed)
* and PCON register bit SMOD1 is 1 (double Baud rate).
* Fosc is the external MCU clock or crystal osc. freq.
*
* In this example, the required Baud rate is 38400...
* Fosc = 16MHz, MCU CLK mode is "X1", SMOD1 = 1, SPD = 1.
* BDCLKDIV = (16E+6 / 2) / (16 * 38400) = 13
* BRL = 256 - 13 = 243.
*/
void
initialise_uart( void )
{
/* Install vector for UART interrupt service */
ROM_VECTOR( 0x23, uart_service );
SCON = 0x50; /* Select UART mode 1 (8 bits data); Enable receiver */
Set_Bit( PCON, BIT7 ); /* SMOD1 = 1 (doubles the Baud rate) */
BDRCON = 0x0E; /* Use internal Baud clk (RBCK=TBCK=1); high speed (SPD=1) */
if ( CKCON0 & BIT0 ) BRL = 230; /* MCU clock 'X2' mode => BDCLKDIV = 26 */
else BRL = 243; /* MCU clock 'X1' mode => BDCLKDIV = 13 */
Set_Bit( gubMiscFlags, SCI_TXRDY ); /* Indicate transmitter is ready now */
Set_Bit( IEN0, BIT4 ); /* Enable UART interrupt (TX and RX) */
Set_Bit( BDRCON, BIT4 ); /* Start Baud clock gen. (RUN=1) */
pcRxTail = acRxFIFObuf; /* Reset RX buffer pointers, byte count */
pcRxHead = acRxFIFObuf;
ubRxCount = 0;
}
/*
* Interrupt Service Routine for 8051 on-chip UART.
*
* If there is a character available in the UART RX register, an interrupt is
* generated and this ISR is called.
* The received char will be read out into a circular (FIFO) buffer in RAM.
*
* The 8051 UART sets the 'Transmit Interrupt' flag (TI) to indicate when the last byte
* has been transmitted, i.e. when the serial "buffer" register (SBUF) can be written to.
* It is not necessary (and quite inconvenient) to use interrupt mode for transmitting
* in this application. However, the primitive 8051 UART does not allow independent
* configuration of TX and RX interrupt modes.
*
* The interrupt service routine simply sets a flag in RAM which mimics the TI flag,
* and clears the TI flag, which is the source of the interrupt.
* The non-interrupt mode UART Transmit function, putch(), uses the RAM flag.
*/
interrupt
uart_service( void )
{
if ( Test_Bit( SCON, BIT0 )) /* 'Receive Int' (RI) flag set => RX data register full */
{
Clear_Bit( SCON, BIT0 ); /* Clear 'Receive Int.' (RI) flag */
*pcRxTail++ = SBUF;
if ( pcRxTail >= (acRxFIFObuf + RXBUFSIZE) )
pcRxTail = acRxFIFObuf;
ubRxCount++;
}
else if ( Test_Bit( SCON, BIT1 )) /* 'Transmit Int' (TI) flag set => TX data register empty */
{
Clear_Bit( SCON, BIT1 ); /* Clear 'Transmit Int' (TI) flag */
Set_Bit( gubMiscFlags, SCI_TXRDY );
}
else /* UART Rx interrupt error */
Set_Bit( gwSystemError, SCI_INT_ERROR );
if ( ubRxCount > RXBUFSIZE ) /* Rx buffer overflow */
Set_Bit( gwSystemError, RX_FIFO_OVFL );
}
/*
* Check serial port RAM buffer for RX character available.
*
* Called by: various
* Entry args: --
* Returns: TRUE if char available, else FALSE
* Affects: --
*/
bool
uart_rx_data_avail( void )
{
if ( ubRxCount )
return TRUE;
else return FALSE;
}
/*
* Function: uart_getch()
*
* Get character from host serial receive RAM buffer. It is assumed the buffer contains
* unread data, as may be established by a prior call to uart_rx_data_avail().
* The function does not wait for input; if the RX buffer is empty, the function
* returns 0xFF (-1), otherwise it returns the character code and adjusts buffer pointers.
* The character is NOT echoed... (see also uart_getche() ).
*
* Called by: CLI functions
* Entry args: --
* Returns: (char) character received, or -1 (0xFF) if none in buffer.
*/
char
uart_getch( void )
{
char c;
if ( uart_rx_data_avail() )
{
Clear_Bit( IEN0, BIT4 ); /* Disable UART interrupt during buffer read */
c = *pcRxHead++;
if ( pcRxHead >= (acRxFIFObuf + RXBUFSIZE) )
pcRxHead = acRxFIFObuf;
--ubRxCount;
Set_Bit( IEN0, BIT4 ); /* Enable UART interrupt */
}
else c = (char) ERROR;
return c;
}
/*
* Function: uart_getche()
*
* Get character from host serial receive RAM buffer. It is assumed the buffer contains
* unread data, as may be established by a prior call to uart_rx_data_avail().
* The function does not wait for input; if the RX buffer is empty, the function
* returns 0xFF (-1), otherwise it returns the character code and adjusts buffer pointers.
* The character is echoed to the UART transmitter.
*
* Called by: CLI functions
* Entry args: --
* Returns: (char) character received, or 0xFF if none in buffer.
*/
char
uart_getche( void )
{
char c = uart_getch();
putch( c );
return c;
}
/*
* Function: usb_vuart_getche()
*
* Get character from USB "virtual UART" RX buffer. It is assumed the buffer contains
* unread data, as may be established by a prior call to usb_vuart_rx_data_avail().
* NB: If there is no data ready in the USB RX buffer, the function will wait indefinitely!
* The character is echoed to the USB transmit buffer and the TX buffer is flushed so that
* the char is sent to the host immediately. (We don't want to wait for TX buffer full.)
*
* Called by: CLI functions
* Entry args: --
* Returns: (char) character received.
*/
char
usb_vuart_getche( void )
{
char c = usb_vuart_getchar();
putch( c );
usb_vuart_flush();
return c;
}
/*
* Function: hci_data_avail
*
* Purpose: Checks for received data available from selected HCI stream (UART or USB).
* Called by: CLI command functions (only).
*
* The input source port (USB or UART) is determined by the variable gbHCI_Stream.
* If gbHCI_Stream is UART_HOST_LINK, the function checks the UART RX buffer,
* otherwise it checks the USB RX buffer.
*
* Entry args: --
* Returns: (bool) TRUE if data is available from the selected input stream, else FALSE.
* Affects: --
*/
bool
hci_data_avail( void )
{
bool yResult = FALSE;
if ( gbHCI_Stream == UART_HOST_LINK && uart_rx_data_avail() )
yResult = TRUE;
else if ( gbHCI_Stream == USB_HOST_LINK && usb_vuart_rx_data_avail() )
yResult = TRUE;
return ( yResult );
}
/*
* Function: getch
* Purpose: Wait for and fetch a char from "Service Port" (selected stream, UART or USB)
*
* The input source port (USB or UART) is determined by the variable gbHCI_Stream.
* If gbHCI_Stream is UART_HOST_LINK, the function inputs via the UART, else via the USB port.
* The input character is not echoed to the host.
*
* While waiting for input, the "background process" (B/G task dispatcher) is called, so as
* not to delay background tasks. NB: To avoid the possibility of infinite recursion,
* neither putch() nor getch() can be called from the "background process" routine.
*
* Called by: CLI command functions (only)
* Entry args: --
* Returns: (char) c = inputted byte
* Affects: --
*/
char
getch( void )
{
char c;
if ( gbHCI_Stream == UART_HOST_LINK )
{
while ( !uart_rx_data_avail() )
{
background_process(); /* wait for char to arrive in UART RX buffer */
}
c = uart_getch();
}
else /* Assume gbHCI_Stream == USB_HOST_LINK */
{
while ( !usb_vuart_rx_data_avail() )
{
background_process(); /* wait for char to arrive in USB RX buffer */
}
c = usb_vuart_getchar();
}
return ( c );
}
/*
* Function: putch
* Purpose: Output 8-bit char via "Service Port" UART or the USB port.
* Called by: CLI command functions (only).
*
* The output destination port (USB or UART) is determined by the variable gbHCI_Stream.
*
* If gbHCI_Stream is UART_HOST_LINK, the function waits for UART TX interrupt (ISR)
* to set the flag SCI_TXRDY ... up to a time limit.
* The time limit ensures that the char will be transmitted, and the function will return,
* in the event that the 'Transmit Interrupt' flag (TI) remains in the low state.
* While waiting, the "background process" (B/G task dispatcher) is called, so as not to
* delay background tasks. NB: To avoid the possibility of infinite recursion, putch()
* cannot be called from any "scheduled" background task.
*
* The character code is added (modulo 256) to a global "response checksum" byte, for
* applications that require response data integrity checking by the host PC.
*
* Called by: CLI command functions
* Entry args: (char) c = byte to be transmitted (8 bits)
* Returns: (char) c
* Affects: gubRespCksm, gubMiscFlags<SCI_TXRDY>
*/
char
putch( char c )
{
int8 bLoopCount = 100; /* Arbitrary loop "time-out" */
if ( gbHCI_Stream == UART_HOST_LINK )
{
while ( --bLoopCount > 0 ) /* Loop until time-out occurs */
{
if ( Test_Bit( gubMiscFlags, SCI_TXRDY ) ) /* Transmitter is ready */
break;
background_process();
}
SBUF = c; /* Write char in TX register, regardless */
Clear_Bit( SCON, BIT1 ); /* Clear TI flag */
Clear_Bit( gubMiscFlags, SCI_TXRDY );
}
else if ( gbHCI_Stream == USB_HOST_LINK )
{
usb_vuart_putchar( c );
if ( c == LF ) usb_vuart_flush();
background_process();
}
gubRespCksm += c;
return ( c );
}
/*********** DEVICE DRIVERS FOR CONTROL SURFACE SWITCHES AND LED INDICATORS *************/
/*****
* Returns TRUE if "INT0" button hit.
* The INT0 button is wired to the MCU input pin P3.2 (external interrupt is disabled).
*/
bool
Button_INT0_hit( void )
{
/*** to be developed ***/
return FALSE;
}
/*****
* Returns TRUE if "TEST" button hit
* The INT0 button is wired to the MCU input pin P1.2 (active Low input).
*/
bool
Button_TEST_hit( void )
{
/*** to be developed ***/
return FALSE;
}
/*************** DEVICE DRIVER FOR CONTROL SURFACE LED ANNUNCIATORS ********************
*
* The LED driver provides a selection of modes for each LED independently, i.e.
* ON, OFF or flashing, with selectable flash rate and duty cycle.
* The LED annunciation modes are set by an array of bytes, one byte per LED.
* This method minimises data RAM allocation, to suit low-end MCU applications.
*
* Annunciator mode byte, bit assignments:
*
* BIT | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
* | FLASH | ON | P2 | P1 | P0 | D2 | D1 | D0 |
*
* FLASH (bit7) = 0 : Disable LED flashing; FLASH = 1 : Enable LED flashing.
* ON (bit6) = 0 : LED is OFF; ON = 1 : LED is ON continuously or flashing.
* Bits 0..5 determine the flash rate (period) and on-time duty...
* P2..P0 => Flash Period (one of 8 predefined, see aubLEDFlashDuty)
* D2..D0 => Flash On-time Duty (one of 16 predefined, see kabLEDFlashDuty)
* The Flash Period must be higher than the Flash Duty.
*
* Table of constants to define 8 preset LED flash periods and ON-time duty (TICKS).
* D2..D0 is table index for On-time duty; P2..P0 is table index for flash period.
* (See enumerated constants, e.g. TIME_100mS, in G2test_defs.h)
*/
static const uint8 kabLEDFlashDuty[] = { 10, 20, 40, 50, 80, 100, 160, 200 }; // TICKS
static far uint8 habLEDannuncMode[NUMBER_OF_LEDS]; // Annunciation modes
static far uint8 habLEDflashTimer[NUMBER_OF_LEDS]; // Flash timers (unit = tick)
/*****
* LED_Refresh() maintains the required annunciation modes of control surface LEDs.
* The driver is a periodic foreground task, called by the RTI tick handler.
*/
void
LED_Refresh( void )
{
uint8 bLEDidx; // LED identifier (index)
bool yLEDstate; // Instantaneous LED state (ON/OFF)... to be determined
bool yLEDmode; // ON/OFF mode bit (1 => on)
bool yLEDflash; // Flash mode bit (1 => flashing)
uint8 bFlashOnTime; // ON-time duty for flash mode (ticks)
uint8 bFlashPeriod; // Flash Period (ticks)
for ( bLEDidx = 0; bLEDidx < NUMBER_OF_LEDS; bLEDidx++ )
{
yLEDmode = habLEDannuncMode[bLEDidx] & BIT6;
yLEDflash = habLEDannuncMode[bLEDidx] & BIT7;
bFlashOnTime = kabLEDFlashDuty[ habLEDannuncMode[bLEDidx] & 7 ];
bFlashPeriod = kabLEDFlashDuty[ (habLEDannuncMode[bLEDidx] >> 3) & 7 ];
if ( bFlashOnTime > bFlashPeriod )
bFlashOnTime = bFlashPeriod / 2;
if ( yLEDmode == 0 ) yLEDstate = OFF;
else if ( yLEDflash && habLEDflashTimer[bLEDidx] > bFlashOnTime )
yLEDstate = OFF; // Duty is done
else yLEDstate = ON; // Active duty or on continuously
SetLEDoutput( bLEDidx, yLEDstate );
if ( ++habLEDflashTimer[bLEDidx] >= bFlashPeriod ) // Adjust flash timer
habLEDflashTimer[bLEDidx] = 0;
}
}
/*****
* The functions below set the operational modes of individual LED annunciators, by writing
* to the relevant LED Annunciator Mode byte. These functions are intended to be called from
* higher-level application code. The LED Annunciator Mode array is not directly accessible
* to functions outside of the kernel module (and doesn't need to be).
*
*
* Function: SetLEDmode
* Purpose: Sets LED annunciator mode to continuously ON or OFF;
* cancels flashing mode.
* Arguments:
* ubLEDident : LED identifier, enumerated (see G2test_defs.h).
* yMode : LED ON/OFF mode (0 => OFF, 1 => ON continuous)
*/
void
SetLEDmode( uint8 ubLEDident, bool yMode )
{
if ( ubLEDident < NUMBER_OF_LEDS )
{
Clear_Bit( habLEDannuncMode[ubLEDident], BIT7 ); // cancel flash mode
if ( yMode == 0 )
Clear_Bit( habLEDannuncMode[ubLEDident], BIT6 );
else Set_Bit( habLEDannuncMode[ubLEDident], BIT6 );
}
}
/*
* Function: SetLEDFlashMode
* Purpose: Sets LED annunciator mode to flashing, with specified period and duty time.
* A call to this function starts the LED flashing.
* To cancel flash mode, use the function SetLEDmode(), above.
* Arguments:
* ubLEDident : LED identifier, enumerated (see G2test_defs.h).
* ubPeriod : Flash Period, 0..7 (one of 8 preset times)
* ubDuty : Flash On-time Duty, 0..7 (one of 8 preset times)
*
* Preset flash rates (period & duty times) are enumerated by eLED_FLASH_PRESET_TIME.
* Flash rate can be set from 1Hz up to 20Hz with variable duty cycle (see G2test_defs.h).
*/
void
SetLEDFlashMode( uint8 ubLEDident, uint8 ubPeriod, uint8 ubDuty )
{
uint8 bMode;
if ( ubLEDident < NUMBER_OF_LEDS )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -