From: batt Date: Thu, 11 Oct 2007 15:19:49 +0000 (+0000) Subject: Move dsp56k and i196 drivers to their drv/ dirs. X-Git-Tag: 1.0.0~376 X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;h=9adb3869a6b8756fbba9ff8a9f7924623e62800d;p=bertos.git Move dsp56k and i196 drivers to their drv/ dirs. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@865 38d2e660-2303-0410-9eaa-f027e97ec537 --- diff --git a/cpu/dsp56k/drv/buzzerled_dsp56k.h b/cpu/dsp56k/drv/buzzerled_dsp56k.h new file mode 100644 index 00000000..4eafa57b --- /dev/null +++ b/cpu/dsp56k/drv/buzzerled_dsp56k.h @@ -0,0 +1,178 @@ +/** + * \file + * + * + * \brief Hardware support for buzzers and leds in DSP56K-based boards + * + * \version $Id$ + * + * \author Giovanni Bajo + */ + +/*#* + *#* $Log$ + *#* Revision 1.7 2006/07/19 12:56:25 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.6 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.5 2005/04/11 19:10:27 bernie + *#* Include top-level headers from cfg/ subdir. + *#* + *#* Revision 1.4 2004/11/16 21:54:43 bernie + *#* Changes for SC Monoboard support. + *#* + *#* Revision 1.3 2004/08/25 14:12:08 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.2 2004/06/03 11:27:09 bernie + *#* Add dual-license information. + *#* + *#* Revision 1.1 2004/05/23 18:36:05 bernie + *#* Import buzzerled driver. + *#* + *#*/ + +#ifndef DRV_BUZZERLED_DSP56K_H +#define DRV_BUZZERLED_DSP56K_H + +#include +#include +#include "pwm.h" + +#if ARCH & ARCH_HECO + +/** + * \name Connection of the leds to the DSP: + *
+ *   Led       Line    DSP Pin
+ *   ---------------------------
+ *   YELLOW    T2      HOME1/TB3
+ *   GREEN     T3      INDX1/TB2
+ *   RED       T4      PHB1/TB1
+ * 
+ */ + +INLINE bool bld_is_inverted_intensity(enum BLD_DEVICE device) +{ + return (device == BLD_GREEN_LED + || device == BLD_YELLOW_LED + || device == BLD_RED_LED); +} + +INLINE bool bld_is_pwm(enum BLD_DEVICE device) +{ + // Only the buzzer is connected to a PWM + return (device == BLD_BUZZER || device == BLD_READY_LED); +} + +INLINE bool bld_is_timer(enum BLD_DEVICE device) +{ + // LEDs are connected to timers + return (device == BLD_GREEN_LED || device == BLD_YELLOW_LED || device == BLD_RED_LED); +} + +INLINE uint16_t bld_get_pwm(enum BLD_DEVICE device) +{ + switch (device) + { + default: ASSERT(0); + case BLD_BUZZER: return 5; // PWMA5 + case BLD_READY_LED: return 9; // PWMB3 + } +} + + +INLINE struct REG_TIMER_STRUCT* bld_get_timer(enum BLD_DEVICE device) +{ + switch (device) + { + default: ASSERT(0); + case BLD_GREEN_LED: return ®_TIMER_B[2]; + case BLD_RED_LED: return ®_TIMER_B[1]; + case BLD_YELLOW_LED: return ®_TIMER_B[3]; + } +} + +INLINE void bld_hw_init(void) +{ +} + +INLINE void bld_hw_set(enum BLD_DEVICE device, bool enable) +{ + if (bld_is_inverted_intensity(device)) + enable = !enable; + + // Handle a BLD connected to a PWM + if (bld_is_pwm(device)) + { + struct PWM* pwm = pwm_get_handle(bld_get_pwm(device)); + + pwm_set_enable(pwm, false); + pwm_set_dutycycle_percent(pwm, (enable ? 50 : 0)); + pwm_set_enable(pwm, true); + } + else if (bld_is_timer(device)) + { + struct REG_TIMER_STRUCT* timer = bld_get_timer(device); + + // Check that the timer is currently stopped, and the OFLAG is not + // controlled by another timer. Otherwise, the led is already + // controlled by the timer, and we cannot correctly set it + // on/off without reprogramming the timer. + ASSERT((timer->CTRL & REG_TIMER_CTRL_MODE_MASK) == REG_TIMER_CTRL_MODE_STOP); + ASSERT(!(timer->SCR & REG_TIMER_SCR_EEOF)); + + // Check also that polarity is correct + ASSERT(!(timer->SCR & REG_TIMER_SCR_OPS)); + + // Without programming the timer, we have a way to manually force a certain + // value on the external pin. We also need to enable the output pin. + timer->SCR &= ~REG_TIMER_SCR_VAL_1; + timer->SCR |= REG_TIMER_SCR_OEN | + REG_TIMER_SCR_FORCE | + (!enable ? REG_TIMER_SCR_VAL_0 : REG_TIMER_SCR_VAL_1); + } + else + ASSERT(0); +} + +#elif ARCH & ARCH_SC + +// We do not need inline functions here, because constant propagation is not big deal here +void bld_hw_init(void); +void bld_hw_set(enum BLD_DEVICE device, bool enable); + +#endif + +#endif /* DRV_BUZZERLED_DSP56K_H */ diff --git a/cpu/dsp56k/drv/ser_dsp56k.c b/cpu/dsp56k/drv/ser_dsp56k.c new file mode 100644 index 00000000..d98c9030 --- /dev/null +++ b/cpu/dsp56k/drv/ser_dsp56k.c @@ -0,0 +1,405 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Stefano Fedrigo + * \author Giovanni Bajo + * + * \brief DSP5680x CPU specific serial I/O driver + */ + +/*#* + *#* $Log$ + *#* Revision 1.14 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.13 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.12 2005/04/11 19:10:27 bernie + *#* Include top-level headers from cfg/ subdir. + *#* + *#* Revision 1.11 2005/01/25 07:42:04 bernie + *#* Simplify. + *#* + *#* Revision 1.10 2005/01/14 00:48:33 aleph + *#* Rename callbacks; SerialHardwareVT.txSending: New callback. + *#* + *#* Revision 1.9 2004/12/08 09:42:55 bernie + *#* Add support for multiplexed serial ports. + *#* + *#* Revision 1.8 2004/10/26 09:00:49 bernie + *#* Don't access serial data register twice. + *#* + *#* Revision 1.7 2004/10/19 08:57:15 bernie + *#* Bugfixes for DSP56K serial driver from scfirm. + *#* + *#* Revision 1.5 2004/08/25 14:12:08 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.4 2004/07/30 14:27:49 rasky + *#* Aggiornati alcuni file DSP56k per la nuova libreria di IRQ management + *#* + *#* Revision 1.3 2004/06/03 11:27:09 bernie + *#* Add dual-license information. + *#* + *#* Revision 1.2 2004/05/23 18:21:53 bernie + *#* Trim CVS logs and cleanup header info. + *#*/ + +#include "ser.h" +#include "ser_p.h" +#include +#include +#include +#include + +// GPIO E is shared with SPI (in DSP56807). Pins 0&1 are TXD0 and RXD0. To use +// the serial, we need to disable the GPIO functions on them. +#define REG_GPIO_SERIAL_0 REG_GPIO_E +#define REG_GPIO_SERIAL_MASK_0 0x03 + +#define REG_GPIO_SERIAL_1 REG_GPIO_D +#define REG_GPIO_SERIAL_MASK_1 0xC0 + + +// Check flag consistency +#if (SERRF_PARITYERROR != REG_SCI_SR_PF) || \ + (SERRF_RXSROVERRUN != REG_SCI_SR_OR) || \ + (SERRF_FRAMEERROR != REG_SCI_SR_FE) || \ + (SERRF_NOISEERROR != REG_SCI_SR_NF) + #error error flags do not match with register bits +#endif + +static unsigned char ser0_fifo_rx[CONFIG_SER0_FIFOSIZE_RX]; +static unsigned char ser0_fifo_tx[CONFIG_SER0_FIFOSIZE_TX]; +static unsigned char ser1_fifo_rx[CONFIG_SER1_FIFOSIZE_RX]; +static unsigned char ser1_fifo_tx[CONFIG_SER1_FIFOSIZE_TX]; + +#if CONFIG_SER_MULTI + #include + + #define MAX_MULTI_GROUPS 1 + + struct Semaphore multi_sems[MAX_MULTI_GROUPS]; +#endif + + +struct SCI +{ + struct SerialHardware hw; + struct Serial* serial; + volatile struct REG_SCI_STRUCT* regs; + IRQ_VECTOR irq_tx; + IRQ_VECTOR irq_rx; + int num_group; + int id; +}; + +static inline void enable_tx_irq_bare(volatile struct REG_SCI_STRUCT* regs) +{ + regs->CR |= REG_SCI_CR_TEIE | REG_SCI_CR_TIIE; +} + +static inline void enable_rx_irq_bare(volatile struct REG_SCI_STRUCT* regs) +{ + regs->CR |= REG_SCI_CR_RIE; +} + +static inline void disable_tx_irq_bare(volatile struct REG_SCI_STRUCT* regs) +{ + regs->CR &= ~(REG_SCI_CR_TEIE | REG_SCI_CR_TIIE); +} + +static inline void disable_rx_irq_bare(volatile struct REG_SCI_STRUCT* regs) +{ + regs->CR &= ~(REG_SCI_CR_RIE | REG_SCI_CR_REIE); +} + +static inline void disable_tx_irq(struct SerialHardware* _hw) +{ + struct SCI* hw = (struct SCI*)_hw; + + disable_tx_irq_bare(hw->regs); +} + +static inline void disable_rx_irq(struct SerialHardware* _hw) +{ + struct SCI* hw = (struct SCI*)_hw; + + disable_rx_irq_bare(hw->regs); +} + +static inline void enable_tx_irq(struct SerialHardware* _hw) +{ + struct SCI* hw = (struct SCI*)_hw; + + enable_tx_irq_bare(hw->regs); +} + +static inline void enable_rx_irq(struct SerialHardware* _hw) +{ + struct SCI* hw = (struct SCI*)_hw; + + enable_rx_irq_bare(hw->regs); +} + +static inline bool tx_irq_enabled(struct SerialHardware* _hw) +{ + struct SCI* hw = (struct SCI*)_hw; + + return (hw->regs->CR & REG_SCI_CR_TEIE); +} + +static void tx_isr(const struct SCI *hw) +{ +#pragma interrupt warn + volatile struct REG_SCI_STRUCT* regs = hw->regs; + + if (fifo_isempty(&hw->serial->txfifo)) + disable_tx_irq_bare(regs); + else + { + // Clear transmitter flags before sending data + (void)regs->SR; + regs->DR = fifo_pop(&hw->serial->txfifo); + } +} + +static void rx_isr(const struct SCI *hw) +{ +#pragma interrupt warn + volatile struct REG_SCI_STRUCT* regs = hw->regs; + + // Propagate errors + hw->serial->status |= regs->SR & (SERRF_PARITYERROR | + SERRF_RXSROVERRUN | + SERRF_FRAMEERROR | + SERRF_NOISEERROR); + + /* + * Serial IRQ can happen for two reason: data ready (RDRF) or overrun (OR) + * If the data is ready, we need to fetch it from the data register or + * the interrupt will retrigger immediatly. In case of overrun, instead, + * the value of the data register is meaningless. + */ + if (regs->SR & REG_SCI_SR_RDRF) + { + unsigned char data = regs->DR; + + if (fifo_isfull(&hw->serial->rxfifo)) + hw->serial->status |= SERRF_RXFIFOOVERRUN; + else + fifo_push(&hw->serial->rxfifo, data); + } + + // Writing anything to the status register clear the error bits. + regs->SR = 0; +} + +static void init(struct SerialHardware* _hw, struct Serial* ser) +{ + struct SCI* hw = (struct SCI*)_hw; + volatile struct REG_SCI_STRUCT* regs = hw->regs; + + // Clear status register (IRQ/status flags) + (void)regs->SR; + regs->SR = 0; + + // Clear data register + (void)regs->DR; + + // Install the handlers and set priorities for both IRQs + irq_install(hw->irq_tx, (isr_t)tx_isr, hw); + irq_install(hw->irq_rx, (isr_t)rx_isr, hw); + irq_setpriority(hw->irq_tx, IRQ_PRIORITY_SCI_TX); + irq_setpriority(hw->irq_rx, IRQ_PRIORITY_SCI_RX); + + // Activate the RX error interrupts, and RX/TX transmissions + regs->CR = REG_SCI_CR_TE | REG_SCI_CR_RE; + enable_rx_irq_bare(regs); + + // Disable GPIO pins for TX and RX lines + // \todo this should be divided into serial 0 and 1 + REG_GPIO_SERIAL_0->PER |= REG_GPIO_SERIAL_MASK_0; + REG_GPIO_SERIAL_1->PER |= REG_GPIO_SERIAL_MASK_1; + + hw->serial = ser; +} + +static void cleanup(struct SerialHardware* _hw) +{ + struct SCI* hw = (struct SCI*)_hw; + + // Uninstall the ISRs + disable_rx_irq(_hw); + disable_tx_irq(_hw); + irq_uninstall(hw->irq_tx); + irq_uninstall(hw->irq_rx); +} + +static void setbaudrate(struct SerialHardware* _hw, unsigned long rate) +{ + struct SCI* hw = (struct SCI*)_hw; + + // SCI has an internal 16x divider on the input clock, which comes + // from the IPbus (see the scheme in user manual, 12.7.3). We apply + // it to calculate the period to store in the register. + hw->regs->BR = (IPBUS_FREQ + rate * 8ul) / (rate * 16ul); +} + +static void setparity(struct SerialHardware* _hw, int parity) +{ + // ??? + ASSERT(0); +} + + +#if CONFIG_SER_MULTI + +static void multi_init(void) +{ + static bool flag = false; + int i; + + if (flag) + return; + + for (i = 0; i < MAX_MULTI_GROUPS; ++i) + sem_init(&multi_sems[i]); + flag = true; +} + +static void init_lock(struct SerialHardware* _hw, struct Serial *ser) +{ + struct SCI* hw = (struct SCI*)_hw; + + // Initialize the multi engine (if needed) + multi_init(); + + // Acquire the lock of the semaphore for this group + ASSERT(hw->num_group >= 0); + ASSERT(hw->num_group < MAX_MULTI_GROUPS); + sem_obtain(&multi_sems[hw->num_group]); + + // Do a hardware switch to the given serial + ser_hw_switch(hw->num_group, hw->id); + + init(_hw, ser); +} + +static void cleanup_unlock(struct SerialHardware* _hw) +{ + struct SCI* hw = (struct SCI*)_hw; + + cleanup(_hw); + + sem_release(&multi_sems[hw->num_group]); +} + +#endif /* CONFIG_SER_MULTI */ + + +static const struct SerialHardwareVT SCI_VT = +{ + .init = init, + .cleanup = cleanup, + .setBaudrate = setbaudrate, + .setParity = setparity, + .txStart = enable_tx_irq, + .txSending = tx_irq_enabled, +}; + +#if CONFIG_SER_MULTI +static const struct SerialHardwareVT SCI_MULTI_VT = +{ + .init = init_lock, + .cleanup = cleanup_unlock, + .setBaudrate = setbaudrate, + .setParity = setparity, + .txStart = enable_tx_irq, + .txSending = tx_irq_enabled, +}; +#endif /* CONFIG_SER_MULTI */ + +#define SCI_DESC_NORMAL(hwch) \ + { \ + .hw = \ + { \ + .table = &SCI_VT, \ + .rxbuffer = ser ## hwch ## _fifo_rx, \ + .txbuffer = ser ## hwch ## _fifo_tx, \ + .rxbuffer_size = countof(ser ## hwch ## _fifo_rx), \ + .txbuffer_size = countof(ser ## hwch ## _fifo_tx), \ + }, \ + .regs = ®_SCI[hwch], \ + .irq_rx = IRQ_SCI ## hwch ## _RECEIVER_FULL, \ + .irq_tx = IRQ_SCI ## hwch ## _TRANSMITTER_READY, \ + .num_group = -1, \ + .id = -1, \ + } \ + /**/ + +#if CONFIG_SER_MULTI +#define SCI_DESC_MULTI(hwch, group_, id_) \ + { \ + .hw = \ + { \ + .table = &SCI_MULTI_VT, \ + .rxbuffer = ser ## hwch ## _fifo_rx, \ + .txbuffer = ser ## hwch ## _fifo_tx, \ + .rxbuffer_size = countof(ser ## hwch ## _fifo_rx), \ + .txbuffer_size = countof(ser ## hwch ## _fifo_tx), \ + }, \ + .regs = ®_SCI[hwch], \ + .irq_rx = IRQ_SCI ## hwch ## _RECEIVER_FULL, \ + .irq_tx = IRQ_SCI ## hwch ## _TRANSMITTER_READY, \ + .num_group = group_, \ + .id = id_, \ + } \ + /**/ +#endif /* CONFIG_SER_MULTI */ + +// \todo Move this into hw.h, with a little preprocessor magic +static struct SCI SCIDescs[] = +{ + SCI_DESC_NORMAL(0), + SCI_DESC_MULTI(1, 0, 0), + SCI_DESC_MULTI(1, 0, 1), +}; + +struct SerialHardware* ser_hw_getdesc(int unit) +{ + ASSERT(unit < countof(SCIDescs)); + return &SCIDescs[unit].hw; +} diff --git a/cpu/dsp56k/drv/timer_dsp56k.h b/cpu/dsp56k/drv/timer_dsp56k.h new file mode 100644 index 00000000..f86cb50b --- /dev/null +++ b/cpu/dsp56k/drv/timer_dsp56k.h @@ -0,0 +1,148 @@ +#error This code must be revised for the new timer API +/** + * \file + * + * + * \version $Id$ + * + * \author Giovanni Bajo + * + * \brief Driver module for DSP56K + */ + +/*#* + *#* $Log$ + *#* Revision 1.10 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.9 2006/02/21 21:28:02 bernie + *#* New time handling based on TIMER_TICKS_PER_SEC to support slow timers with ticks longer than 1ms. + *#* + *#* Revision 1.8 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.7 2005/04/11 19:10:28 bernie + *#* Include top-level headers from cfg/ subdir. + *#* + *#* Revision 1.6 2004/11/16 22:37:14 bernie + *#* Replace IPTR with iptr_t. + *#* + *#* Revision 1.5 2004/08/25 14:12:08 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.4 2004/07/30 14:27:49 rasky + *#* Aggiornati alcuni file DSP56k per la nuova libreria di IRQ management + *#* + *#* Revision 1.3 2004/06/06 18:30:34 bernie + *#* Import DSP56800 changes from SC. + *#* + *#* Revision 1.2 2004/06/03 11:27:09 bernie + *#* Add dual-license information. + *#* + *#* Revision 1.1 2004/05/23 18:23:30 bernie + *#* Import drv/timer module. + *#* + *#*/ + +#ifndef DRV_TIMER_DSP56K_H +#define DRV_TIMER_DSP56K_H + +#include "timer.h" +#include +#include +#include +#include + +// Calculate register pointer and irq vector from hw.h setting +#define REG_SYSTEM_TIMER PP_CAT(REG_TIMER_, SYSTEM_TIMER) +#define SYSTEM_TIMER_IRQ_VECTOR PP_CAT(IRQ_TIMER_, SYSTEM_TIMER) + +/// Prescaler for the system timer +#define TIMER_PRESCALER 16 + +/// Frequency of the hardware high precision timer +#define TIMER_HW_HPTICKS_PER_SEC (IPBUS_FREQ / TIMER_PRESCALER) + +/// Type of time expressed in ticks of the hardware high precision timer +typedef uint16_t hptime_t; + +static void system_timer_isr(UNUSED(iptr_t, arg)); + +static void timer_hw_init(void) +{ + uint16_t compare; + + // Clear compare flag status and enable interrupt on compare + REG_SYSTEM_TIMER->SCR &= ~REG_TIMER_SCR_TCF; + REG_SYSTEM_TIMER->SCR |= REG_TIMER_SCR_TCFIE; + + // Calculate the compare value needed to generate an interrupt exactly + // TICKS_PER_SEC times each second (usually, every millisecond). Check that + // the calculation is accurate, otherwise there is a precision error + // (probably the prescaler is too big or too small). + compare = TIMER_HW_HPTICKS_PER_SEC / TICKS_PER_SEC; + ASSERT((uint32_t)compare * TICKS_PER_SEC == IPBUS_FREQ / TIMER_PRESCALER); + REG_SYSTEM_TIMER->CMP1 = compare; + + // The value for reload (at initializationa and after compare is met) is zero + REG_SYSTEM_TIMER->LOAD = 0; + + // Set the interrupt handler and priority + irq_install(SYSTEM_TIMER_IRQ_VECTOR, &system_timer_isr, NULL); + irq_setpriority(SYSTEM_TIMER_IRQ_VECTOR, IRQ_PRIORITY_SYSTEM_TIMER); + + // Small preprocessor trick to generate the REG_TIMER_CTRL_PRIMARY_IPBYNN macro + // needed to set the prescaler + #define REG_CONTROL_PRESCALER PP_CAT(REG_TIMER_CTRL_PRIMARY_IPBY, TIMER_PRESCALER) + + // Setup the counter and start counting + REG_SYSTEM_TIMER->CTRL = + REG_TIMER_CTRL_MODE_RISING | // count rising edges (normal) + REG_CONTROL_PRESCALER | // frequency (IPbus / TIMER_PRESCALER) + REG_TIMER_CTRL_LENGTH; // up to CMP1, then reload +} + +INLINE void timer_hw_irq(void) +{ + // Clear the overflow flag so that we are ready for another interrupt + REG_SYSTEM_TIMER->SCR &= ~REG_TIMER_SCR_TCF; +} + +INLINE hptime_t timer_hw_hpread(void) +{ + return REG_SYSTEM_TIMER->CNTR; +} + +#define DEFINE_TIMER_ISR \ + static void system_timer_isr(UNUSED(iptr_t, arg)) + +#endif /* DRV_TIMER_DSP56_H */ diff --git a/cpu/i196/drv/ser_i196.c b/cpu/i196/drv/ser_i196.c new file mode 100644 index 00000000..a87de6fa --- /dev/null +++ b/cpu/i196/drv/ser_i196.c @@ -0,0 +1,134 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief CPU specific serial I/O driver + */ + +/*#* + *#* $Log$ + *#* Revision 1.7 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.6 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.5 2004/12/13 11:51:08 bernie + *#* DISABLE_INTS/ENABLE_INTS: Convert to IRQ_DISABLE/IRQ_ENABLE. + *#* + *#* Revision 1.4 2004/08/25 14:12:08 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.3 2004/06/03 11:27:09 bernie + *#* Add dual-license information. + *#* + *#* Revision 1.2 2004/05/23 18:21:53 bernie + *#* Trim CVS logs and cleanup header info. + *#* + *#*/ + +#include "hw.h" +#include "serhw.h" + +#define SER_HW_ENABLE_TX \ + ATOMIC( \ + if (!ser_sending) \ + { \ + ser_sending = true; \ + (INT_PEND1 |= INT1F_TI) \ + } \ + ); + +static volatile bool ser_sending; + +// Serial TX intr +INTERRUPT(0x30) void TI_interrupt(void) +{ + if (CANT_SEND) + { + ser_sending = false; + return; + } + + /* Can we send two bytes at the same time? */ + if (SP_STAT & SPSF_TX_EMPTY) + { + SBUF = fifo_pop(&ser_txfifo); + + if (CANT_SEND) + { + ser_sending = false; + return; + } + } + + SBUF = fifo_pop(&ser_txfifo); +} + +INTERRUPT(0x32) void RI_interrupt(void) +{ + ser_status |= SP_STAT & + (SPSF_OVERRUN_ERROR | SPSF_PARITY_ERROR | SPSF_FRAMING_ERROR); + if (fifo_isfull(&ser_rxfifo)) + ser_status |= SERRF_RXFIFOOVERRUN; + else + fifo_push(&ser_rxfifo, SBUF); +} + +static void ser_setbaudrate(unsigned long rate) +{ + // Calcola il periodo per la generazione del baud rate richiesto + uint16_t baud = (uint16_t)(((CLOCK_FREQ / 16) / rate) - 1) | 0x8000; + BAUD_RATE = (uint8_t)baud; + BAUD_RATE = (uint8_t)(baud >> 8); +} + +static void ser_hw_init(void) +{ + // Inizializza la porta seriale + SP_CON = SPCF_RECEIVE_ENABLE | SPCF_MODE1; + ioc1_img |= IOC1F_TXD_SEL | IOC1F_EXTINT_SRC; + IOC1 = ioc1_img; + + // Svuota il buffer di ricezione + { + uint8_t dummy = SBUF; + } + + // Abilita gli interrupt + INT_MASK1 |= INT1F_TI | INT1F_RI; +} + diff --git a/cpu/i196/drv/timer_i196.h b/cpu/i196/drv/timer_i196.h new file mode 100644 index 00000000..5c4bc8bd --- /dev/null +++ b/cpu/i196/drv/timer_i196.h @@ -0,0 +1,89 @@ +#error This code must be revised for the new timer API +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Low-level timer module for AVR + */ + +/*#* + *#* $Log$ + *#* Revision 1.7 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.6 2006/02/21 21:28:02 bernie + *#* New time handling based on TIMER_TICKS_PER_SEC to support slow timers with ticks longer than 1ms. + *#* + *#* Revision 1.5 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.4 2004/12/13 11:51:08 bernie + *#* DISABLE_INTS/ENABLE_INTS: Convert to IRQ_DISABLE/IRQ_ENABLE. + *#* + *#* Revision 1.3 2004/08/25 14:12:08 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.2 2004/06/03 11:27:09 bernie + *#* Add dual-license information. + *#* + *#* Revision 1.1 2004/05/23 18:23:30 bernie + *#* Import drv/timer module. + *#* + *#*/ + +#ifndef TIMER_I196_H +#define TIMER_I196_H + +/** + * Retrigger TIMER2, adjusting the time to account for + * the interrupt prologue latency. + */ +#define TIMER_RETRIGGER (TIMER2 -= TICKS_RATE) + +#define TIMER_INIT \ + TIMER2 = (65535 - TICKS_RATE); \ + INT_MASK1 |= INT1F_T2OVF; \ + ATOMIC( \ + WSR = 1; \ + IOC3 |= IOC3F_T2_ENA; \ + WSR = 0; \ + ) + +#define DEFINE_TIMER_ISR \ + INTERRUPT(0x38) void TM2_OVFL_interrupt(void); \ + INTERRUPT(0x38) void TM2_OVFL_interrupt(void) + +#endif /* DRV_TIMER_I196_H */ diff --git a/drv/buzzerled_dsp56k.h b/drv/buzzerled_dsp56k.h deleted file mode 100644 index 4eafa57b..00000000 --- a/drv/buzzerled_dsp56k.h +++ /dev/null @@ -1,178 +0,0 @@ -/** - * \file - * - * - * \brief Hardware support for buzzers and leds in DSP56K-based boards - * - * \version $Id$ - * - * \author Giovanni Bajo - */ - -/*#* - *#* $Log$ - *#* Revision 1.7 2006/07/19 12:56:25 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.6 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.5 2005/04/11 19:10:27 bernie - *#* Include top-level headers from cfg/ subdir. - *#* - *#* Revision 1.4 2004/11/16 21:54:43 bernie - *#* Changes for SC Monoboard support. - *#* - *#* Revision 1.3 2004/08/25 14:12:08 rasky - *#* Aggiornato il comment block dei log RCS - *#* - *#* Revision 1.2 2004/06/03 11:27:09 bernie - *#* Add dual-license information. - *#* - *#* Revision 1.1 2004/05/23 18:36:05 bernie - *#* Import buzzerled driver. - *#* - *#*/ - -#ifndef DRV_BUZZERLED_DSP56K_H -#define DRV_BUZZERLED_DSP56K_H - -#include -#include -#include "pwm.h" - -#if ARCH & ARCH_HECO - -/** - * \name Connection of the leds to the DSP: - *
- *   Led       Line    DSP Pin
- *   ---------------------------
- *   YELLOW    T2      HOME1/TB3
- *   GREEN     T3      INDX1/TB2
- *   RED       T4      PHB1/TB1
- * 
- */ - -INLINE bool bld_is_inverted_intensity(enum BLD_DEVICE device) -{ - return (device == BLD_GREEN_LED - || device == BLD_YELLOW_LED - || device == BLD_RED_LED); -} - -INLINE bool bld_is_pwm(enum BLD_DEVICE device) -{ - // Only the buzzer is connected to a PWM - return (device == BLD_BUZZER || device == BLD_READY_LED); -} - -INLINE bool bld_is_timer(enum BLD_DEVICE device) -{ - // LEDs are connected to timers - return (device == BLD_GREEN_LED || device == BLD_YELLOW_LED || device == BLD_RED_LED); -} - -INLINE uint16_t bld_get_pwm(enum BLD_DEVICE device) -{ - switch (device) - { - default: ASSERT(0); - case BLD_BUZZER: return 5; // PWMA5 - case BLD_READY_LED: return 9; // PWMB3 - } -} - - -INLINE struct REG_TIMER_STRUCT* bld_get_timer(enum BLD_DEVICE device) -{ - switch (device) - { - default: ASSERT(0); - case BLD_GREEN_LED: return ®_TIMER_B[2]; - case BLD_RED_LED: return ®_TIMER_B[1]; - case BLD_YELLOW_LED: return ®_TIMER_B[3]; - } -} - -INLINE void bld_hw_init(void) -{ -} - -INLINE void bld_hw_set(enum BLD_DEVICE device, bool enable) -{ - if (bld_is_inverted_intensity(device)) - enable = !enable; - - // Handle a BLD connected to a PWM - if (bld_is_pwm(device)) - { - struct PWM* pwm = pwm_get_handle(bld_get_pwm(device)); - - pwm_set_enable(pwm, false); - pwm_set_dutycycle_percent(pwm, (enable ? 50 : 0)); - pwm_set_enable(pwm, true); - } - else if (bld_is_timer(device)) - { - struct REG_TIMER_STRUCT* timer = bld_get_timer(device); - - // Check that the timer is currently stopped, and the OFLAG is not - // controlled by another timer. Otherwise, the led is already - // controlled by the timer, and we cannot correctly set it - // on/off without reprogramming the timer. - ASSERT((timer->CTRL & REG_TIMER_CTRL_MODE_MASK) == REG_TIMER_CTRL_MODE_STOP); - ASSERT(!(timer->SCR & REG_TIMER_SCR_EEOF)); - - // Check also that polarity is correct - ASSERT(!(timer->SCR & REG_TIMER_SCR_OPS)); - - // Without programming the timer, we have a way to manually force a certain - // value on the external pin. We also need to enable the output pin. - timer->SCR &= ~REG_TIMER_SCR_VAL_1; - timer->SCR |= REG_TIMER_SCR_OEN | - REG_TIMER_SCR_FORCE | - (!enable ? REG_TIMER_SCR_VAL_0 : REG_TIMER_SCR_VAL_1); - } - else - ASSERT(0); -} - -#elif ARCH & ARCH_SC - -// We do not need inline functions here, because constant propagation is not big deal here -void bld_hw_init(void); -void bld_hw_set(enum BLD_DEVICE device, bool enable); - -#endif - -#endif /* DRV_BUZZERLED_DSP56K_H */ diff --git a/drv/ser_dsp56k.c b/drv/ser_dsp56k.c deleted file mode 100644 index d98c9030..00000000 --- a/drv/ser_dsp56k.c +++ /dev/null @@ -1,405 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Stefano Fedrigo - * \author Giovanni Bajo - * - * \brief DSP5680x CPU specific serial I/O driver - */ - -/*#* - *#* $Log$ - *#* Revision 1.14 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.13 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.12 2005/04/11 19:10:27 bernie - *#* Include top-level headers from cfg/ subdir. - *#* - *#* Revision 1.11 2005/01/25 07:42:04 bernie - *#* Simplify. - *#* - *#* Revision 1.10 2005/01/14 00:48:33 aleph - *#* Rename callbacks; SerialHardwareVT.txSending: New callback. - *#* - *#* Revision 1.9 2004/12/08 09:42:55 bernie - *#* Add support for multiplexed serial ports. - *#* - *#* Revision 1.8 2004/10/26 09:00:49 bernie - *#* Don't access serial data register twice. - *#* - *#* Revision 1.7 2004/10/19 08:57:15 bernie - *#* Bugfixes for DSP56K serial driver from scfirm. - *#* - *#* Revision 1.5 2004/08/25 14:12:08 rasky - *#* Aggiornato il comment block dei log RCS - *#* - *#* Revision 1.4 2004/07/30 14:27:49 rasky - *#* Aggiornati alcuni file DSP56k per la nuova libreria di IRQ management - *#* - *#* Revision 1.3 2004/06/03 11:27:09 bernie - *#* Add dual-license information. - *#* - *#* Revision 1.2 2004/05/23 18:21:53 bernie - *#* Trim CVS logs and cleanup header info. - *#*/ - -#include "ser.h" -#include "ser_p.h" -#include -#include -#include -#include - -// GPIO E is shared with SPI (in DSP56807). Pins 0&1 are TXD0 and RXD0. To use -// the serial, we need to disable the GPIO functions on them. -#define REG_GPIO_SERIAL_0 REG_GPIO_E -#define REG_GPIO_SERIAL_MASK_0 0x03 - -#define REG_GPIO_SERIAL_1 REG_GPIO_D -#define REG_GPIO_SERIAL_MASK_1 0xC0 - - -// Check flag consistency -#if (SERRF_PARITYERROR != REG_SCI_SR_PF) || \ - (SERRF_RXSROVERRUN != REG_SCI_SR_OR) || \ - (SERRF_FRAMEERROR != REG_SCI_SR_FE) || \ - (SERRF_NOISEERROR != REG_SCI_SR_NF) - #error error flags do not match with register bits -#endif - -static unsigned char ser0_fifo_rx[CONFIG_SER0_FIFOSIZE_RX]; -static unsigned char ser0_fifo_tx[CONFIG_SER0_FIFOSIZE_TX]; -static unsigned char ser1_fifo_rx[CONFIG_SER1_FIFOSIZE_RX]; -static unsigned char ser1_fifo_tx[CONFIG_SER1_FIFOSIZE_TX]; - -#if CONFIG_SER_MULTI - #include - - #define MAX_MULTI_GROUPS 1 - - struct Semaphore multi_sems[MAX_MULTI_GROUPS]; -#endif - - -struct SCI -{ - struct SerialHardware hw; - struct Serial* serial; - volatile struct REG_SCI_STRUCT* regs; - IRQ_VECTOR irq_tx; - IRQ_VECTOR irq_rx; - int num_group; - int id; -}; - -static inline void enable_tx_irq_bare(volatile struct REG_SCI_STRUCT* regs) -{ - regs->CR |= REG_SCI_CR_TEIE | REG_SCI_CR_TIIE; -} - -static inline void enable_rx_irq_bare(volatile struct REG_SCI_STRUCT* regs) -{ - regs->CR |= REG_SCI_CR_RIE; -} - -static inline void disable_tx_irq_bare(volatile struct REG_SCI_STRUCT* regs) -{ - regs->CR &= ~(REG_SCI_CR_TEIE | REG_SCI_CR_TIIE); -} - -static inline void disable_rx_irq_bare(volatile struct REG_SCI_STRUCT* regs) -{ - regs->CR &= ~(REG_SCI_CR_RIE | REG_SCI_CR_REIE); -} - -static inline void disable_tx_irq(struct SerialHardware* _hw) -{ - struct SCI* hw = (struct SCI*)_hw; - - disable_tx_irq_bare(hw->regs); -} - -static inline void disable_rx_irq(struct SerialHardware* _hw) -{ - struct SCI* hw = (struct SCI*)_hw; - - disable_rx_irq_bare(hw->regs); -} - -static inline void enable_tx_irq(struct SerialHardware* _hw) -{ - struct SCI* hw = (struct SCI*)_hw; - - enable_tx_irq_bare(hw->regs); -} - -static inline void enable_rx_irq(struct SerialHardware* _hw) -{ - struct SCI* hw = (struct SCI*)_hw; - - enable_rx_irq_bare(hw->regs); -} - -static inline bool tx_irq_enabled(struct SerialHardware* _hw) -{ - struct SCI* hw = (struct SCI*)_hw; - - return (hw->regs->CR & REG_SCI_CR_TEIE); -} - -static void tx_isr(const struct SCI *hw) -{ -#pragma interrupt warn - volatile struct REG_SCI_STRUCT* regs = hw->regs; - - if (fifo_isempty(&hw->serial->txfifo)) - disable_tx_irq_bare(regs); - else - { - // Clear transmitter flags before sending data - (void)regs->SR; - regs->DR = fifo_pop(&hw->serial->txfifo); - } -} - -static void rx_isr(const struct SCI *hw) -{ -#pragma interrupt warn - volatile struct REG_SCI_STRUCT* regs = hw->regs; - - // Propagate errors - hw->serial->status |= regs->SR & (SERRF_PARITYERROR | - SERRF_RXSROVERRUN | - SERRF_FRAMEERROR | - SERRF_NOISEERROR); - - /* - * Serial IRQ can happen for two reason: data ready (RDRF) or overrun (OR) - * If the data is ready, we need to fetch it from the data register or - * the interrupt will retrigger immediatly. In case of overrun, instead, - * the value of the data register is meaningless. - */ - if (regs->SR & REG_SCI_SR_RDRF) - { - unsigned char data = regs->DR; - - if (fifo_isfull(&hw->serial->rxfifo)) - hw->serial->status |= SERRF_RXFIFOOVERRUN; - else - fifo_push(&hw->serial->rxfifo, data); - } - - // Writing anything to the status register clear the error bits. - regs->SR = 0; -} - -static void init(struct SerialHardware* _hw, struct Serial* ser) -{ - struct SCI* hw = (struct SCI*)_hw; - volatile struct REG_SCI_STRUCT* regs = hw->regs; - - // Clear status register (IRQ/status flags) - (void)regs->SR; - regs->SR = 0; - - // Clear data register - (void)regs->DR; - - // Install the handlers and set priorities for both IRQs - irq_install(hw->irq_tx, (isr_t)tx_isr, hw); - irq_install(hw->irq_rx, (isr_t)rx_isr, hw); - irq_setpriority(hw->irq_tx, IRQ_PRIORITY_SCI_TX); - irq_setpriority(hw->irq_rx, IRQ_PRIORITY_SCI_RX); - - // Activate the RX error interrupts, and RX/TX transmissions - regs->CR = REG_SCI_CR_TE | REG_SCI_CR_RE; - enable_rx_irq_bare(regs); - - // Disable GPIO pins for TX and RX lines - // \todo this should be divided into serial 0 and 1 - REG_GPIO_SERIAL_0->PER |= REG_GPIO_SERIAL_MASK_0; - REG_GPIO_SERIAL_1->PER |= REG_GPIO_SERIAL_MASK_1; - - hw->serial = ser; -} - -static void cleanup(struct SerialHardware* _hw) -{ - struct SCI* hw = (struct SCI*)_hw; - - // Uninstall the ISRs - disable_rx_irq(_hw); - disable_tx_irq(_hw); - irq_uninstall(hw->irq_tx); - irq_uninstall(hw->irq_rx); -} - -static void setbaudrate(struct SerialHardware* _hw, unsigned long rate) -{ - struct SCI* hw = (struct SCI*)_hw; - - // SCI has an internal 16x divider on the input clock, which comes - // from the IPbus (see the scheme in user manual, 12.7.3). We apply - // it to calculate the period to store in the register. - hw->regs->BR = (IPBUS_FREQ + rate * 8ul) / (rate * 16ul); -} - -static void setparity(struct SerialHardware* _hw, int parity) -{ - // ??? - ASSERT(0); -} - - -#if CONFIG_SER_MULTI - -static void multi_init(void) -{ - static bool flag = false; - int i; - - if (flag) - return; - - for (i = 0; i < MAX_MULTI_GROUPS; ++i) - sem_init(&multi_sems[i]); - flag = true; -} - -static void init_lock(struct SerialHardware* _hw, struct Serial *ser) -{ - struct SCI* hw = (struct SCI*)_hw; - - // Initialize the multi engine (if needed) - multi_init(); - - // Acquire the lock of the semaphore for this group - ASSERT(hw->num_group >= 0); - ASSERT(hw->num_group < MAX_MULTI_GROUPS); - sem_obtain(&multi_sems[hw->num_group]); - - // Do a hardware switch to the given serial - ser_hw_switch(hw->num_group, hw->id); - - init(_hw, ser); -} - -static void cleanup_unlock(struct SerialHardware* _hw) -{ - struct SCI* hw = (struct SCI*)_hw; - - cleanup(_hw); - - sem_release(&multi_sems[hw->num_group]); -} - -#endif /* CONFIG_SER_MULTI */ - - -static const struct SerialHardwareVT SCI_VT = -{ - .init = init, - .cleanup = cleanup, - .setBaudrate = setbaudrate, - .setParity = setparity, - .txStart = enable_tx_irq, - .txSending = tx_irq_enabled, -}; - -#if CONFIG_SER_MULTI -static const struct SerialHardwareVT SCI_MULTI_VT = -{ - .init = init_lock, - .cleanup = cleanup_unlock, - .setBaudrate = setbaudrate, - .setParity = setparity, - .txStart = enable_tx_irq, - .txSending = tx_irq_enabled, -}; -#endif /* CONFIG_SER_MULTI */ - -#define SCI_DESC_NORMAL(hwch) \ - { \ - .hw = \ - { \ - .table = &SCI_VT, \ - .rxbuffer = ser ## hwch ## _fifo_rx, \ - .txbuffer = ser ## hwch ## _fifo_tx, \ - .rxbuffer_size = countof(ser ## hwch ## _fifo_rx), \ - .txbuffer_size = countof(ser ## hwch ## _fifo_tx), \ - }, \ - .regs = ®_SCI[hwch], \ - .irq_rx = IRQ_SCI ## hwch ## _RECEIVER_FULL, \ - .irq_tx = IRQ_SCI ## hwch ## _TRANSMITTER_READY, \ - .num_group = -1, \ - .id = -1, \ - } \ - /**/ - -#if CONFIG_SER_MULTI -#define SCI_DESC_MULTI(hwch, group_, id_) \ - { \ - .hw = \ - { \ - .table = &SCI_MULTI_VT, \ - .rxbuffer = ser ## hwch ## _fifo_rx, \ - .txbuffer = ser ## hwch ## _fifo_tx, \ - .rxbuffer_size = countof(ser ## hwch ## _fifo_rx), \ - .txbuffer_size = countof(ser ## hwch ## _fifo_tx), \ - }, \ - .regs = ®_SCI[hwch], \ - .irq_rx = IRQ_SCI ## hwch ## _RECEIVER_FULL, \ - .irq_tx = IRQ_SCI ## hwch ## _TRANSMITTER_READY, \ - .num_group = group_, \ - .id = id_, \ - } \ - /**/ -#endif /* CONFIG_SER_MULTI */ - -// \todo Move this into hw.h, with a little preprocessor magic -static struct SCI SCIDescs[] = -{ - SCI_DESC_NORMAL(0), - SCI_DESC_MULTI(1, 0, 0), - SCI_DESC_MULTI(1, 0, 1), -}; - -struct SerialHardware* ser_hw_getdesc(int unit) -{ - ASSERT(unit < countof(SCIDescs)); - return &SCIDescs[unit].hw; -} diff --git a/drv/ser_i196.c b/drv/ser_i196.c deleted file mode 100644 index a87de6fa..00000000 --- a/drv/ser_i196.c +++ /dev/null @@ -1,134 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief CPU specific serial I/O driver - */ - -/*#* - *#* $Log$ - *#* Revision 1.7 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.6 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.5 2004/12/13 11:51:08 bernie - *#* DISABLE_INTS/ENABLE_INTS: Convert to IRQ_DISABLE/IRQ_ENABLE. - *#* - *#* Revision 1.4 2004/08/25 14:12:08 rasky - *#* Aggiornato il comment block dei log RCS - *#* - *#* Revision 1.3 2004/06/03 11:27:09 bernie - *#* Add dual-license information. - *#* - *#* Revision 1.2 2004/05/23 18:21:53 bernie - *#* Trim CVS logs and cleanup header info. - *#* - *#*/ - -#include "hw.h" -#include "serhw.h" - -#define SER_HW_ENABLE_TX \ - ATOMIC( \ - if (!ser_sending) \ - { \ - ser_sending = true; \ - (INT_PEND1 |= INT1F_TI) \ - } \ - ); - -static volatile bool ser_sending; - -// Serial TX intr -INTERRUPT(0x30) void TI_interrupt(void) -{ - if (CANT_SEND) - { - ser_sending = false; - return; - } - - /* Can we send two bytes at the same time? */ - if (SP_STAT & SPSF_TX_EMPTY) - { - SBUF = fifo_pop(&ser_txfifo); - - if (CANT_SEND) - { - ser_sending = false; - return; - } - } - - SBUF = fifo_pop(&ser_txfifo); -} - -INTERRUPT(0x32) void RI_interrupt(void) -{ - ser_status |= SP_STAT & - (SPSF_OVERRUN_ERROR | SPSF_PARITY_ERROR | SPSF_FRAMING_ERROR); - if (fifo_isfull(&ser_rxfifo)) - ser_status |= SERRF_RXFIFOOVERRUN; - else - fifo_push(&ser_rxfifo, SBUF); -} - -static void ser_setbaudrate(unsigned long rate) -{ - // Calcola il periodo per la generazione del baud rate richiesto - uint16_t baud = (uint16_t)(((CLOCK_FREQ / 16) / rate) - 1) | 0x8000; - BAUD_RATE = (uint8_t)baud; - BAUD_RATE = (uint8_t)(baud >> 8); -} - -static void ser_hw_init(void) -{ - // Inizializza la porta seriale - SP_CON = SPCF_RECEIVE_ENABLE | SPCF_MODE1; - ioc1_img |= IOC1F_TXD_SEL | IOC1F_EXTINT_SRC; - IOC1 = ioc1_img; - - // Svuota il buffer di ricezione - { - uint8_t dummy = SBUF; - } - - // Abilita gli interrupt - INT_MASK1 |= INT1F_TI | INT1F_RI; -} - diff --git a/drv/timer_dsp56k.h b/drv/timer_dsp56k.h deleted file mode 100644 index f86cb50b..00000000 --- a/drv/timer_dsp56k.h +++ /dev/null @@ -1,148 +0,0 @@ -#error This code must be revised for the new timer API -/** - * \file - * - * - * \version $Id$ - * - * \author Giovanni Bajo - * - * \brief Driver module for DSP56K - */ - -/*#* - *#* $Log$ - *#* Revision 1.10 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.9 2006/02/21 21:28:02 bernie - *#* New time handling based on TIMER_TICKS_PER_SEC to support slow timers with ticks longer than 1ms. - *#* - *#* Revision 1.8 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.7 2005/04/11 19:10:28 bernie - *#* Include top-level headers from cfg/ subdir. - *#* - *#* Revision 1.6 2004/11/16 22:37:14 bernie - *#* Replace IPTR with iptr_t. - *#* - *#* Revision 1.5 2004/08/25 14:12:08 rasky - *#* Aggiornato il comment block dei log RCS - *#* - *#* Revision 1.4 2004/07/30 14:27:49 rasky - *#* Aggiornati alcuni file DSP56k per la nuova libreria di IRQ management - *#* - *#* Revision 1.3 2004/06/06 18:30:34 bernie - *#* Import DSP56800 changes from SC. - *#* - *#* Revision 1.2 2004/06/03 11:27:09 bernie - *#* Add dual-license information. - *#* - *#* Revision 1.1 2004/05/23 18:23:30 bernie - *#* Import drv/timer module. - *#* - *#*/ - -#ifndef DRV_TIMER_DSP56K_H -#define DRV_TIMER_DSP56K_H - -#include "timer.h" -#include -#include -#include -#include - -// Calculate register pointer and irq vector from hw.h setting -#define REG_SYSTEM_TIMER PP_CAT(REG_TIMER_, SYSTEM_TIMER) -#define SYSTEM_TIMER_IRQ_VECTOR PP_CAT(IRQ_TIMER_, SYSTEM_TIMER) - -/// Prescaler for the system timer -#define TIMER_PRESCALER 16 - -/// Frequency of the hardware high precision timer -#define TIMER_HW_HPTICKS_PER_SEC (IPBUS_FREQ / TIMER_PRESCALER) - -/// Type of time expressed in ticks of the hardware high precision timer -typedef uint16_t hptime_t; - -static void system_timer_isr(UNUSED(iptr_t, arg)); - -static void timer_hw_init(void) -{ - uint16_t compare; - - // Clear compare flag status and enable interrupt on compare - REG_SYSTEM_TIMER->SCR &= ~REG_TIMER_SCR_TCF; - REG_SYSTEM_TIMER->SCR |= REG_TIMER_SCR_TCFIE; - - // Calculate the compare value needed to generate an interrupt exactly - // TICKS_PER_SEC times each second (usually, every millisecond). Check that - // the calculation is accurate, otherwise there is a precision error - // (probably the prescaler is too big or too small). - compare = TIMER_HW_HPTICKS_PER_SEC / TICKS_PER_SEC; - ASSERT((uint32_t)compare * TICKS_PER_SEC == IPBUS_FREQ / TIMER_PRESCALER); - REG_SYSTEM_TIMER->CMP1 = compare; - - // The value for reload (at initializationa and after compare is met) is zero - REG_SYSTEM_TIMER->LOAD = 0; - - // Set the interrupt handler and priority - irq_install(SYSTEM_TIMER_IRQ_VECTOR, &system_timer_isr, NULL); - irq_setpriority(SYSTEM_TIMER_IRQ_VECTOR, IRQ_PRIORITY_SYSTEM_TIMER); - - // Small preprocessor trick to generate the REG_TIMER_CTRL_PRIMARY_IPBYNN macro - // needed to set the prescaler - #define REG_CONTROL_PRESCALER PP_CAT(REG_TIMER_CTRL_PRIMARY_IPBY, TIMER_PRESCALER) - - // Setup the counter and start counting - REG_SYSTEM_TIMER->CTRL = - REG_TIMER_CTRL_MODE_RISING | // count rising edges (normal) - REG_CONTROL_PRESCALER | // frequency (IPbus / TIMER_PRESCALER) - REG_TIMER_CTRL_LENGTH; // up to CMP1, then reload -} - -INLINE void timer_hw_irq(void) -{ - // Clear the overflow flag so that we are ready for another interrupt - REG_SYSTEM_TIMER->SCR &= ~REG_TIMER_SCR_TCF; -} - -INLINE hptime_t timer_hw_hpread(void) -{ - return REG_SYSTEM_TIMER->CNTR; -} - -#define DEFINE_TIMER_ISR \ - static void system_timer_isr(UNUSED(iptr_t, arg)) - -#endif /* DRV_TIMER_DSP56_H */ diff --git a/drv/timer_i196.h b/drv/timer_i196.h deleted file mode 100644 index 5c4bc8bd..00000000 --- a/drv/timer_i196.h +++ /dev/null @@ -1,89 +0,0 @@ -#error This code must be revised for the new timer API -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Low-level timer module for AVR - */ - -/*#* - *#* $Log$ - *#* Revision 1.7 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.6 2006/02/21 21:28:02 bernie - *#* New time handling based on TIMER_TICKS_PER_SEC to support slow timers with ticks longer than 1ms. - *#* - *#* Revision 1.5 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.4 2004/12/13 11:51:08 bernie - *#* DISABLE_INTS/ENABLE_INTS: Convert to IRQ_DISABLE/IRQ_ENABLE. - *#* - *#* Revision 1.3 2004/08/25 14:12:08 rasky - *#* Aggiornato il comment block dei log RCS - *#* - *#* Revision 1.2 2004/06/03 11:27:09 bernie - *#* Add dual-license information. - *#* - *#* Revision 1.1 2004/05/23 18:23:30 bernie - *#* Import drv/timer module. - *#* - *#*/ - -#ifndef TIMER_I196_H -#define TIMER_I196_H - -/** - * Retrigger TIMER2, adjusting the time to account for - * the interrupt prologue latency. - */ -#define TIMER_RETRIGGER (TIMER2 -= TICKS_RATE) - -#define TIMER_INIT \ - TIMER2 = (65535 - TICKS_RATE); \ - INT_MASK1 |= INT1F_T2OVF; \ - ATOMIC( \ - WSR = 1; \ - IOC3 |= IOC3F_T2_ENA; \ - WSR = 0; \ - ) - -#define DEFINE_TIMER_ISR \ - INTERRUPT(0x38) void TM2_OVFL_interrupt(void); \ - INTERRUPT(0x38) void TM2_OVFL_interrupt(void) - -#endif /* DRV_TIMER_I196_H */