📄 mn10300_serial.c
字号:
{ 0, 0 }, // 1800 { 0, 0 }, // 2400 { 0, 0 }, // 3600 { 110, 56 }, // 4800 { 0, 0 }, // 7200 { 110, 28 }, // 9600 { 0, 0 }, // 14400 { 71, 21 }, // 19200 { 102, 7 }, // 38400 { 0, 0 }, // 57600 { 9, 26 }, // 115200 { 0, 0 }, // 230400};#else#error Unsupported MN10300 variant#endif//-------------------------------------------------------------------------// Info for each serial device controlledtypedef struct mn10300_serial_info { CYG_ADDRWORD base; CYG_ADDRWORD timer_base; CYG_WORD timer_select; CYG_WORD rx_int; CYG_WORD tx_int; cyg_bool is_serial2; cyg_interrupt rx_interrupt; cyg_interrupt tx_interrupt; cyg_handle_t rx_interrupt_handle; cyg_handle_t tx_interrupt_handle;#ifdef CYG_HAL_MN10300_SERIAL_RX_FIFO volatile cyg_int32 fifo_head; volatile cyg_int32 fifo_tail; volatile cyg_uint8 fifo[16];#endif } mn10300_serial_info;//-------------------------------------------------------------------------// Callback functions exported by this driverstatic SERIAL_FUNS(mn10300_serial_funs, mn10300_serial_putc, mn10300_serial_getc, mn10300_serial_set_config, mn10300_serial_start_xmit, mn10300_serial_stop_xmit );//-------------------------------------------------------------------------// Hardware info for each serial line#ifndef CYGPKG_HAL_MN10300_AM31_STDEVAL1#ifdef CYGPKG_IO_SERIAL_MN10300_SERIAL0static mn10300_serial_info mn10300_serial_info0 = { SERIAL0_BASE, TIMER0_BASE, SERIAL0_TIMER_SELECT, CYGNUM_HAL_INTERRUPT_SERIAL_0_RX, CYGNUM_HAL_INTERRUPT_SERIAL_0_TX, false};#if CYGNUM_IO_SERIAL_MN10300_SERIAL0_BUFSIZE > 0static unsigned char mn10300_serial_out_buf0[CYGNUM_IO_SERIAL_MN10300_SERIAL0_BUFSIZE];static unsigned char mn10300_serial_in_buf0[CYGNUM_IO_SERIAL_MN10300_SERIAL0_BUFSIZE];#endif#endif // CYGPKG_IO_SERIAL_MN10300_SERIAL0#endif#ifdef CYGPKG_IO_SERIAL_MN10300_SERIAL1static mn10300_serial_info mn10300_serial_info1 = { SERIAL1_BASE, TIMER1_BASE, SERIAL1_TIMER_SELECT, CYGNUM_HAL_INTERRUPT_SERIAL_1_RX, CYGNUM_HAL_INTERRUPT_SERIAL_1_TX, false};#if CYGNUM_IO_SERIAL_MN10300_SERIAL1_BUFSIZE > 0static unsigned char mn10300_serial_out_buf1[CYGNUM_IO_SERIAL_MN10300_SERIAL1_BUFSIZE];static unsigned char mn10300_serial_in_buf1[CYGNUM_IO_SERIAL_MN10300_SERIAL1_BUFSIZE];#endif#endif // CYGPKG_IO_SERIAL_MN10300_SERIAL1#ifdef CYGPKG_IO_SERIAL_MN10300_SERIAL2static mn10300_serial_info mn10300_serial_info2 = { SERIAL2_BASE, TIMER2_BASE, SERIAL2_TIMER_SELECT, CYGNUM_HAL_INTERRUPT_SERIAL_2_RX, CYGNUM_HAL_INTERRUPT_SERIAL_2_TX, true};#if CYGNUM_IO_SERIAL_MN10300_SERIAL2_BUFSIZE > 0static unsigned char mn10300_serial_out_buf2[CYGNUM_IO_SERIAL_MN10300_SERIAL2_BUFSIZE];static unsigned char mn10300_serial_in_buf2[CYGNUM_IO_SERIAL_MN10300_SERIAL2_BUFSIZE];#endif#endif // CYGPKG_IO_SERIAL_MN10300_SERIAL2//-------------------------------------------------------------------------// Channel descriptions:#ifdef CYGPKG_IO_SERIAL_MN10300_POLLED_MODE#define SIZEOF_BUF(_x_) 0#else#define SIZEOF_BUF(_x_) sizeof(_x_)#endif#ifndef CYGPKG_HAL_MN10300_AM31_STDEVAL1#ifdef CYGPKG_IO_SERIAL_MN10300_SERIAL0#if CYGNUM_IO_SERIAL_MN10300_SERIAL0_BUFSIZE > 0static SERIAL_CHANNEL_USING_INTERRUPTS(mn10300_serial_channel0, mn10300_serial_funs, mn10300_serial_info0, CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_MN10300_SERIAL0_BAUD), CYG_SERIAL_STOP_DEFAULT, CYG_SERIAL_PARITY_DEFAULT, CYG_SERIAL_WORD_LENGTH_DEFAULT, CYG_SERIAL_FLAGS_DEFAULT, &mn10300_serial_out_buf0[0], SIZEOF_BUF(mn10300_serial_out_buf0), &mn10300_serial_in_buf0[0], SIZEOF_BUF(mn10300_serial_in_buf0) );#elsestatic SERIAL_CHANNEL(mn10300_serial_channel0, mn10300_serial_funs, mn10300_serial_info0, CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_MN10300_SERIAL0_BAUD), CYG_SERIAL_STOP_DEFAULT, CYG_SERIAL_PARITY_DEFAULT, CYG_SERIAL_WORD_LENGTH_DEFAULT, CYG_SERIAL_FLAGS_DEFAULT );#endif#endif // CYGPKG_IO_SERIAL_MN10300_SERIAL0#endif #ifdef CYGPKG_IO_SERIAL_MN10300_SERIAL1#if CYGNUM_IO_SERIAL_MN10300_SERIAL1_BUFSIZE > 0static SERIAL_CHANNEL_USING_INTERRUPTS(mn10300_serial_channel1, mn10300_serial_funs, mn10300_serial_info1, CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_MN10300_SERIAL1_BAUD), CYG_SERIAL_STOP_DEFAULT, CYG_SERIAL_PARITY_DEFAULT, CYG_SERIAL_WORD_LENGTH_DEFAULT, CYG_SERIAL_FLAGS_DEFAULT, &mn10300_serial_out_buf1[0], SIZEOF_BUF(mn10300_serial_out_buf1), &mn10300_serial_in_buf1[0], SIZEOF_BUF(mn10300_serial_in_buf1) );#elsestatic SERIAL_CHANNEL(mn10300_serial_channel1, mn10300_serial_funs, mn10300_serial_info1, CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_MN10300_SERIAL1_BAUD), CYG_SERIAL_STOP_DEFAULT, CYG_SERIAL_PARITY_DEFAULT, CYG_SERIAL_WORD_LENGTH_DEFAULT, CYG_SERIAL_FLAGS_DEFAULT );#endif#endif // CYGPKG_IO_SERIAL_MN10300_SERIAL1#ifdef CYGPKG_IO_SERIAL_MN10300_SERIAL2#if CYGNUM_IO_SERIAL_MN10300_SERIAL2_BUFSIZE > 0static SERIAL_CHANNEL_USING_INTERRUPTS(mn10300_serial_channel2, mn10300_serial_funs, mn10300_serial_info2, CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_MN10300_SERIAL2_BAUD), CYG_SERIAL_STOP_DEFAULT, CYG_SERIAL_PARITY_DEFAULT, CYG_SERIAL_WORD_LENGTH_DEFAULT, CYG_SERIAL_FLAGS_DEFAULT, &mn10300_serial_out_buf2[0], SIZEOF_BUF(mn10300_serial_out_buf2), &mn10300_serial_in_buf2[0], SIZEOF_BUF(mn10300_serial_in_buf2) );#elsestatic SERIAL_CHANNEL(mn10300_serial_channel2, mn10300_serial_funs, mn10300_serial_info2, CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_MN10300_SERIAL2_BAUD), CYG_SERIAL_STOP_DEFAULT, CYG_SERIAL_PARITY_DEFAULT, CYG_SERIAL_WORD_LENGTH_DEFAULT, CYG_SERIAL_FLAGS_DEFAULT );#endif#endif // CYGPKG_IO_SERIAL_MN10300_SERIAL2 //-------------------------------------------------------------------------// And finally, the device table entries:#ifndef CYGPKG_HAL_MN10300_AM31_STDEVAL1#ifdef CYGPKG_IO_SERIAL_MN10300_SERIAL0// On the standard eval board serial0 is not connected. If enabled, it// generates continuous frame error and overrun interrupts. Hence we do// not touch it.DEVTAB_ENTRY(mn10300_serial_io0, CYGDAT_IO_SERIAL_MN10300_SERIAL0_NAME, 0, // Does not depend on a lower level interface &cyg_io_serial_devio, mn10300_serial_init, mn10300_serial_lookup, // Serial driver may need initializing &mn10300_serial_channel0 );#endif // CYGPKG_IO_SERIAL_MN10300_SERIAL0#endif#ifdef CYGPKG_IO_SERIAL_MN10300_SERIAL1DEVTAB_ENTRY(mn10300_serial_io1, CYGDAT_IO_SERIAL_MN10300_SERIAL1_NAME, 0, // Does not depend on a lower level interface &cyg_io_serial_devio, mn10300_serial_init, mn10300_serial_lookup, // Serial driver may need initializing &mn10300_serial_channel1 );#endif // CYGPKG_IO_SERIAL_MN10300_SERIAL1#ifdef CYGPKG_IO_SERIAL_MN10300_SERIAL2DEVTAB_ENTRY(mn10300_serial_io2, CYGDAT_IO_SERIAL_MN10300_SERIAL2_NAME, 0, // Does not depend on a lower level interface &cyg_io_serial_devio, mn10300_serial_init, mn10300_serial_lookup, // Serial driver may need initializing &mn10300_serial_channel2 );#endif // CYGPKG_IO_SERIAL_MN10300_SERIAL2//-------------------------------------------------------------------------// Read the serial line's status register. Serial 2 has an 8 bit status// register while serials 0 and 1 have 16 bit registers. This function// uses the correct size access, but passes back a 16 bit quantity for// both.static cyg_uint16 mn10300_read_sr( mn10300_serial_info *mn10300_chan ){ cyg_uint16 sr = 0; if( mn10300_chan->is_serial2 ) { cyg_uint8 sr8; HAL_READ_UINT8(mn10300_chan->base+SERIAL_STR, sr8); sr = sr8; } else { HAL_READ_UINT16(mn10300_chan->base+SERIAL_STR, sr); } return sr;}//-------------------------------------------------------------------------static boolmn10300_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init){ mn10300_serial_info *mn10300_chan = (mn10300_serial_info *)chan->dev_priv; cyg_uint16 cr = 0; cyg_uint16 sr; // wait for the device to become quiescent. This could take some time // if the device had been transmitting at a low baud rate. do { sr = mn10300_read_sr(mn10300_chan); } while (sr & (SR_RXF|SR_TXF)); // Disable device entirely. HAL_WRITE_UINT16(mn10300_chan->base+SERIAL_CTR, 0); // Set up the Interrupt Mode Register HAL_WRITE_UINT8(mn10300_chan->base+SERIAL_ICR, 0); // Set up baud rate if( mn10300_chan->is_serial2 ) { // Serial 2 is a bit different from 0 and 1 in the way that the // baud rate is controlled. cyg_uint8 baud_divisor = select_baud_2[new_config->baud].timer2_val; if (baud_divisor == 0) return false; // Invalid baud rate selected HAL_WRITE_UINT8(mn10300_chan->timer_base+TIMER_BR, baud_divisor); HAL_WRITE_UINT8(mn10300_chan->timer_base+TIMER_MD, 0x80 ); baud_divisor = select_baud_2[new_config->baud].serial2_val; HAL_WRITE_UINT8(mn10300_chan->base+SERIAL_TIM, baud_divisor); cr |= mn10300_chan->timer_select; } else { cyg_uint16 baud_divisor = select_baud_01[new_config->baud]; cyg_uint8 timer_mode = 0x80; if (baud_divisor == 0) return false; // Invalid baud rate selected#if defined(CYGPKG_HAL_MN10300_AM33) if( baud_divisor > 255 ) { // The AM33 runs at a higher clock rate than the AM31 and // needs a bigger divisor for low baud rates. We do this by // using timer 0 as a prescaler. We set it to 198 so we can then // use it to prescale for both serial0 and serial1 if they need // it. static int timer0_initialized = 0; baud_divisor /= 198; baud_divisor--; timer_mode = 0x84; if( !timer0_initialized ) { timer0_initialized = 1; HAL_WRITE_UINT8(HW_TIMER0+TIMER_BR, 198 ); HAL_WRITE_UINT8(HW_TIMER0+TIMER_MD, 0x80 ); } }#endif HAL_WRITE_UINT8(mn10300_chan->timer_base+TIMER_BR, baud_divisor); HAL_WRITE_UINT8(mn10300_chan->timer_base+TIMER_MD, timer_mode ); cr |= mn10300_chan->timer_select; }#ifdef PORT3_MD HAL_WRITE_UINT8( PORT3_MD, 0x01 );#endif // set up other config values:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -