From 22240d0455c6bd837fe928b29068e795be3febae Mon Sep 17 00:00:00 2001 From: aleph Date: Mon, 2 Aug 2004 20:20:29 +0000 Subject: [PATCH 1/1] Merge from kseries git-svn-id: https://src.develer.com/svnoss/bertos/trunk@99 38d2e660-2303-0410-9eaa-f027e97ec537 --- compiler.h | 29 +++++++++++++++-- cpu.h | 30 +++++++++++++----- drv/kdebug.c | 79 +++++++++++++++++++++++++++++++++++++++++++---- drv/ser.h | 8 +++-- drv/ser_avr.c | 63 ++++++++++++++++++++++++++++++++----- drv/timer.c | 5 ++- drv/timer.h | 18 ++++++++++- drv/timer_avr.h | 12 +++++-- kern/proc.c | 9 +++++- kern/switch_avr.S | 19 ++++++++++++ mware/fifobuf.h | 5 ++- 11 files changed, 245 insertions(+), 32 deletions(-) diff --git a/compiler.h b/compiler.h index 0f6e8f7b..a2689e8e 100755 --- a/compiler.h +++ b/compiler.h @@ -15,6 +15,9 @@ /* * $Log$ + * Revision 1.13 2004/08/02 20:20:29 aleph + * Merge from project_ks + * * Revision 1.12 2004/08/01 01:21:17 bernie * LIKELY(), UNLIKELY(): New compiler-specific macros. * @@ -256,9 +259,29 @@ /* Simple macros */ -#define ABS(a) (((a) < 0) ? -(a) : (a)) -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#if GNUC_PREREQ(2,0) + #define ABS(n) ({ \ + __typeof__(n) _n = (n); \ + (_n < 0) ? -_n : _n; \ + }) + #define MIN(a,b) ({ \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + (void)(&_a == &_b); /* ensure same type */ \ + (_a < _b) ? _a : _b; \ + }) + #define MAX(a,b) ({ \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + (void)(&_a == &_b); /* ensure same type */ \ + (_a > _b) ? _a : _b; \ + }) +#else /* !GNUC */ + /* Buggy macros for inferior compilers */ + #define ABS(a) (((a) < 0) ? -(a) : (a)) + #define MIN(a,b) (((a) < (b)) ? (a) : (b)) + #define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif /* !GNUC */ #ifndef BV /*! Convert a bit value to a binary flag */ diff --git a/cpu.h b/cpu.h index f373b7b1..096a5563 100755 --- a/cpu.h +++ b/cpu.h @@ -17,6 +17,9 @@ /* * $Log$ + * Revision 1.10 2004/08/02 20:20:29 aleph + * Merge from project_ks + * * Revision 1.9 2004/07/30 14:24:16 rasky * Task switching con salvataggio perfetto stato di interrupt (SR) * Kernel monitor per dump informazioni su stack dei processi @@ -52,15 +55,12 @@ #include "compiler.h" -//! Initialization value for registers in stack frame -#define CPU_REG_INIT_VALUE(reg) 0 - -// Macros for determining CPU endianess +// Macros for determining CPU endianness #define CPU_BIG_ENDIAN 0x1234 #define CPU_LITTLE_ENDIAN 0x3412 // Macros to include cpu-specific version of the headers -#define CPU_HEADER(module) PP_STRINGIZE(PP_CAT4(module, _, CPU_ID, .h)) +#define CPU_HEADER(module) PP_STRINGIZE(PP_CAT3(module, _, CPU_ID).h) #if CPU_I196 @@ -136,11 +136,27 @@ typedef uint8_t cpuflags_t; typedef uint8_t cpustack_t; - #define CPU_REGS_CNT 32 - #define CPU_SAVED_REGS_CNT 18 + /* Register counts include SREG too */ + #define CPU_REGS_CNT 33 + #define CPU_SAVED_REGS_CNT 19 #define CPU_STACK_GROWS_UPWARD 0 #define CPU_SP_ON_EMPTY_SLOT 1 #define CPU_BYTE_ORDER CPU_LITTLE_ENDIAN + + /*! + * Initialization value for registers in stack frame. + * The register index is not directly corrispondent to CPU + * register numbers. Index 0 is the SREG register: the initial + * value is all 0 but the interrupt bit (bit 7). + */ + #define CPU_REG_INIT_VALUE(reg) (reg == 0 ? 0x80 : 0) + +#endif + + +//! Default for macro not defined in the right arch section +#ifndef CPU_REG_INIT_VALUE + #define CPU_REG_INIT_VALUE(reg) 0 #endif diff --git a/drv/kdebug.c b/drv/kdebug.c index 063df825..ff692b34 100755 --- a/drv/kdebug.c +++ b/drv/kdebug.c @@ -16,6 +16,9 @@ /* * $Log$ + * Revision 1.9 2004/08/02 20:20:29 aleph + * Merge from project_ks + * * Revision 1.8 2004/07/30 14:26:33 rasky * Semplificato l'output dell'ASSERT * Aggiunta ASSERT2 con stringa di help opzionalmente disattivabile @@ -69,6 +72,19 @@ #elif CPU_AVR #include #if CONFIG_KDEBUG_PORT == 0 + + /* External 485 transceiver on UART0 (to be overridden in "hw.h"). */ + #if !defined(SER_UART0_485_INIT) + #if defined(SER_UART0_485_RX) || defined(SER_UART0_485_TX) + #error SER_UART0_485_INIT, SER_UART0_485_RX and SER_UART0_485_TX must be defined together + #endif + #define SER_UART0_485_INIT do {} while (0) + #define SER_UART0_485_TX do {} while (0) + #define SER_UART0_485_RX do {} while (0) + #elif !defined(SER_UART0_485_RX) || !defined(SER_UART0_485_TX) + #error SER_UART0_485_INIT, SER_UART0_485_RX and SER_UART0_485_TX must be defined together + #endif + #if defined(__AVR_ATmega64__) #define UCR UCSR0B #define UDR UDR0 @@ -77,15 +93,63 @@ #define UCR UCSRB #define USR UCSRA #endif + #define KDBG_WAIT_READY() do { loop_until_bit_is_set(USR, UDRE); } while(0) - #define KDBG_WRITE_CHAR(c) do { UCR |= BV(TXEN); UDR = (c); } while(0) - #define KDBG_MASK_IRQ(old) do { (old) = UCR & BV(TXCIE); cbi(UCR, TXCIE); } while(0) - #define KDBG_RESTORE_IRQ(old) do { UCR |= (old); } while(0) + #define KDBG_WAIT_TXDONE() do { loop_until_bit_is_set(USR, TXC); } while(0) + /* + * BUG: before sending a new character the TXC flag is cleared to allow + * KDBG_WAIT_TXDONE() to work properly, but, if KDBG_WRITE_CHAR() is called + * after the RXC flag is set by hardware, a new TXC could be generated + * after we clear it and before the new character is put in UDR. In this + * case if a 485 is used the transceiver will be put in RX mode while + * transmitting the last char. + */ + #define KDBG_WRITE_CHAR(c) do { USR |= BV(TXC); UDR = (c); } while(0) + + #define KDBG_MASK_IRQ(old) do { \ + SER_UART0_485_TX; \ + (old) = UCR; \ + UCR |= BV(TXEN); \ + UCR &= ~(BV(TXCIE) | BV(UDRIE)); \ + } while(0) + + #define KDBG_RESTORE_IRQ(old) do { \ + KDBG_WAIT_TXDONE(); \ + SER_UART0_485_RX; \ + UCR = (old); \ + } while(0) + #elif CONFIG_KDEBUG_PORT == 1 + + /* External 485 transceiver on UART1 (to be overridden in "hw.h"). */ + #ifndef SER_UART1_485_INIT + #if defined(SER_UART1_485_RX) || defined(SER_UART1_485_TX) + #error SER_UART1_485_INIT, SER_UART1_485_RX and SER_UART1_485_TX must be defined together + #endif + #define SER_UART1_485_INIT do {} while (0) + #define SER_UART1_485_TX do {} while (0) + #define SER_UART1_485_RX do {} while (0) + #elif !defined(SER_UART1_485_RX) || !defined(SER_UART1_485_TX) + #error SER_UART1_485_INIT, SER_UART1_485_RX and SER_UART1_485_TX must be defined together + #endif + #define KDBG_WAIT_READY() do { loop_until_bit_is_set(UCSR1A, UDRE); } while(0) - #define KDBG_WRITE_CHAR(c) do { UCSR1B |= BV(TXEN); UDR1 = (c); } while(0) - #define KDBG_MASK_IRQ(old) do { (old) = UCSR1B & BV(TXCIE); cbi(UCSR1B, TXCIE); } while(0) - #define KDBG_RESTORE_IRQ(old) do { UCSR1B |= (old); } while(0) + #define KDBG_WAIT_TXDONE() do { loop_until_bit_is_set(UCSR1A, TXC); } while(0) + #define KDBG_WRITE_CHAR(c) do { UCSR1A |= BV(TXC); UDR1 = (c); } while(0) + + #define KDBG_MASK_IRQ(old) do { \ + SER_UART1_485_TX; \ + (old) = UCSR1B; \ + UCSR1B |= BV(TXEN); \ + UCSR1B &= ~(BV(TXCIE) | BV(UDRIE)); \ + } while(0) + + #define KDBG_RESTORE_IRQ(old) do { \ + KDBG_WAIT_TXDONE(); \ + SER_UART1_485_RX; \ + UCSR1B = (old); \ + } while(0) + #else #error CONFIG_KDEBUG_PORT should be either 0 or 1 #endif @@ -123,9 +187,11 @@ void kdbg_init(void) #if CONFIG_KDEBUG_PORT == 0 UBRR0H = (uint8_t)(period>>8); UBRR0L = (uint8_t)period; + SER_UART0_485_INIT; #elif CONFIG_KDEBUG_PORT == 1 UBRR1H = (uint8_t)(period>>8); UBRR1L = (uint8_t)period; + SER_UART1_485_INIT; #else #error CONFIG_KDEBUG_PORT must be either 0 or 1 #endif @@ -134,6 +200,7 @@ void kdbg_init(void) UBRRL = (uint8_t)period; #elif defined(__AVR_ATmega103__) UBRR = (uint8_t)period; + SER_UART0_485_INIT; #else #error Unknown arch #endif diff --git a/drv/ser.h b/drv/ser.h index e4350556..dd38f3e0 100755 --- a/drv/ser.h +++ b/drv/ser.h @@ -14,6 +14,9 @@ /* * $Log$ + * Revision 1.8 2004/08/02 20:20:29 aleph + * Merge from project_ks + * * Revision 1.7 2004/07/30 14:15:53 rasky * Nuovo supporto unificato per detect della CPU * @@ -108,10 +111,9 @@ enum #else #error unknown architecture #endif - - SER_CNT /**< Number of serial ports */ + SER_CNT /*!< Number of serial ports */ }; -/* @} */ +/*\}*/ struct SerialHardware; diff --git a/drv/ser_avr.c b/drv/ser_avr.c index 2e94c219..c43f7238 100755 --- a/drv/ser_avr.c +++ b/drv/ser_avr.c @@ -38,6 +38,9 @@ /* * $Log$ + * Revision 1.9 2004/08/02 20:20:29 aleph + * Merge from project_ks + * * Revision 1.8 2004/07/29 22:57:09 bernie * Several tweaks to reduce code size on ATmega8. * @@ -83,11 +86,27 @@ #endif /* External 485 transceiver on UART0 (to be overridden in "hw.h"). */ -#ifndef SER_UART0_485_INIT -#define SER_UART0_485_INIT do {} while (0) +#if !defined(SER_UART0_485_INIT) + #if defined(SER_UART0_485_RX) || defined(SER_UART0_485_TX) + #error SER_UART0_485_INIT, SER_UART0_485_RX and SER_UART0_485_TX must be defined together + #endif + #define SER_UART0_485_INIT do {} while (0) + #define SER_UART0_485_TX do {} while (0) + /* SER_UART0_485_RX must not be defined! */ +#elif !defined(SER_UART0_485_RX) || !defined(SER_UART0_485_TX) + #error SER_UART0_485_INIT, SER_UART0_485_RX and SER_UART0_485_TX must be defined together #endif -#ifndef SER_UART0_485_TX -#define SER_UART0_485_TX do {} while (0) + +/* External 485 transceiver on UART1 (to be overridden in "hw.h"). */ +#ifndef SER_UART1_485_INIT + #if defined(SER_UART1_485_RX) || defined(SER_UART1_485_TX) + #error SER_UART1_485_INIT, SER_UART1_485_RX and SER_UART1_485_TX must be defined together + #endif + #define SER_UART1_485_INIT do {} while (0) + #define SER_UART1_485_TX do {} while (0) + /* SER_UART1_485_RX must not be defined! */ +#elif !defined(SER_UART1_485_RX) || !defined(SER_UART1_485_TX) + #error SER_UART1_485_INIT, SER_UART1_485_RX and SER_UART1_485_TX must be defined together #endif @@ -199,12 +218,13 @@ static void uart0_setbaudrate(UNUSED(struct SerialHardware *, _hw), unsigned lon { /* Compute baud-rate period */ uint16_t period = (((CLOCK_FREQ / 16UL) + (rate / 2)) / rate) - 1; - DB(kprintf("uart0_setbaudrate(rate=%lu): period=%d\n", rate, period);) #ifndef __AVR_ATmega103__ UBRR0H = (period) >> 8; #endif UBRR0L = (period); + + DB(kprintf("uart0_setbaudrate(rate=%lu): period=%d\n", rate, period);) } static void uart0_setparity(UNUSED(struct SerialHardware *, _hw), int parity) @@ -220,6 +240,10 @@ static void uart1_enabletxirq(UNUSED(struct SerialHardware *, _hw)) { #if CONFIG_SER_TXFILL && (CONFIG_KBUS_PORT == 1) UCSR1B = BV(RXCIE) | BV(UDRIE) | BV(RXEN) | BV(TXEN) | BV(UCSZ2); +#elif defined(SER_UART1_485_TX) + /* Disable receiver, enable transmitter, switch 485 transceiver. */ + UCSR1B = BV(UDRIE) | BV(TXEN); + SER_UART1_485_TX; #else UCSR1B = BV(RXCIE) | BV(UDRIE) | BV(RXEN) | BV(TXEN); #endif @@ -242,7 +266,7 @@ static void uart1_init(UNUSED(struct SerialHardware *, _hw), UNUSED(struct Seria #else UCSR1B = BV(RXCIE) | BV(RXEN); #endif - + SER_UART1_485_INIT; RTS_ON; } @@ -255,10 +279,11 @@ static void uart1_setbaudrate(UNUSED(struct SerialHardware *, _hw), unsigned lon { /* Compute baud-rate period */ uint16_t period = (((CLOCK_FREQ / 16UL) + (rate / 2)) / rate) - 1; - DB(kprintf("uart1_setbaudrate(rate=%ld): period=%d\n", rate, period);) UBRR1H = (period) >> 8; UBRR1L = (period); + + DB(kprintf("uart1_setbaudrate(rate=%ld): period=%d\n", rate, period);) } static void uart1_setparity(UNUSED(struct SerialHardware *, _hw), int parity) @@ -409,6 +434,13 @@ SIGNAL(SIG_UART1_DATA) */ UCSR1B &= ~BV(TXB8); UDR1 = SER_FILL_BYTE; +#elif defined(SER_UART1_485_RX) + /* + * - Disable UDR empty interrupt + * - Disable the transmitter (the in-progress transfer will complete) + * - Enable the transmit complete interrupt for the 485 tranceiver. + */ + UCSR1B = BV(TXCIE); #else /* Disable UDR empty interrupt and transmitter */ UCSR1B = BV(RXCIE) | BV(RXEN); @@ -432,6 +464,23 @@ SIGNAL(SIG_UART1_DATA) UDR1 = fifo_pop(txfifo); } } + +#ifdef SER_UART1_485_RX +/*! + * Serial port 1 TX complete interrupt handler. + * + * \sa port 0 TX complete handler. + */ +SIGNAL(SIG_UART1_TRANS) +{ + /* Turn the 485 tranceiver into receive mode. */ + SER_UART1_485_RX; + + /* Enable UART receiver and receive interrupt. */ + UCSR1B = BV(RXCIE) | BV(RXEN); +} +#endif /* SER_UART1_485_RX */ + #endif // AVR_HAS_UART1 diff --git a/drv/timer.c b/drv/timer.c index f471cb57..24287cb9 100755 --- a/drv/timer.c +++ b/drv/timer.c @@ -15,6 +15,9 @@ /* * $Log$ + * Revision 1.11 2004/08/02 20:20:29 aleph + * Merge from project_ks + * * Revision 1.10 2004/07/30 14:15:53 rasky * Nuovo supporto unificato per detect della CPU * @@ -216,7 +219,7 @@ DEFINE_TIMER_ISR REMOVE((Node *)timer); /* Execute the associated event */ - event_doIntr(&timer->expire); + event_do(&timer->expire); } #endif /* CONFIG_TIMER_DISABLE_EVENTS */ diff --git a/drv/timer.h b/drv/timer.h index 07147416..3180e1b8 100755 --- a/drv/timer.h +++ b/drv/timer.h @@ -15,6 +15,9 @@ /* * $Log$ + * Revision 1.13 2004/08/02 20:20:29 aleph + * Merge from project_ks + * * Revision 1.12 2004/07/30 14:34:10 rasky * Vari fix per documentazione e commenti * Aggiunte PP_CATn e STATIC_ASSERT @@ -62,7 +65,7 @@ #include /*! Number of timer ticks per second. */ -#define TICKS_PER_SEC 1000 +#define TICKS_PER_SEC ((time_t)1000) /* Function protos */ extern void timer_init(void); @@ -180,5 +183,18 @@ INLINE time_t timer_tick_unlocked(void) /* OBSOLETE */ #define timer_gettick_irq timer_tick_unlocked + +/*! + * Return the minutes passed since timer start. + * + * The minutes uptime is computed directly from system tick counter: + * in case of a 4 bytes time_t after 71582 minutes the value will + * wrap around. + */ +INLINE time_t timer_minutes(void) +{ + return timer_gettick() / (TICKS_PER_SEC * 60); +} + #endif /* DRV_TIMER_H */ diff --git a/drv/timer_avr.h b/drv/timer_avr.h index b536c953..7a68b615 100755 --- a/drv/timer_avr.h +++ b/drv/timer_avr.h @@ -15,6 +15,9 @@ /* * $Log$ + * Revision 1.10 2004/08/02 20:20:29 aleph + * Merge from project_ks + * * Revision 1.9 2004/07/22 02:01:14 bernie * Use TIMER_PRESCALER consistently. * @@ -157,8 +160,13 @@ TIFR = BV(OCF2) | BV(TOV2); /* Setup Timer/Counter interrupt */ -#warning Aleph, please use TIMER_PRESCALER here - TCCR2 = BV(WGM21) | BV(CS21) | BV(CS20); + TCCR2 = BV(WGM21) + #if TIMER_PRESCALER == 64 + | BV(CS21) | BV(CS20) + #else + #error Unsupported value of TIMER_PRESCALER + #endif + ; /* Clear on Compare match & prescaler = 64, internal sys clock. When changing prescaler change TIMER_HW_HPTICKS_PER_SEC too */ TCNT2 = 0x00; /* initialization of Timer/Counter */ diff --git a/kern/proc.c b/kern/proc.c index 3971df00..6ce3071a 100755 --- a/kern/proc.c +++ b/kern/proc.c @@ -17,6 +17,9 @@ /* * $Log$ + * Revision 1.7 2004/08/02 20:20:29 aleph + * Merge from project_ks + * * Revision 1.6 2004/07/30 14:24:16 rasky * Task switching con salvataggio perfetto stato di interrupt (SR) * Kernel monitor per dump informazioni su stack dei processi @@ -47,7 +50,7 @@ #include /* memset() */ -/*! CPU dependent context switching routines +/*! CPU dependent context switching routines * \note This function *MUST* preserve also the status of the interrupts. */ extern void asm_switch_context(cpustack_t **new_sp, cpustack_t **save_sp); @@ -157,6 +160,9 @@ void monitor_debug_stacks(void) static void proc_init_struct(Process* proc) { + /* Avoid warning for unused argument */ + (void)proc; + #if CONFIG_KERN_SIGNALS proc->sig_recv = 0; #endif @@ -166,6 +172,7 @@ static void proc_init_struct(Process* proc) #endif } + void proc_init(void) { INITLIST(&ProcReadyList); diff --git a/kern/switch_avr.S b/kern/switch_avr.S index 08dfbe8d..84fa14d3 100755 --- a/kern/switch_avr.S +++ b/kern/switch_avr.S @@ -16,10 +16,18 @@ #include +/* + * NOTE: At each change of this function affecting proc.c + * (i.e. arguments, data stored in the stack) bump up version + * number in asm_switch_version(). + */ + /* void asm_switch_context(void **new_sp, void **save_sp) */ .globl asm_switch_context asm_switch_context: + in r0,SREG-__SFR_OFFSET + push r0 ; push r0 caller-save ; push r1 caller-save push r2 @@ -98,5 +106,16 @@ asm_switch_context: pop r2 ; pop r1 caller-save ; pop r0 caller-save + pop r0 + out SREG-__SFR_OFFSET,r0 + + ret + +/* int asm_switch_version(void) */ +.globl asm_switch_version +asm_switch_version: + ldi r24,lo8(1) + ldi r25,hi8(1) ret + diff --git a/mware/fifobuf.h b/mware/fifobuf.h index a643a7e6..12de2949 100755 --- a/mware/fifobuf.h +++ b/mware/fifobuf.h @@ -43,6 +43,9 @@ /* * $Log$ + * Revision 1.12 2004/08/02 20:20:29 aleph + * Merge from project_ks + * * Revision 1.11 2004/07/30 14:15:53 rasky * Nuovo supporto unificato per detect della CPU * @@ -248,7 +251,7 @@ INLINE void fifo_flush(FIFOBuffer *fb) ENABLE_IRQRESTORE(flags); } -#endif /* !__AVR__ */ +#endif /* !CPU_AVR */ /*! -- 2.25.1