int hal_enable_profile_timer(int resolution) { // Run periodic timer interrupt for profile cyg_uint16 piscr; int period = resolution / 100; // Attach pit arbiter. HAL_INTERRUPT_ATTACH (PIT_IRQ, &hal_arbitration_isr_pit, ID_PIT, 0); HAL_INTERRUPT_UNMASK (PIT_IRQ); // Attach pit isr. HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_SIU_PIT, &isr_pit, ID_PIT, 0); HAL_INTERRUPT_SET_LEVEL (CYGNUM_HAL_INTERRUPT_SIU_PIT, PIT_IRQ_LEVEL); HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_SIU_PIT); // Set period. HAL_WRITE_UINT32 (CYGARC_REG_IMM_PITC, (2*period) << CYGARC_REG_IMM_PITC_COUNT_SHIFT); // Enable. HAL_READ_UINT16 (CYGARC_REG_IMM_PISCR, piscr); piscr |= CYGARC_REG_IMM_PISCR_PTE; HAL_WRITE_UINT16 (CYGARC_REG_IMM_PISCR, piscr); return resolution; }
externC void cyg_drv_interrupt_attach( cyg_handle_t interrupt ) { cyg_interrupt *intr = (cyg_interrupt *)interrupt; CYG_REPORT_FUNCTION(); CYG_ASSERT( intr->vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); CYG_ASSERT( intr->vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); HAL_INTERRUPT_SET_LEVEL( intr->vector, intr->priority ); #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN CYG_ASSERT( intr->next == NULL , "cyg_interrupt already on a list"); { cyg_uint32 index; HAL_TRANSLATE_VECTOR( intr->vector, index ); if( chain_list[index] == NULL ) { // First Interrupt on this chain, just assign it and // register the chain_isr with the HAL. chain_list[index] = intr; HAL_INTERRUPT_ATTACH( intr->vector, chain_isr, &chain_list[index], NULL ); } else { // There are already interrupts chained, add this one into // the chain in priority order. cyg_interrupt **p = &chain_list[index]; while( *p != NULL ) { cyg_interrupt *n = *p; if( n->priority < intr->priority ) break; p = &n->next; } intr->next = *p; *p = intr; } } #else HAL_INTERRUPT_ATTACH( intr->vector, intr->isr, intr->data, intr ); #endif CYG_REPORT_RETURN(); }
externC void hal_variant_IRQ_init(void) { // Mask off everything. This guarantees that we can safely install a handler on the decrementer // later on HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_IRQ0); HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_IRQ1); HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_IRQ2); HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_IRQ3); HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_IRQ4); HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_IRQ5); HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_IRQ6); HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_IRQ7); HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_LVL0); HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_LVL1); HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_LVL2); HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_LVL3); HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_LVL4); HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_LVL5); HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_LVL6); HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_LVL7); #ifdef CYGSEM_HAL_POWERPC_MPC5XX_IMB3_ARBITER HAL_INTERRUPT_ATTACH(CYGNUM_HAL_INTERRUPT_SIU_LVL7, hal_arbitration_imb3, &imb3_data_head, 0); HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_SIU_LVL7); #endif #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \ || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) // GDB-CTRLC // Install a default arbiter for serial interrupts. This allows // to make a boot monitor simply turn on the required Rx interrupt // and still be delivered the necessary default isr. Without this, // redboot would be informed of a level interrupt on the SIU instead // of the Rx interrupt that really happened. // Make sure the interrupts are set up on the correct level sci_arbiter.priority = CYGNUM_HAL_ISR_SOURCE_PRIORITY_QSCI; sci_arbiter.data = 0; sci_arbiter.arbiter = hal_arbitration_isr_sci; hal_mpc5xx_install_arbitration_isr(&sci_arbiter); HAL_INTERRUPT_SET_LEVEL(CYGNUM_HAL_INTERRUPT_IMB3_SCI0_RX, CYGNUM_HAL_ISR_SOURCE_PRIORITY_QSCI); HAL_INTERRUPT_SET_LEVEL(CYGNUM_HAL_INTERRUPT_IMB3_SCI0_RX, CYGNUM_HAL_ISR_SOURCE_PRIORITY_QSCI); #endif }
static int cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) { static int irq_state = 0; channel_data_t* chan = (channel_data_t*)__ch_data; int ret = 0; CYGARC_HAL_SAVE_GP(); switch (__func) { case __COMMCTL_GETBAUD: ret = chan->baud_rate; break; case __COMMCTL_SETBAUD: { va_list ap; va_start(ap, __func); ret = chan->baud_rate; chan->baud_rate = va_arg(ap, cyg_int32); init_serial_channel(chan); va_end(ap); } break; case __COMMCTL_IRQ_ENABLE: HAL_INTERRUPT_SET_LEVEL(chan->imb3_vector, chan->level); HAL_INTERRUPT_UNMASK(chan->imb3_vector); HAL_INTERRUPT_UNMASK(chan->siu_vector); irq_state = 1; break; case __COMMCTL_IRQ_DISABLE: ret = irq_state; irq_state = 0; HAL_INTERRUPT_MASK(chan->imb3_vector); HAL_INTERRUPT_MASK(chan->siu_vector); break; case __COMMCTL_DBG_ISR_VECTOR: ret = chan->siu_vector; break; case __COMMCTL_SET_TIMEOUT: { va_list ap; va_start(ap, __func); ret = chan->msec_timeout; chan->msec_timeout = va_arg(ap, cyg_uint32); va_end(ap); } break; default: break; } CYGARC_HAL_RESTORE_GP(); return ret; }
static void hal_ctrlc_isr_init(void) { // cyg_uint16 cr; // HAL_READ_UINT16( SERIAL_CR, cr ); // cr |= LCR_RXE; // HAL_WRITE_UINT16( SERIAL_CR, cr ); HAL_INTERRUPT_SET_LEVEL( CYGHWR_HAL_GDB_PORT_VECTOR, 4 ); HAL_INTERRUPT_UNMASK( CYGHWR_HAL_GDB_PORT_VECTOR ); }
externC void cyg_drv_interrupt_level( cyg_vector_t vector, cyg_priority_t level ) { CYG_REPORT_FUNCTION(); CYG_REPORT_FUNCARG2("vector = %d, level = %d", vector, level); CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); HAL_INTERRUPT_SET_LEVEL( vector, level ); CYG_REPORT_RETURN(); }
static int cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) { static int irq_state = 0; channel_data_t* chan = (channel_data_t*)__ch_data; int ret = -1; cyg_uint8 ier; va_list ap; CYGARC_HAL_SAVE_GP(); va_start(ap, __func); switch (__func) { case __COMMCTL_GETBAUD: ret = chan->baud_rate; break; case __COMMCTL_SETBAUD: chan->baud_rate = va_arg(ap, cyg_int32); // Should we verify this value here? init_channel(chan); ret = 0; break; case __COMMCTL_IRQ_ENABLE: HAL_INTERRUPT_UNMASK(chan->isr_vector); HAL_INTERRUPT_SET_LEVEL(chan->isr_vector, 1); HAL_READ_UINT8(chan->base+PXA2X0_UART_IER, ier); ier |= PXA2X0_UART_IER_RAVIE; HAL_WRITE_UINT8(chan->base+PXA2X0_UART_IER, ier); irq_state = 1; break; case __COMMCTL_IRQ_DISABLE: ret = irq_state; irq_state = 0; HAL_INTERRUPT_MASK(chan->isr_vector); HAL_READ_UINT8(chan->base+PXA2X0_UART_IER, ier); ier &= ~PXA2X0_UART_IER_RAVIE; HAL_WRITE_UINT8(chan->base+PXA2X0_UART_IER, ier); break; case __COMMCTL_DBG_ISR_VECTOR: ret = chan->isr_vector; break; case __COMMCTL_SET_TIMEOUT: ret = chan->msec_timeout; chan->msec_timeout = va_arg(ap, cyg_uint32); break; default: break; } va_end(ap); CYGARC_HAL_RESTORE_GP(); return ret; }
static int cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) { static int irq_state = 0; channel_data_t* chan = (channel_data_t*)__ch_data; cyg_uint8 ier; int ret = 0; CYGARC_HAL_SAVE_GP(); switch (__func) { case __COMMCTL_IRQ_ENABLE: irq_state = 1; HAL_READ_UINT8(chan->base+CYG_DEVICE_BK0_IER, ier); ier |= CYG_DEVICE_BK0_IER_RXHDL_IE; HAL_WRITE_UINT8(chan->base+CYG_DEVICE_BK0_IER, ier); HAL_INTERRUPT_SET_LEVEL(chan->isr_vector, 1); HAL_INTERRUPT_UNMASK(chan->isr_vector); break; case __COMMCTL_IRQ_DISABLE: ret = irq_state; irq_state = 0; HAL_READ_UINT8(chan->base+CYG_DEVICE_BK0_IER, ier); ier &= ~CYG_DEVICE_BK0_IER_RXHDL_IE; HAL_WRITE_UINT8(chan->base+CYG_DEVICE_BK0_IER, ier); HAL_INTERRUPT_MASK(chan->isr_vector); break; case __COMMCTL_DBG_ISR_VECTOR: ret = chan->isr_vector; break; case __COMMCTL_SET_TIMEOUT: { va_list ap; va_start(ap, __func); ret = chan->msec_timeout; chan->msec_timeout = va_arg(ap, cyg_uint32); va_end(ap); } default: break; } CYGARC_HAL_RESTORE_GP(); return ret; }
externC void hal_variant_IRQ_init(void) { #ifdef CYGSEM_HAL_POWERPC_MPC860_CPM_ENABLE // Attach first-level CPM arbiter to the configured SIU level and // enable CPM interrupts. #define ID_CPM 0xDEAD #define CYGPRI_SIU_LVL (CYGNUM_HAL_INTERRUPT_SIU_LVL0 \ +CYGHWR_HAL_POWERPC_MPC860_CPM_LVL*2) HAL_INTERRUPT_ATTACH (CYGPRI_SIU_LVL, &hal_arbitration_isr_cpm, ID_CPM, 0); HAL_INTERRUPT_UNMASK (CYGPRI_SIU_LVL); HAL_INTERRUPT_SET_LEVEL (CYGNUM_HAL_INTERRUPT_SIU_CPM, CYGHWR_HAL_POWERPC_MPC860_CPM_LVL); HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_SIU_CPM); #endif }
//-------------------------------------------------------------------------- // Platform init code. void hal_platform_init(void) { cyg_uint32 bcsr, gcr, frr, eicr, iack; int vec; // Initialize I/O interfaces hal_if_init(); // Reset interrupt controller/state HAL_READ_UINT32LE(_CSB281_EPIC_GCR, gcr); HAL_READ_UINT32LE(_CSB281_EPIC_FRR, frr); HAL_WRITE_UINT32LE(_CSB281_EPIC_GCR, gcr | _CSB281_EPIC_GCR_R); do { HAL_READ_UINT32LE(_CSB281_EPIC_GCR, gcr); } while ((gcr & _CSB281_EPIC_GCR_R) != 0); HAL_WRITE_UINT32LE(_CSB281_EPIC_GCR, gcr | _CSB281_EPIC_GCR_M); HAL_READ_UINT32LE(_CSB281_EPIC_EICR, eicr); // Force direct interrupts eicr &= ~_CSB281_EPIC_EICR_SIE; HAL_WRITE_UINT32LE(_CSB281_EPIC_EICR, eicr); for (vec = CYGNUM_HAL_INTERRUPT_IRQ0; vec <= CYGNUM_HAL_ISR_MAX; vec++) { HAL_INTERRUPT_CONFIGURE(vec, 0, 0); // Default to low-edge HAL_INTERRUPT_SET_LEVEL(vec, 0x0F); // Priority } vec = (frr & 0x0FFF0000) >> 16; // Number of interrupt sources while (vec-- > 0) { HAL_READ_UINT32LE(_CSB281_EPIC_IACK, iack); HAL_WRITE_UINT32LE(_CSB281_EPIC_EOI, 0); } HAL_WRITE_UINT32LE(_CSB281_EPIC_PCTPR, 1); // Enables interrupts #ifndef CYGSEM_HAL_USE_ROM_MONITOR // Reset peripherals HAL_READ_UINT32(_CSB281_BCSR, bcsr); HAL_WRITE_UINT32(_CSB281_BCSR, _zero_bit(bcsr, _CSB281_BCSR_PRESET)); HAL_WRITE_UINT32(_CSB281_BCSR, _one_bit(bcsr, _CSB281_BCSR_PRESET)); _csb281_i2c_init(); _csb281_fs6377_init(0); #endif #ifdef CYGSEM_CSB281_LCD_COMM lcd_comm_init(); #endif _csb281_pci_init(); }
int hal_enable_profile_timer(int resolution) { cyg_uint16 ticks; // Make sure the clock is not running but is otherwise initialized. HAL_WRITE_UINT16(HAL_MCFxxxx_PROFILE_TIMER_BASE + HAL_MCFxxxx_PITx_PCSR, HAL_MCFxxxx_PITx_PCSR_PRE_64 | HAL_MCFxxxx_PITx_PCSR_OVW | HAL_MCFxxxx_PITx_PCSR_PIE | HAL_MCFxxxx_PITx_PCSR_PIF | HAL_MCFxxxx_PITx_PCSR_RLD); // The resolution is a time interval in microseconds. The actual // cpu clock frequency is determined by the platform. This is divided // by 64, which means it may not be possible to get the exact resolution. ticks = ((resolution * CYGHWR_HAL_SYSTEM_CLOCK_MHZ) / 64) - 1; HAL_WRITE_UINT16(HAL_MCFxxxx_PROFILE_TIMER_BASE + HAL_MCFxxxx_PITx_PMR, ticks); // Convert back to microseconds. This may actually increase rounding // errors for some arguments and platforms, but the result should // still be accurate enough for practical purposes. resolution = ((ticks + 1) * 64) / CYGHWR_HAL_SYSTEM_CLOCK_MHZ; // Set up the interrupt handler. This is usually a high-priority // interrupt so that we can get profiling information for other // interrupt sources. #ifdef HAL_VSR_SET HAL_VSR_SET(HAL_MCFxxxx_PROFILE_TIMER_VECTOR, &hal_mcfxxxx_profile_vsr, (cyg_uint32)0); #endif HAL_INTERRUPT_SET_LEVEL(HAL_MCFxxxx_PROFILE_TIMER_ISR, CYGNUM_HAL_M68K_MCFxxxx_SOFTWARE_PROFILE_TIMER_ISR_PRIORITY); HAL_INTERRUPT_UNMASK(HAL_MCFxxxx_PROFILE_TIMER_ISR); // Now start the timer running. HAL_WRITE_UINT16(HAL_MCFxxxx_PROFILE_TIMER_BASE + HAL_MCFxxxx_PITx_PCSR, HAL_MCFxxxx_PITx_PCSR_PRE_64 | HAL_MCFxxxx_PITx_PCSR_OVW | HAL_MCFxxxx_PITx_PCSR_PIE | HAL_MCFxxxx_PITx_PCSR_PIF | HAL_MCFxxxx_PITx_PCSR_RLD | HAL_MCFxxxx_PITx_PCSR_EN); // Return the actual resolution. return resolution; }
static void entry0( cyg_addrword_t data ) { int tick; // Scheduler and thus timer interrupts are running by the // time we get here. // Wait for next tick tick = cyg_current_time(); do {} while (cyg_current_time() == tick); tick = cyg_current_time(); // Then mask timer interrupts HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_RTC); // and wait for the time when the next tick should have come // and check it didn't trigger an interrupt hal_delay_us(TICK_DELAY); CYG_TEST_CHECK(cyg_current_time() == tick, "Timer interrupt while masked"); // Now change interrupt level, and make the check again. Changing // level should not affect interrupt mask state. HAL_INTERRUPT_SET_LEVEL(CYGNUM_HAL_INTERRUPT_RTC, 8); hal_delay_us(TICK_DELAY); CYG_TEST_CHECK(cyg_current_time() == tick, "Timer interrupt after changing level"); // Finally unmask the interrupt and make sure it results in ticks. HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_RTC); hal_delay_us(TICK_DELAY); CYG_TEST_CHECK(cyg_current_time() != tick, "No timer interrupt after unmask"); CYG_TEST_PASS_FINISH("SH intr0 test end"); }
static int cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) { static int irq_state = 0; channel_data_t* chan; cyg_uint8 icr; int ret = 0; CYGARC_HAL_SAVE_GP(); // Some of the diagnostic print code calls through here with no idea what the ch_data is. // Go ahead and assume it is channels[0]. if (__ch_data == 0) __ch_data = (void*)&channels[0]; chan = (channel_data_t*)__ch_data; switch (__func) { case __COMMCTL_IRQ_ENABLE: irq_state = 1; HAL_READ_UINT8(chan->base + _SERIAL_ICR, icr); icr |= SIO_INT_ENABLE; HAL_WRITE_UINT8(chan->base + _SERIAL_ICR, icr); HAL_INTERRUPT_SET_LEVEL(chan->isr_vector, 1); HAL_INTERRUPT_UNMASK(chan->isr_vector); break; case __COMMCTL_IRQ_DISABLE: ret = irq_state; irq_state = 0; HAL_READ_UINT8(chan->base + _SERIAL_ICR, icr); icr &= ~SIO_INT_ENABLE; HAL_WRITE_UINT8(chan->base + _SERIAL_ICR, icr); HAL_INTERRUPT_MASK(chan->isr_vector); break; case __COMMCTL_DBG_ISR_VECTOR: ret = chan->isr_vector; break; case __COMMCTL_SET_TIMEOUT: { va_list ap; va_start(ap, __func); ret = chan->msec_timeout; chan->msec_timeout = va_arg(ap, cyg_uint32); va_end(ap); } break; case __COMMCTL_SETBAUD: { cyg_uint32 baud_rate; cyg_uint8* port = chan->base; va_list ap; va_start(ap, __func); baud_rate = va_arg(ap, cyg_uint32); va_end(ap); // Disable port interrupts while changing hardware HAL_READ_UINT8(port + _SERIAL_ICR, icr); HAL_WRITE_UINT8(port + _SERIAL_ICR, 0); // Set baud rate. ret = cyg_hal_plf_serial_set_baud(port, baud_rate); // Reenable interrupts if necessary HAL_WRITE_UINT8(port + _SERIAL_ICR, icr); } break; case __COMMCTL_GETBAUD: break; default: break; } CYGARC_HAL_RESTORE_GP(); return ret; }
static int cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) { static int irq_state = 0; channel_data_t* chan; cyg_uint8 ier; int ret = 0; CYGARC_HAL_SAVE_GP(); // Some of the diagnostic print code calls through here with no idea what the ch_data is. // Go ahead and assume it is channels[0]. if (__ch_data == 0) __ch_data = (void*)&channels[0]; chan = (channel_data_t*)__ch_data; switch (__func) { case __COMMCTL_IRQ_ENABLE: irq_state = 1; HAL_READ_UINT8(chan->base + SER_16550_IER, ier); ier |= SIO_IER_ERDAI; HAL_WRITE_UINT8(chan->base + SER_16550_IER, ier); HAL_INTERRUPT_SET_LEVEL(chan->isr_vector, 1); HAL_INTERRUPT_UNMASK(chan->isr_vector); break; case __COMMCTL_IRQ_DISABLE: ret = irq_state; irq_state = 0; HAL_READ_UINT8(chan->base + SER_16550_IER, ier); ier &= ~SIO_IER_ERDAI; HAL_WRITE_UINT8(chan->base + SER_16550_IER, ier); HAL_INTERRUPT_MASK(chan->isr_vector); break; case __COMMCTL_DBG_ISR_VECTOR: ret = chan->isr_vector; break; case __COMMCTL_SET_TIMEOUT: { va_list ap; va_start(ap, __func); ret = chan->msec_timeout; chan->msec_timeout = va_arg(ap, cyg_uint32); va_end(ap); } break; case __COMMCTL_SETBAUD: { cyg_uint32 baud_rate; cyg_uint16 baud_divisor; cyg_uint8* port = chan->base; va_list ap; va_start(ap, __func); baud_rate = va_arg(ap, cyg_uint32); va_end(ap); switch (baud_rate) { case 110: baud_divisor = DIVISOR(110); break; case 150: baud_divisor = DIVISOR(150); break; case 300: baud_divisor = DIVISOR(300); break; case 600: baud_divisor = DIVISOR(600); break; case 1200: baud_divisor = DIVISOR(1200); break; case 2400: baud_divisor = DIVISOR(2400); break; case 4800: baud_divisor = DIVISOR(4800); break; case 7200: baud_divisor = DIVISOR(7200); break; case 9600: baud_divisor = DIVISOR(9600); break; case 14400: baud_divisor = DIVISOR(14400); break; case 19200: baud_divisor = DIVISOR(19200); break; case 38400: baud_divisor = DIVISOR(38400); break; case 57600: baud_divisor = DIVISOR(57600); break; case 115200: baud_divisor = DIVISOR(115200); break; case 230400: baud_divisor = DIVISOR(230400); break; default: return -1; break; // Invalid baud rate selected } // Disable port interrupts while changing hardware HAL_READ_UINT8(port+SER_16550_IER, ier); HAL_WRITE_UINT8(port+SER_16550_IER, 0); // Set baud rate. cyg_hal_plf_serial_set_baud(port, baud_divisor); // Reenable interrupts if necessary HAL_WRITE_UINT8(port+SER_16550_IER, ier); } break; case __COMMCTL_GETBAUD: break; default: break; } CYGARC_HAL_RESTORE_GP(); return ret; }
static int cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) { static int irq_state = 0; channel_data_t* chan; cyg_uint8 ier; int ret = 0; CYGARC_HAL_SAVE_GP(); // Some of the diagnostic print code calls through here with no idea what the ch_data is. // Go ahead and assume it is channels[0]. if (__ch_data == 0) __ch_data = (void*)&channels[0]; chan = (channel_data_t*)__ch_data; switch (__func) { case __COMMCTL_IRQ_ENABLE: irq_state = 1; HAL_READ_UINT8(chan->base + SER_16550_IER, ier); ier |= SIO_IER_ERDAI; HAL_WRITE_UINT8(chan->base + SER_16550_IER, ier); HAL_INTERRUPT_SET_LEVEL(chan->isr_vector, 1); HAL_INTERRUPT_UNMASK(chan->isr_vector); break; case __COMMCTL_IRQ_DISABLE: ret = irq_state; irq_state = 0; HAL_READ_UINT8(chan->base + SER_16550_IER, ier); ier &= ~SIO_IER_ERDAI; HAL_WRITE_UINT8(chan->base + SER_16550_IER, ier); HAL_INTERRUPT_MASK(chan->isr_vector); break; case __COMMCTL_DBG_ISR_VECTOR: ret = chan->isr_vector; break; case __COMMCTL_SET_TIMEOUT: { va_list ap; va_start(ap, __func); ret = chan->msec_timeout; chan->msec_timeout = va_arg(ap, cyg_uint32); va_end(ap); } break; case __COMMCTL_SETBAUD: { cyg_uint32 baud_rate; cyg_uint16 baud_divisor; cyg_uint8* port = chan->base; va_list ap; va_start(ap, __func); baud_rate = va_arg(ap, cyg_uint32); va_end(ap); switch (baud_rate) { case 110: baud_divisor = BAUD_110; break; case 150: baud_divisor = BAUD_150; break; case 300: baud_divisor = BAUD_300; break; case 600: baud_divisor = BAUD_600; break; case 1200: baud_divisor = BAUD_1200; break; case 2400: baud_divisor = BAUD_2400; break; case 4800: baud_divisor = BAUD_4800; break; case 7200: baud_divisor = BAUD_7200; break; case 9600: baud_divisor = BAUD_9600; break; case 14400: baud_divisor = BAUD_14400; break; case 19200: baud_divisor = BAUD_19200; break; case 38400: baud_divisor = BAUD_38400; break; case 57600: baud_divisor = BAUD_57600; break; case 115200: baud_divisor = BAUD_115200; break; case 230400: baud_divisor = BAUD_230400; break; default: return -1; break; // Invalid baud rate selected } // // We may need to increase the timeout before causing a break reset. // According to the Atlas Users Manual (Document MD00005) The BRKRES // register will need to be programmed with a value larger that 0xA (the default) // if we are going to use a baud rate lower than 2400. // if (baud_rate <= 2400) { // For now, just disable the break reset entirely. HAL_WRITE_UINT32(HAL_ATLAS_BRKRES, 0); } else { // Put the break reset state back to the default HAL_WRITE_UINT32(HAL_ATLAS_BRKRES, HAL_ATLAS_BRKRES_DEFAULT_VALUE); } // Disable port interrupts while changing hardware HAL_READ_UINT8(port+SER_16550_IER, ier); HAL_WRITE_UINT8(port+SER_16550_IER, 0); // Set baud rate. cyg_hal_plf_serial_set_baud(port, baud_divisor); // Reenable interrupts if necessary HAL_WRITE_UINT8(port+SER_16550_IER, ier); } break; case __COMMCTL_GETBAUD: break; default: break; } CYGARC_HAL_RESTORE_GP(); return ret; }
static int cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) { static int irq_state = 0; channel_data_t* chan; cyg_uint32 intmask; int ret = 0; CYGARC_HAL_SAVE_GP(); // Some of the diagnostic print code calls through here with no idea what the ch_data is. // Go ahead and assume it is channels[0]. if (__ch_data == 0) __ch_data = (void*)&channels[0]; chan = (channel_data_t*)__ch_data; switch (__func) { case __COMMCTL_IRQ_ENABLE: irq_state = 1; RA_UART_REG(chan->base, UART_IER) |= UART_IER_ERBFI; HAL_INTERRUPT_SET_LEVEL(chan->isr_vector, 1); HAL_INTERRUPT_UNMASK(chan->isr_vector); break; case __COMMCTL_IRQ_DISABLE: ret = irq_state; irq_state = 0; RA_UART_REG(chan->base, UART_IER) &= ~UART_IER_ERBFI; HAL_INTERRUPT_MASK(chan->isr_vector); break; case __COMMCTL_DBG_ISR_VECTOR: ret = chan->isr_vector; break; case __COMMCTL_SET_TIMEOUT: { va_list ap; va_start(ap, __func); ret = chan->msec_timeout; chan->msec_timeout = va_arg(ap, cyg_uint32); va_end(ap); } break; case __COMMCTL_SETBAUD: { cyg_uint32 baud_rate; cyg_uint16 baud_divisor; cyg_uint32 port = chan->base; va_list ap; va_start(ap, __func); baud_rate = va_arg(ap, cyg_uint32); va_end(ap); baud_divisor = RA_SERIAL_BAUD_DIVISOR(baud_rate); // Disable port interrupts while changing hardware intmask = RA_UART_REG(port, UART_IER); RA_UART_REG(port, UART_IER) = 0; // Set baud rate. cyg_hal_plf_serial_set_baud(port, baud_divisor); // Reenable interrupts if necessary RA_UART_REG(port, UART_IER) = intmask; } break; case __COMMCTL_GETBAUD: break; default: break; } CYGARC_HAL_RESTORE_GP(); return ret; }