📄 duart.c
字号:
/* * $Id: duart.c,v 1.7 1998/08/05 15:12:03 joel Exp $ *//*########################################################### This code is a modified version of what you will find at the# end of the IDP User's manual. The original code is copyrighted# by Motorola and Motorola Semiconductor Products as well as# Motorola Software products group.## Modifications to the original IDP code by Doug McBride, Colorado# Space Grant College. Modifications include a means of accessing# port B of the duart as well as port A as well as modifications for# buffering and RTEMS support. Modifications are provided# as is and may not be correct.## Rob Savoye provided the format for the mc68681 header file## Joel Sherrill provided inspiration for recoding my original assembly# for this file into C (a good idea)###########################################################*/#include <bsp.h>#include <ringbuf.h>rtems_isr C_Receive_ISR(rtems_vector_number vector);extern Ring_buffer_t Console_Buffer[];extern unsigned char inbuf[];extern unsigned char inbuf_portb[];extern unsigned tail;extern unsigned tail_portb;unsigned char Pit_initialized = 0;/*###################################################################### The volatile routine to initialize the duart -- port a and port b######################################################################*/volatile void init_pit(){ /* * ports A & B while configuring PIT by: * * + disable Interrupt Mask Register * + disable port A transmitter * + disable port A receiver * + disable port B transmitter * + disable port B receiver */ MC68681_WRITE(DUART_ADDR, MC68681_INTERRUPT_MASK_REG, 0x00); MC68681_WRITE(DUART_ADDR, MC68681_COMMAND_REG_A ,MC68681_MODE_REG_DISABLE_TX); MC68681_WRITE(DUART_ADDR, MC68681_COMMAND_REG_A, MC68681_MODE_REG_DISABLE_RX); MC68681_WRITE(DUART_ADDR, MC68681_COMMAND_REG_B, MC68681_MODE_REG_DISABLE_TX); MC68681_WRITE(DUART_ADDR, MC68681_COMMAND_REG_B, MC68681_MODE_REG_DISABLE_RX); /* * install ISR for ports A and B */ set_vector(C_Receive_ISR, (VECT+H3VECT), 1); /* * initialize pit * * set mode to 0 -- disable all ports * set up pirq and piack * all pins on port b are input * submode 1x, h3 interrupt enabled * setup pivr * turn on all ports */ MC68230_WRITE(PGCR, 0x00); MC68230_WRITE(PSRR, 0x18); MC68230_WRITE(PBDDR, 0x00); MC68230_WRITE(PBCR, 0x82); MC68230_WRITE(PIVR, VECT); MC68230_WRITE(PGCR, 0x20); /* * For some reason, the reset of receiver/transmitter only works for * the first time around -- it garbles the output otherwise * (e.g., sp21) */ if (!Pit_initialized) { /* * initialize the duart registers on port b * WARNING:OPTIMIZER MAY ONLY EXECUTE THIRD STATEMENT IF NOT VOLATILE * * reset tx, channel b * reset rx, channel b * reset mr pointer, ch */ MC68681_WRITE(DUART_ADDR, MC68681_COMMAND_REG_B, MC68681_MODE_REG_RESET_TX); MC68681_WRITE(DUART_ADDR, MC68681_COMMAND_REG_B, MC68681_MODE_REG_RESET_RX); MC68681_WRITE(DUART_ADDR, MC68681_COMMAND_REG_B, MC68681_MODE_REG_RESET_MR_PTR); /* * initialize the duart registers on port a * WARNING:OPTIMIZER MAY ONLY EXECUTE THIRD STATEMENT IF NOT VOLATILE * * reset tx, channel a * reset rx, channel a * reset mr pointer, ch */ MC68681_WRITE(DUART_ADDR, MC68681_COMMAND_REG_A, MC68681_MODE_REG_RESET_TX); MC68681_WRITE(DUART_ADDR, MC68681_COMMAND_REG_A, MC68681_MODE_REG_RESET_RX); MC68681_WRITE(DUART_ADDR, MC68681_COMMAND_REG_A, MC68681_MODE_REG_RESET_MR_PTR); Pit_initialized = 1; } /* * Init the general registers of the duart * * init ivr * init imr * init acr * init ctur * init ctlr * init opcr * init cts */ MC68681_WRITE(DUART_ADDR, MC68681_INTERRUPT_VECTOR_REG, MC68681_INTERRUPT_VECTOR_INIT); MC68681_WRITE(DUART_ADDR, MC68681_INTERRUPT_MASK_REG, MC68681_IR_RX_READY_A | MC68681_IR_RX_READY_B); MC68681_WRITE(DUART_ADDR, MC68681_AUX_CTRL_REG, MC68681_CLEAR); MC68681_WRITE(DUART_ADDR, MC68681_COUNTER_TIMER_UPPER_REG, 0x00); MC68681_WRITE(DUART_ADDR, MC68681_COUNTER_TIMER_LOWER_REG, 0x02); MC68681_WRITE(DUART_ADDR, MC68681_OUTPUT_PORT_CONFIG_REG, MC68681_CLEAR); MC68681_WRITE(DUART_ADDR, MC68681_OUTPUT_PORT_SET_REG, 0x01); /* * init the actual serial port for port a * * Set Baud Rate to 9600 * Set Stop bit length of 1 * enable Transmit and receive */ MC68681_WRITE(DUART_ADDR, MC68681_CLOCK_SELECT_REG_A, MC68681_BAUD_RATE_MASK_9600); MC68681_WRITE(DUART_ADDR, MC68681_MODE_REG_1A, (MC68681_8BIT_CHARS | MC68681_NO_PARITY)); MC68681_WRITE(DUART_ADDR, MC68681_MODE_REG_2A,MC68681_STOP_BIT_LENGTH_1); MC68681_WRITE(DUART_ADDR, MC68681_COMMAND_REG_A, (MC68681_MODE_REG_ENABLE_TX | MC68681_MODE_REG_ENABLE_RX)); /* * init the actual serial port for port b * init csrb -- 9600 baud */ MC68681_WRITE(DUART_ADDR, MC68681_CLOCK_SELECT_REG_B, MC68681_BAUD_RATE_MASK_9600);#define EIGHT_BITS_NO_PARITY#ifdef EIGHT_BITS_NO_PARITY /* * Set 8 Bit characters with no parity */ MC68681_WRITE(DUART_ADDR, MC68681_MODE_REG_1B, (MC68681_NO_PARITY | MC68681_8BIT_CHARS) );#else /* * Set 7 Bit Characters with parity */ MC68681_WRITE(DUART_ADDR, MC68681_MODE_REG_1B, (MC68681_WITH_PARITY | MC68681_7BIT_CHARS) );#endif /* * Set Stop Bit length to 1 * Disable Recieve and transmit on B */ MC68681_WRITE(DUART_ADDR, MC68681_MODE_REG_2B,MC68681_STOP_BIT_LENGTH_1); MC68681_WRITE(DUART_ADDR, MC68681_COMMAND_REG_B, (MC68681_MODE_REG_ENABLE_TX | MC68681_MODE_REG_ENABLE_RX) );}/*###################################################################### interrupt handler for receive of character from duart on ports A & B#####################################################################*/rtems_isr C_Receive_ISR(rtems_vector_number vector){ volatile unsigned char *_addr; /* * Clear pit interrupt. */ _addr = (unsigned char *) (PIT_ADDR + PITSR); *_addr = 0x04; /* * check port A first for input * extract rcvrdy on port B * set ptr to recieve buffer and read character into ring buffer */ _addr = (unsigned char *) (DUART_ADDR + MC68681_STATUS_REG_A); if (*_addr & MC68681_RX_READY) /* extract rcvrdy on port A */ { _addr = (unsigned char *) (DUART_ADDR + MC68681_RECEIVE_BUFFER_A); Ring_buffer_Add_character( &Console_Buffer[ 0 ], *_addr ); } /* * If not on port A, let's check port B * extract rcvrdy on port B * set ptr to recieve buffer and read character into ring buffer */ else { _addr = (unsigned char *) (DUART_ADDR + MC68681_STATUS_REG_B); if (*_addr & MC68681_RX_READY) /* extract rcvrdy on port B */ { _addr = (unsigned char *) (DUART_ADDR + MC68681_RECEIVE_BUFFER_B); Ring_buffer_Add_character( &Console_Buffer[ 1 ], *_addr ); } /* * if not ready on port A or port B, must be an error * if error, get out so that fifo is undisturbed */ }}/*###################################################################### This is the routine that actually transmits a character one at a time# This routine transmits on port A of the IDP board#####################################################################*/void transmit_char(char ch){ volatile unsigned char *_addr; /* * Get SRA (extract txrdy) */ _addr = (unsigned char *) (DUART_ADDR + MC68681_STATUS_REG_A); while (!(*_addr & MC68681_TX_READY)) { } /* * transmit character over port A */ MC68681_WRITE(DUART_ADDR, MC68681_TRANSMIT_BUFFER_A, ch);}/*###################################################################### This is the routine that actually transmits a character one at a time# This routine transmits on port B of the IDP board#####################################################################*/void transmit_char_portb(char ch){ volatile unsigned char *_addr; /* * Get SRB (extract txrdy) */ _addr = (unsigned char *) (DUART_ADDR + MC68681_STATUS_REG_B); while (!(*_addr & MC68681_TX_READY)) { } /* * transmit character over port B */ MC68681_WRITE(DUART_ADDR, MC68681_TRANSMIT_BUFFER_B, ch);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -