diff --git a/Makefile.include b/Makefile.include new file mode 100644 index 0000000..427eaf0 --- /dev/null +++ b/Makefile.include @@ -0,0 +1,4 @@ +ifeq ($(CPU),stm32f407vgt6) + export USEMODULE += stm32f4xxstdperi + export UNDEF += $(BINDIR)syscalls.o +endif diff --git a/stm32f407vgt6/atom.c b/stm32f407vgt6/atom.c index 484c564..934b54a 100644 --- a/stm32f407vgt6/atom.c +++ b/stm32f407vgt6/atom.c @@ -4,152 +4,16 @@ * Created on: 10.08.2012 * Author: pfeiffer */ -#include "sched.h" +#include "atomic.h" #include "cpu.h" -extern void sched_task_exit(void); -void sched_task_return(void); - -unsigned int atomic_set_return(unsigned int* p, unsigned int uiVal) { - //unsigned int cspr = disableIRQ(); //crashes - dINT(); - unsigned int uiOldVal = *p; - *p = uiVal; - //restoreIRQ(cspr); //crashes - eINT(); - return uiOldVal; -} - -void cpu_switch_context_exit(void){ - sched_run(); - sched_task_return(); -} - - -void thread_yield(void) { - asm("svc 0x01\n"); -} - - -__attribute__((naked)) -void SVC_Handler(void) +unsigned int atomic_set_return(unsigned int *p, unsigned int uiVal) { - save_context(); - asm("bl sched_run"); - /* call scheduler update active_thread variable with pdc of next thread - * the thread that has higest priority and is in PENDING state */ - restore_context(); -} - - /* kernel functions */ -void ctx_switch(void) -{ - /* Save return address on stack */ - /* stmfd sp!, {lr} */ - - /* disable interrupts */ - /* mov lr, #NOINT|SVCMODE */ - /* msr CPSR_c, lr */ - /* cpsid i */ - - /* save other register */ - asm("nop"); - - asm("mov r12, sp"); - asm("stmfd r12!, {r4-r11}"); - - /* save user mode stack pointer in *active_thread */ - asm("ldr r1, =active_thread"); /* r1 = &active_thread */ - asm("ldr r1, [r1]"); /* r1 = *r1 = active_thread */ - asm("str r12, [r1]"); /* store stack pointer in tasks pdc*/ - - sched_task_return(); -} -/* call scheduler so active_thread points to the next task */ -void sched_task_return(void) -{ - /* load pdc->stackpointer in r0 */ - asm("ldr r0, =active_thread"); /* r0 = &active_thread */ - asm("ldr r0, [r0]"); /* r0 = *r0 = active_thread */ - asm("ldr sp, [r0]"); /* sp = r0 restore stack pointer*/ - asm("pop {r4}"); /* skip exception return */ - asm(" pop {r4-r11}"); - asm(" pop {r0-r3,r12,lr}"); /* simulate register restor from stack */ -// asm("pop {r4}"); /*foo*/ - asm("pop {pc}"); -} -/* - * cortex m4 knows stacks and handles register backups - * - * so use different stack frame layout - * - * - * with float storage - * ------------------------------------------------------------------------------------------------------------------------------------ - * | R0 | R1 | R2 | R3 | LR | PC | xPSR | S0 | S1 | S2 | S3 | S4 | S5 | S6 | S7 | S8 | S9 | S10 | S11 | S12 | S13 | S14 | S15 | FPSCR | - * ------------------------------------------------------------------------------------------------------------------------------------ - * - * without - * - * -------------------------------------- - * | R0 | R1 | R2 | R3 | LR | PC | xPSR | - * -------------------------------------- - * - * - */ -char * thread_stack_init(void * task_func, void * stack_start, int stack_size ) { - unsigned int * stk; - stk = (unsigned int *) (stack_start + stack_size); - - /* marker */ - stk--; - *stk = 0x77777777; - - //FIXME FPSCR - stk--; - *stk = (unsigned int) 0; - - //S0 - S15 - for (int i = 15; i >= 0; i--) { - stk--; - *stk = i; - } - - //FIXME xPSR - stk--; - *stk = (unsigned int) 0x01000200; - - //program counter - stk--; - *stk = (unsigned int) task_func; - - /* link register */ - stk--; - *stk = (unsigned int) 0x0; - - /* r12 */ - stk--; - *stk = (unsigned int) 0; - - /* r0 - r3 */ - for (int i = 3; i >= 0; i--) { - stk--; - *stk = i; - } - - /* r11 - r4 */ - for (int i = 11; i >= 4; i--) { - stk--; - *stk = i; - } - - /* foo */ - /*stk--; - *stk = (unsigned int) 0xDEADBEEF;*/ - - /* lr means exception return code */ - stk--; - *stk = (unsigned int) 0xfffffff9; // return to taskmode main stack pointer - - return (char*) stk; + //unsigned int cspr = disableIRQ(); //crashes + dINT(); + unsigned int uiOldVal = *p; + *p = uiVal; + //restoreIRQ(cspr); //crashes + eINT(); + return uiOldVal; } diff --git a/stm32f407vgt6/cpu.c b/stm32f407vgt6/cpu.c index 9e78c6f..b27857f 100644 --- a/stm32f407vgt6/cpu.c +++ b/stm32f407vgt6/cpu.c @@ -5,37 +5,152 @@ * Author: pfeiffer */ -#include "stdint.h" -#include "stm32f4xx_tim.h" +#include -void stm32f4_pclk_scale(uint32_t source, uint32_t target, uint32_t* pclksel, uint32_t* prescale) +#include "stm32f4xx.h" + +#include "cpu.h" +#include "sched.h" + +extern void sched_task_exit(void); + +static inline void save_context(void); +static inline void restore_context(void); + +__attribute__((always_inline)) +static inline void save_context(void) +{ + /* {r0-r3,r12,LR,PC,xPSR} are saved automatically on exception entry */ + + asm("ldr r1, =active_thread"); + /* load address of currend pdc */ + asm("ldr r1, [r1]"); + /* deref pdc */ + asm("cmp r1, #0"); + /* active_thread exists */ + asm("ittt ne"); + /*if active_thread != NULL */ + asm("pushne {r4-r11}"); + /* save unsaved registers */ + /*vstmdb sp!, {s16-s31} */ //FIXME save fpu registers if needed + asm("pushne {LR}"); + /* save exception return value */ + asm("strne sp, [r1]"); + /* write sp to pdc->sp means current threads stack pointer */ +} + +__attribute__((always_inline)) +static inline void restore_context(void) { - uint32_t pclkdiv; - *prescale = source / target; - - if( (*prescale % 4) == 0 ) { - *pclksel = TIM_CKD_DIV4; - pclkdiv = 4; - } else if( (*prescale % 2) == 0 ) { - *pclksel = TIM_CKD_DIV2; - pclkdiv = 2; - } else { - *pclksel = TIM_CKD_DIV1; - pclkdiv = 1; - } - *prescale /= pclkdiv; - - if( *prescale % 2 ) - (*prescale)++; + asm("ldr r0, =active_thread"); + /* load address of currend pdc */ + asm("ldr r0, [r0]"); + /* deref pdc */ + asm("ldr sp, [r0]"); + /* load pdc->sp to sp register */ + + asm("pop {r0}"); + /* restore exception retrun value from stack */ + /*pop {s16-s31} */ //FIXME load fpu register if needed depends on r0 exret + asm("pop {r4-r11}"); + /* load unloaded register */ + // asm("pop {r4}"); /*foo*/ + asm("bx r0"); /* load exception return value to pc causes end of exception*/ + /* {r0-r3,r12,LR,PC,xPSR} are restored automatically on exception return */ } +void cpu_switch_context_exit(void) +{ + __pendSV(); + __enable_irq(); +} + +void thread_yield(void) +{ + __pendSV(); +} + +__attribute__((naked)) +void PendSV_Handler(void) +{ + save_context(); + sched_run(); + restore_context(); +} + +/* + * cortex m4 knows stacks and handles register backups + * + * so use different stack frame layout + * + * + * with float storage + * ------------------------------------------------------------------------------------------------------------------------------------ + * | R0 | R1 | R2 | R3 | LR | PC | xPSR | S0 | S1 | S2 | S3 | S4 | S5 | S6 | S7 | S8 | S9 | S10 | S11 | S12 | S13 | S14 | S15 | FPSCR | + * ------------------------------------------------------------------------------------------------------------------------------------ + * + * without + * + * -------------------------------------- + * | R0 | R1 | R2 | R3 | LR | PC | xPSR | + * -------------------------------------- + * + * + */ +char *thread_stack_init(void *task_func, void *stack_start, uint32_t stack_size) +{ + uint32_t *stk; + stk = (uint32_t *)(stack_start + stack_size); + + /* marker */ + stk--; + *stk = 0x77777777; + + //FIXME FPSCR + stk--; + *stk = (uint32_t) 0; + + //S0 - S15 + for (int i = 15; i >= 0; i--) { + stk--; + *stk = i; + } + + //FIXME xPSR + stk--; + *stk = (uint32_t) 0x01000200; + + //program counter + stk--; + *stk = (uint32_t) task_func; + + /* link register */ + stk--; + *stk = (uint32_t) sched_task_exit; + + /* r12 */ + stk--; + *stk = (uint32_t) 0; + + /* r0 - r3 */ + for (int i = 3; i >= 0; i--) { + stk--; + *stk = i; + } + + /* r11 - r4 */ + for (int i = 11; i >= 4; i--) { + stk--; + *stk = i; + } -void cpu_clock_scale(uint32_t source, uint32_t target, uint32_t* prescale) { - uint32_t pclksel; + /* foo */ + /*stk--; + *stk = (uint32_t) 0xDEADBEEF;*/ - stm32f4_pclk_scale(source, target, &pclksel, prescale); + /* lr means exception return code */ + stk--; + *stk = (uint32_t) 0xfffffff9; // return to taskmode main stack pointer - //PCLKSEL0 = (PCLKSEL0 & ~(BIT2|BIT3)) | (pclksel << 2); // timer 0 - //PCLKSEL0 = (PCLKSEL0 & ~(BIT4|BIT5)) | (pclksel << 4); // timer 1 - //PCLKSEL1 = (PCLKSEL1 & ~(BIT12|BIT13)) | (pclksel << 12); // timer 2 + return (char *) stk; } diff --git a/stm32f407vgt6/include/cpu-conf.h b/stm32f407vgt6/include/cpu-conf.h index 2577ccd..4cb434c 100644 --- a/stm32f407vgt6/include/cpu-conf.h +++ b/stm32f407vgt6/include/cpu-conf.h @@ -71,6 +71,8 @@ and the mailinglist (subscription via web site) #define KERNEL_CONF_STACKSIZE_DEFAULT 2500 #endif +#define KERNEL_CONF_STACKSIZE_PRINTF 4096 + #define KERNEL_CONF_STACKSIZE_IDLE 500 /** @} */ diff --git a/stm32f407vgt6/include/cpu.h b/stm32f407vgt6/include/cpu.h index 3169be6..c48b33b 100644 --- a/stm32f407vgt6/include/cpu.h +++ b/stm32f407vgt6/include/cpu.h @@ -28,96 +28,31 @@ and the mailinglist (subscription via web site) #define __CPU_H /** - * @defgroup + * @defgroup * @ingroup cpu * @{ */ #include + #include "stm32f407vgt6.h" void thread_yield(void); -void cpu_clock_scale(uint32_t source, uint32_t target, uint32_t* prescale); - -__attribute__( ( always_inline ) ) static __INLINE int inISR(void) -{ - return (__get_IPSR() & 0xFF); -} - -__attribute__( ( always_inline ) ) static __INLINE unsigned int disableIRQ(void) -{ - // FIXME PRIMASK is the old CPSR (FAULTMASK ??? BASEPRI ???) - //PRIMASK lesen - unsigned int uiPriMask = __get_PRIMASK(); - __disable_irq(); - return uiPriMask; -} - -__attribute__( ( always_inline ) ) static __INLINE void restoreIRQ(unsigned oldPRIMASK) -{ - //PRIMASK lesen setzen - __set_PRIMASK(oldPRIMASK); -} -__attribute__( ( always_inline ) ) static __INLINE void dINT(void) +__attribute__((always_inline)) static __INLINE void dINT(void) { - __disable_irq(); + __disable_irq(); } -__attribute__( ( always_inline ) ) static __INLINE void eINT(void) +__attribute__((always_inline)) static __INLINE void eINT(void) { - __enable_irq(); + __enable_irq(); } - -__attribute__( ( always_inline ) ) static __INLINE void save_context(void) -{ - /* {r0-r3,r12,LR,PC,xPSR} are saved automatically on exception entry */ - asm("push {r4-r11}"); - /* save unsaved registers */ - /*vstmdb sp!, {s16-s31} */ //FIXME save fpu registers if needed - asm("push {LR}"); - /* save exception return value */ - - asm("ldr r1, =active_thread"); - /* load address of currend pdc */ - asm("ldr r1, [r1]"); - /* deref pdc */ - asm("str sp, [r1]"); - /* write sp to pdc->sp means current threads stack pointer */ -} - -__attribute__( ( always_inline ) ) static __INLINE void restore_context(void) +__attribute__((always_inline)) static __INLINE void __pendSV(void) { - asm("ldr r0, =active_thread"); - /* load address of currend pdc */ - asm("ldr r0, [r0]"); - /* deref pdc */ - asm("ldr sp, [r0]"); - /* load pdc->sp to sp register */ - - asm("pop {r0}"); - /* restore exception retrun value from stack */ - /*pop {s16-s31} */ //FIXME load fpu register if needed depends on r0 exret - asm("pop {r4-r11}"); - /* load unloaded register */ -// asm("pop {r4}"); /*foo*/ - asm("bx r0"); /* load exception return value to pc causes end of exception*/ - /* {r0-r3,r12,LR,PC,xPSR} are restored automatically on exception return */ + SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; } - -//extern uintptr_t __stack_start; ///< end of user stack memory space - -/* -#define SYSMON_STACKPTR ({ register void* __stack_ptr; \ - __asm__ __volatile__ ( "mov %0, sp" : "=r" (__stack_ptr) ); \ - __stack_ptr; }) -#define SYSMON_STACKSTART (&__stack_start) -*/ - -//void lpc2387_pclk_scale(uint32_t source, uint32_t target, uint32_t* pclksel, uint32_t* prescale); -//bool install_irq( int IntNumber, void *HandlerAddr, int Priority ); - /** @} */ #endif /* __CPU_H */ diff --git a/stm32f407vgt6/include/hwtimer_cpu.h b/stm32f407vgt6/include/hwtimer_cpu.h index f87b3ac..cfaa7c6 100644 --- a/stm32f407vgt6/include/hwtimer_cpu.h +++ b/stm32f407vgt6/include/hwtimer_cpu.h @@ -11,8 +11,8 @@ #ifndef HWTIMER_CPU_H_ #define HWTIMER_CPU_H_ -#define ARCH_MAXTIMERS 1 -#define HWTIMER_SPEED 100000 +#define ARCH_MAXTIMERS 4 +#define HWTIMER_SPEED (1000000) #define HWTIMER_MAXTICKS (0xFFFFFFFF) #endif /* HWTIMER_CPU_H_ */ diff --git a/stm32f407vgt6/irq.c b/stm32f407vgt6/irq.c new file mode 100644 index 0000000..0c21ba1 --- /dev/null +++ b/stm32f407vgt6/irq.c @@ -0,0 +1,22 @@ +#include "irq.h" +#include "stm32f4xx.h" + +int inISR(void) +{ + return (__get_IPSR() & 0xFF); +} + +unsigned int disableIRQ(void) +{ + // FIXME PRIMASK is the old CPSR (FAULTMASK ??? BASEPRI ???) + //PRIMASK lesen + unsigned int uiPriMask = __get_PRIMASK(); + __disable_irq(); + return uiPriMask; +} + +void restoreIRQ(unsigned oldPRIMASK) +{ + //PRIMASK lesen setzen + __set_PRIMASK(oldPRIMASK); +} diff --git a/stm32f407vgt6/stm32f4-hwtimer_arch.c b/stm32f407vgt6/stm32f4-hwtimer_arch.c index cc65d2d..0d1f12e 100644 --- a/stm32f407vgt6/stm32f4-hwtimer_arch.c +++ b/stm32f407vgt6/stm32f4-hwtimer_arch.c @@ -43,349 +43,205 @@ and the mailinglist (subscription via web site) * */ +#include "stm32f4xx.h" #include "cpu.h" -//#include "bitarithm.h" +#include "sched.h" #include "hwtimer_cpu.h" #include "hwtimer_arch.h" -//#include "arm_common.h" -//#define VULP(x) ((volatile unsigned long*) (x)) -// +static uint32_t hwtimer_arch_prescale(uint32_t fcpu, uint32_t ftimer); + ///// High level interrupt handler static void (*int_handler)(int); -//Only kept for testing purposes -//void TIM3_IRQHandler(void) { -// TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); -// if (GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_1 )) { -// GPIO_WriteBit(GPIOB, GPIO_Pin_1, RESET); -// puts("i"); -// } else { -// GPIO_WriteBit(GPIOB, GPIO_Pin_1, SET); -// puts("a"); -//// USART3_SendString("Test"); -// } -//} - -#include "sched.h" - - -__attribute__((naked)) -void TIM3_IRQHandler(void) { - save_context(); +void (*TIM_SetCompare[])(TIM_TypeDef *TIMx, uint32_t Compare1) = { + TIM_SetCompare1, + TIM_SetCompare2, + TIM_SetCompare3, + TIM_SetCompare4 +}; + +uint16_t TIM_IT_CC[] = { + TIM_IT_CC1, + TIM_IT_CC2, + TIM_IT_CC3, + TIM_IT_CC4 +}; + +uint16_t TIM_Channel_[] = { + TIM_Channel_1, + TIM_Channel_2, + TIM_Channel_3, + TIM_Channel_4 +}; + +void TIM2_IRQHandler(void) +{ + int i; + + for (i = 0; i < ARCH_MAXTIMERS; i++) { + if (TIM_GetITStatus(TIM2, TIM_IT_CC[i]) != RESET) { + TIM_ClearITPendingBit(TIM2, TIM_IT_CC[i]); + TIM_ITConfig(TIM2, TIM_IT_CC[i], DISABLE); + TIM_CCxCmd(TIM2, TIM_Channel_[i], TIM_CCx_Disable); + + int_handler(i); + } + } + + if (sched_context_switch_request) { + __pendSV(); + } +} - TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); -// TIM_Cmd(TIM3, DISABLE); - if(!(TIM3->CR1 & TIM_CR1_CEN)){ - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, DISABLE); - int_handler(0); - } +static uint32_t hwtimer_arch_prescale(uint32_t fcpu, uint32_t ftimer) +{ + switch (RCC->CFGR & RCC_CFGR_HPRE) { + case RCC_CFGR_HPRE_DIV512: + fcpu >>= 1; - if(sched_context_switch_request) - { - // scheduler - sched_run(); - } + case RCC_CFGR_HPRE_DIV256: + fcpu >>= 1; - restore_context(); -} + case RCC_CFGR_HPRE_DIV128: + fcpu >>= 1; -__attribute__((naked)) -void TIM4_IRQHandler(void) { - save_context(); + case RCC_CFGR_HPRE_DIV64: + fcpu >>= 2; - TIM_ClearITPendingBit(TIM4, TIM_IT_Update ); -// TIM_Cmd(TIM3, DISABLE); - if(!(TIM4->CR1 & TIM_CR1_CEN)){ - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, DISABLE); - int_handler(1); - } + case RCC_CFGR_HPRE_DIV16: + fcpu >>= 1; - if(sched_context_switch_request) - { - // scheduler - sched_run(); - } + case RCC_CFGR_HPRE_DIV8: + fcpu >>= 1; - restore_context(); -} + case RCC_CFGR_HPRE_DIV4: + fcpu >>= 1; -__attribute__((naked)) -void TIM6_DAC_IRQHandler(void) { - save_context(); + case RCC_CFGR_HPRE_DIV2: + fcpu >>= 1; - TIM_ClearITPendingBit(TIM6, TIM_IT_Update ); -// TIM_Cmd(TIM3, DISABLE); - if(!(TIM6->CR1 & TIM_CR1_CEN)){ - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, DISABLE); - int_handler(2); - } + case RCC_CFGR_HPRE_DIV1: + default: + ; + } - if(sched_context_switch_request) - { - // scheduler - sched_run(); - } + switch (RCC->CFGR & RCC_CFGR_PPRE1) { + case RCC_CFGR_PPRE1_DIV16: + fcpu >>= 1; - restore_context(); -} + case RCC_CFGR_PPRE1_DIV8: + fcpu >>= 1; -__attribute__((naked)) -void TIM7_IRQHandler(void) { - save_context(); + case RCC_CFGR_PPRE1_DIV4: + fcpu >>= 1; - TIM_ClearITPendingBit(TIM7, TIM_IT_Update ); -// TIM_Cmd(TIM3, DISABLE); - if(!(TIM7->CR1 & TIM_CR1_CEN)){ - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, DISABLE); - int_handler(3); - } + case RCC_CFGR_PPRE1_DIV2: + fcpu >>= 1; + fcpu <<= 1; /* (APBx presc = 1) ? x1 : x2 */ - if(sched_context_switch_request) - { - // scheduler - sched_run(); - } + case RCC_CFGR_PPRE1_DIV1: + default: + ; + } - restore_context(); + return fcpu / ftimer; } - -// -///// Timer 0-3 interrupt handler -//static void timer_irq(void) __attribute__((interrupt("IRQ"))); -// -//inline unsigned long get_base_address(short timer) { -// return (volatile unsigned long)(TMR0_BASE_ADDR + (timer / 8) * 0x6C000 + (timer/4 - (timer/8)*2) * 0x4000); -//} -// -//static void timer_irq(void) -//{ -// short timer = 0; -// if (T0IR) { -// timer = 0; -// } else if (T1IR) { -// timer = 4; -// } else if (T2IR) { -// timer = 8; -// } -// -// volatile unsigned long base = get_base_address(timer); -// -// if (*VULP(base+TXIR) & BIT0) { -// *VULP(base+TXMCR) &= ~BIT0; -// *VULP(base+TXIR) = BIT0; -// int_handler(timer); -// } -// if (*VULP(base+TXIR) & BIT1) { -// *VULP(base+TXMCR) &= ~BIT3; -// *VULP(base+TXIR) = BIT1; -// int_handler(timer + 1); -// } -// if (*VULP(base+TXIR) & BIT2) { -// *VULP(base+TXMCR) &= ~BIT6; -// *VULP(base+TXIR) = BIT2; -// int_handler(timer + 2); -// } -// if (*VULP(base+TXIR) & BIT3) { -// *VULP(base+TXMCR) &= ~BIT9; -// *VULP(base+TXIR) = BIT3; -// int_handler(timer + 3); -// } -// -// VICVectAddr = 0; // acknowledge interrupt (if using VIC IRQ) -//} - -//This procedure is used for 32-Bit permanent timer -static void timer2_init(uint32_t cpsr) { -// PCONP |= PCTIM0; // power up timer -// T0TCR = 2; // disable and reset timer -// T0MCR = 0; // disable compare -// T0CCR = 0; // capture is disabled -// T0EMR = 0; // no external match output -// T0PR = cpsr; // set prescaler -// install_irq(TIMER0_INT, &timer_irq, 1); -// T0TCR = 1; // reset counter - /* TIM2 clock enable */ - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); - /* Time base configuration */ - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; - //TIM_TimeBaseStructure.TIM_Period = 100 - 1; // 1 MHz down to 10 KHz (0.1 ms) - TIM_TimeBaseStructure.TIM_Prescaler = 840 -1; /*1 msec reso*/ //cpsr; // Down to 1 MHz (adjust per your clock) - TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //not relevant in this case - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseStructure.TIM_Period = 0xFFFFFFFF; - TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; - TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); - TIM_UpdateRequestConfig(TIM2,TIM_UpdateSource_Regular); -// TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); - - /* TIM2 enable counter */ - TIM_Cmd(TIM2, ENABLE); +void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu) +{ + uint32_t cpsr; + + int_handler = handler; + cpsr = hwtimer_arch_prescale(fcpu, HWTIMER_SPEED); + + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); + /* Time base configuration */ + TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + TIM_TimeBaseStructure.TIM_Period = HWTIMER_MAXTICKS; // 1 MHz down to 10 KHz (0.1 ms) + TIM_TimeBaseStructure.TIM_Prescaler = cpsr - 1; /*1 msec reso*/ //cpsr; // Down to 1 MHz (adjust per your clock) + TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //not relevant in this case + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseStructure.TIM_Period = HWTIMER_MAXTICKS; + TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; + TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); + + TIM_OCInitTypeDef TIM_OCInitStruct; + TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_Timing; + TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Disable; + TIM_OCInitStruct.TIM_Pulse = 0; + TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; + TIM_OC1Init(TIM2, &TIM_OCInitStruct); + TIM_OC2Init(TIM2, &TIM_OCInitStruct); + TIM_OC3Init(TIM2, &TIM_OCInitStruct); + TIM_OC4Init(TIM2, &TIM_OCInitStruct); + + NVIC_InitTypeDef NVIC_InitStructure; + NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F; + NVIC_Init(&NVIC_InitStructure); + + TIM_Cmd(TIM2, ENABLE); } -void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu) { - - uint32_t cpsr; - int_handler = handler; - //TODO folgende Iimplementierung fehlerhaft: - cpu_clock_scale(fcpu, HWTIMER_SPEED, &cpsr); - /*only tim2 & tim5 are 32bit */ -// timer0_init(cpsr); -// timer1_init(cpsr); - timer2_init(cpsr); //for hwtimer_now(); - // hardware timer 3 is used in several projects for special purpose - // timer3_init(cpsr); +/*---------------------------------------------------------------------------*/ +void hwtimer_arch_enable_interrupt(void) +{ + NVIC_InitTypeDef NVIC_InitStructure; + // Timer Interrupt konfigurieren + NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F; + NVIC_Init(&NVIC_InitStructure); } /*---------------------------------------------------------------------------*/ -void hwtimer_arch_enable_interrupt(void) { - NVIC_InitTypeDef NVIC_InitStructure; - // Timer Interrupt konfigurieren - NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F; - NVIC_Init(&NVIC_InitStructure); - NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; - NVIC_Init(&NVIC_InitStructure); - NVIC_InitStructure.NVIC_IRQChannel = TIM6_DAC_IRQn; - NVIC_Init(&NVIC_InitStructure); - NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn; - NVIC_Init(&NVIC_InitStructure); -// VICIntEnable = 1 << TIMER0_INT; /* Enable Interrupt */ -// VICIntEnable = 1 << TIMER1_INT; /* Enable Interrupt */ -// VICIntEnable = 1 << TIMER2_INT; /* Enable Interrupt */ +void hwtimer_arch_disable_interrupt(void) +{ + NVIC_InitTypeDef NVIC_InitStructure; + // Timer Interrupt konfigurieren + NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; + NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE; + NVIC_Init(&NVIC_InitStructure); } /*---------------------------------------------------------------------------*/ -void hwtimer_arch_disable_interrupt(void) { - NVIC_InitTypeDef NVIC_InitStructure; - // Timer Interrupt konfigurieren - NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; - NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F; - NVIC_Init(&NVIC_InitStructure); - NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; - NVIC_Init(&NVIC_InitStructure); - NVIC_InitStructure.NVIC_IRQChannel = TIM6_DAC_IRQn; - NVIC_Init(&NVIC_InitStructure); - NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn; - NVIC_Init(&NVIC_InitStructure); -// VICIntEnClr = 1 << TIMER0_INT; /* Disable Interrupt */ -// VICIntEnClr = 1 << TIMER1_INT; /* Disable Interrupt */ -// VICIntEnClr = 1 << TIMER2_INT; /* Disable Interrupt */ +void hwtimer_arch_set(unsigned long offset, short timer) +{ + hwtimer_arch_set_absolute(offset + TIM_GetCounter(TIM2), timer); } /*---------------------------------------------------------------------------*/ -void hwtimer_arch_set(unsigned long offset, short timer) { - offset *= 10; // due to compatibilty input is a count of 10us, so change it to 1us for calculation - /* TIMER clock enable - we have TIM2 to TIM7, because the other make use of APB2 - * TIM2 and TIM5 are 32-Bit */ - switch(timer){ - case 0: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);break; - case 1: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);break; - case 2: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);break; - case 3: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);break; - } - - /* Time base configuration */ - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; - //TIM_TimeBaseStructure.TIM_Period = 100 - 1; // 1 MHz down to 10 KHz (0.1 ms) - TIM_TimeBaseStructure.TIM_Prescaler = offset*84 / 0xFFFF +1; /*1 msec reso*/ //cpsr; // Down to 1 MHz (adjust per your clock) - TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //not relevant in this case - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseStructure.TIM_Period = offset*84/TIM_TimeBaseStructure.TIM_Prescaler;; - TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; - switch(timer){ - case 0: { - TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); - TIM_SelectOnePulseMode(TIM3,TIM_OPMode_Single); - TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); - /* enable counter */ - TIM_Cmd(TIM3, ENABLE); - break; - } - case 1: { - TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); - TIM_SelectOnePulseMode(TIM4,TIM_OPMode_Single); - TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); - /* enable counter */ - TIM_Cmd(TIM4, ENABLE); - break; - } - case 2: { - TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure); - TIM_SelectOnePulseMode(TIM6,TIM_OPMode_Single); - TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE); - /* enable counter */ - TIM_Cmd(TIM6, ENABLE); - break; - } - case 3: { - TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure); - TIM_SelectOnePulseMode(TIM7,TIM_OPMode_Single); - TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE); - /* enable counter */ - TIM_Cmd(TIM7, ENABLE); - break; - } - } - - - // Calculate base address of timer register - // Timer 0-3 are matched to TIMER0 - // Timer 4-7 are matched to TIMER1 - // Timer 8-11 are matched to TIMER2 -/* volatile unsigned long base = get_base_address(timer); - // Calculate match register address of corresponding timer - timer %= 4; - unsigned long cpsr = disableIRQ(); - volatile unsigned long* addr = VULP(base + TXMR0 + 4 * timer); - // Calculate match register value - unsigned long value = *VULP(base + TXTC) + offset; - *addr = value; // set match register - *VULP(base+TXIR) = 0x01 << timer; // reset interrupt register value for corresponding match register - *VULP(base+TXMCR) &= ~(7 << (3 * timer)); // Clear all bits - *VULP(base+TXMCR) |= (MR0I << (3 * timer)); // enable interrupt for match register - restoreIRQ(cpsr);*/ +void hwtimer_arch_set_absolute(unsigned long value, short timer) +{ + TIM_SetCompare[timer](TIM2, value); + TIM_ITConfig(TIM2, TIM_IT_CC[timer], ENABLE); + TIM_CCxCmd(TIM2, TIM_Channel_[timer], TIM_CCx_Enable); } /*---------------------------------------------------------------------------*/ -void hwtimer_arch_unset(short timer) { - switch (timer) { - case 0: { - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, DISABLE); - break; - } - case 1: { - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, DISABLE); - break; - } - case 2: { - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, DISABLE); - break; - } - case 3: { - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, DISABLE); - break; - } - } -/* volatile unsigned long base = get_base_address(timer); - timer %= 4; - *VULP(base+TXMCR) &= ~(MR0I << (3 * timer)); // disable interrupt for match register - *VULP(base+TXIR) = 0x01 << timer; // reset interrupt register value for corresponding match register - *VULP(base+TXIR) */ +void hwtimer_arch_unset(short timer) +{ + TIM_ITConfig(TIM2, TIM_IT_CC[timer], DISABLE); + TIM_CCxCmd(TIM2, TIM_Channel_[timer], TIM_CCx_Disable); } /*---------------------------------------------------------------------------*/ -unsigned long hwtimer_arch_now(void) { - return TIM_GetCounter(TIM2); +/** + * @brief Return hardware timer absolute tick count. + * + * @return Hardware timer absolute tick count. + */ +unsigned long hwtimer_arch_now(void) +{ + return TIM_GetCounter(TIM2); } diff --git a/stm32f407vgt6/stm32f407vgt6-lpm.c b/stm32f407vgt6/stm32f407vgt6-lpm.c index 3d05b8e..108fa22 100644 --- a/stm32f407vgt6/stm32f407vgt6-lpm.c +++ b/stm32f407vgt6/stm32f407vgt6-lpm.c @@ -4,64 +4,237 @@ * Created on: 09.08.2012 * Author: pfeiffer */ +#include "stm32f4xx.h" + #include #include #include "lpm.h" +#include "hwtimer.h" + +/* Comment it to disable RTC automatic calibration */ +#define RTC_AUTO_CALIB -/* lpm is accessed before memory init and initialized separately through code */ -__attribute__((section(".noinit"))) static enum lpm_mode lpm; +static int lpm_enabled; + +static int rtc_synch_prediv = 250; + +#ifdef RTC_AUTO_CALIB +#define RTC_CALIB_THRESHOLD (3000) +#define RTC_CALIB_DURATION_THRESHOLD (200) + +static int lpm_initialized; +static uint32_t rtc_calib_start_time; +static uint32_t rtc_calib_valid_count; +#endif /* RTC_AUTO_CALIB */ + +void RTC_WKUP_IRQHandler(void) +{ + if (RTC_GetITStatus(RTC_IT_WUT) != RESET) { +#ifdef RTC_AUTO_CALIB + + /* + * Sychronize RTC tick with Timer 2 by adjusting Synchronous Prescaler + * until errors are below RTC_CALIB_THRESHOLD three times in succession. + */ + if (!lpm_initialized) { + uint32_t delta; + int error; + int ratio; + + delta = hwtimer_now() - rtc_calib_start_time; + error = delta - 1000000; + ratio = 1000 * 1000000 / delta; + + if (error > RTC_CALIB_THRESHOLD || error < -RTC_CALIB_THRESHOLD) { + int old_rtc_synch_prediv = rtc_synch_prediv; + + /* + * Filter undesired measurement result delayed by other + * interrupt handler + */ + if (ratio - 1000 < RTC_CALIB_DURATION_THRESHOLD && + ratio - 1000 > -RTC_CALIB_DURATION_THRESHOLD) { + rtc_synch_prediv = rtc_synch_prediv * 1000000 / delta; + + if (old_rtc_synch_prediv == rtc_synch_prediv) { + rtc_synch_prediv -= (error > 0 ? 1 : -1); + } + + rtc_calib_valid_count = 0; + } + + /* Reset RTC prescaler and tick */ + RTC_InitTypeDef RTC_InitStruct; + RTC_InitStruct.RTC_AsynchPrediv = 128 - 1; + RTC_InitStruct.RTC_SynchPrediv = rtc_synch_prediv - 1; + RTC_Init(&RTC_InitStruct); + + rtc_calib_start_time = hwtimer_now(); + } + else if (rtc_calib_valid_count < 2) { + if (ratio - 1000 < RTC_CALIB_DURATION_THRESHOLD && + ratio - 1000 > -RTC_CALIB_DURATION_THRESHOLD) { + rtc_calib_valid_count++; + } + } + else { + RTC_WakeUpCmd(DISABLE); + lpm_initialized = 1; + } + } + +#endif /* RTC_AUTO_CALIB */ + + RTC_ClearITPendingBit(RTC_IT_WUT); + EXTI_ClearITPendingBit(EXTI_Line22); + } +} + +void lpm_init(void) +{ + if (!lpm_enabled) { + EXTI_InitTypeDef EXTI_InitStructure; + NVIC_InitTypeDef NVIC_InitStructure; + RTC_InitTypeDef RTC_InitStruct; + + EXTI_ClearITPendingBit(EXTI_Line22); + EXTI_InitStructure.EXTI_Line = EXTI_Line22; + EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; + EXTI_InitStructure.EXTI_LineCmd = ENABLE; + EXTI_Init(&EXTI_InitStructure); + + NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); + PWR_BackupAccessCmd(ENABLE); + + /* Setup RTC clock */ + RCC_LSICmd(ENABLE); + + while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET); + + RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); + RCC_RTCCLKCmd(ENABLE); + RTC_WaitForSynchro(); + + RTC_InitStruct.RTC_AsynchPrediv = 128 - 1; + RTC_InitStruct.RTC_SynchPrediv = rtc_synch_prediv - 1; + RTC_Init(&RTC_InitStruct); + +#ifdef RTC_AUTO_CALIB + rtc_calib_start_time = hwtimer_now(); +#endif /* RTC_AUTO_CALIB */ + + RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits); + RTC_ITConfig(RTC_IT_WUT, ENABLE); + + RTC_WakeUpCmd(DISABLE); + +#ifdef RTC_AUTO_CALIB + RTC_SetWakeUpCounter(0); + RTC_WakeUpCmd(ENABLE); +#endif /* RTC_AUTO_CALIB */ + + lpm_enabled = 1; + } +} + +enum lpm_mode lpm_set(enum lpm_mode target) +{ + enum lpm_mode last_lpm = lpm; + + if (target == LPM_IDLE) { + + } + else if (target == LPM_SLEEP) { +#ifdef RTC_AUTO_CALIB + + if (lpm_initialized) { +#else + + if (lpm_enabled) { +#endif /* RTC_AUTO_CALIB */ + uint32_t nearest_timer = 0; + uint32_t now = hwtimer_now(); + uint32_t tmp; + + /* Find nearest timer */ + if (TIM2->CCER && TIM_Channel_1) { + tmp = TIM2->CCR1 - now; + + if (!nearest_timer || (nearest_timer && tmp < nearest_timer)) { + nearest_timer = tmp; + } + } + + if (TIM2->CCER && TIM_Channel_2) { + tmp = TIM2->CCR2 - now; + + if (!nearest_timer || (nearest_timer && tmp < nearest_timer)) { + nearest_timer = tmp; + } + } + + if (TIM2->CCER && TIM_Channel_3) { + tmp = TIM2->CCR3 - now; + + if (!nearest_timer || (nearest_timer && tmp < nearest_timer)) { + nearest_timer = tmp; + } + } + + if (TIM2->CCER && TIM_Channel_4) { + tmp = TIM2->CCR4 - now; + + if (!nearest_timer || (nearest_timer && tmp < nearest_timer)) { + nearest_timer = tmp; + } + } + + /* Use RTC and deep sleep for long term timer */ + if (nearest_timer > 1000000) { + uint32_t seconds = nearest_timer / 1000000; + + RTC_SetWakeUpCounter(seconds - 1); + + RTC_WakeUpCmd(ENABLE); + + PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI); + + RTC_WakeUpCmd(DISABLE); + + /* Recover system clocks */ + RCC_HSEConfig(RCC_HSE_ON); + + while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); + + RCC_PLLCmd(ENABLE); + + while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); + + RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); + + while (RCC_GetSYSCLKSource() != 0x08); + + TIM2->CNT += seconds * 1000000; + } + } + + __WFI(); + } + + lpm = target; -// FIXME IMPL SLEEP MODES -enum lpm_mode lpm_set(enum lpm_mode target) { -// unsigned target_flags; - enum lpm_mode last_lpm = lpm; - - if( target == LPM_IDLE ) - { - - } - /* calculate target mcu power mode */ - -// if( target == LPM_IDLE ) -// target_flags = PM_IDLE; -// else if( target == LPM_SLEEP ) -// target_flags = PM_SLEEP; -// else if( target == LPM_POWERDOWN ) -// target_flags = PM_POWERDOWN; -// else -// target_flags = 0; -// -// -// if(target > LPM_IDLE){ -// // Disconnect PLL -// -// PLLCON &= ~0x0002; -// PLLFEED = 0xAA; -// PLLFEED = 0x55; -// while (PLLSTAT & BIT25); -// // Disabling PLL not mandatory, is done by hardware -// } - - lpm = target; - -// PCON |= target_flags; // set target power mode - return last_lpm; + return last_lpm; } -void lpm_awake(void) { -#if LPM_DEBUG - unsigned long usec = RTC_CTC; -#endif -// if( (lpm >= LPM_SLEEP) | ( ~PLLSTAT & (BIT24 | BIT25 | BIT25) )) { // wake up from deep sleep & detect loss of PLL connection -// //benchmark -// init_clks1(); -// init_clks2(); -// // Debug tests -//#if LPM_DEBUG -// usec = RTC_CTC-usec; -// printf("Wakeup in %lu usecs\n",usec * 31); -//#endif -// } - lpm = LPM_ON; +void lpm_awake(void) +{ + lpm = LPM_ON; } diff --git a/stm32f407vgt6/syscalls.c b/stm32f407vgt6/syscalls.c index 8981109..9b02916 100644 --- a/stm32f407vgt6/syscalls.c +++ b/stm32f407vgt6/syscalls.c @@ -45,6 +45,7 @@ and the mailinglist (subscription via web site) #include // core #include "kernel.h" +#include "irq.h" // sys #include "lpm.h" //#include "tracelog.h" @@ -88,42 +89,42 @@ extern uintptr_t __heap3_max; ///< maximum for end of heap memory space /// current position in heap -static caddr_t heap[NUM_HEAPS] = {(caddr_t)&__heap1_start};//,(caddr_t)&__heap3_start,(caddr_t)&__heap2_start}; // add heap3 before heap2 cause Heap3 address is lower then addr of heap2 +static caddr_t heap[NUM_HEAPS] = {(caddr_t) &__heap1_start}; //,(caddr_t)&__heap3_start,(caddr_t)&__heap2_start}; // add heap3 before heap2 cause Heap3 address is lower then addr of heap2 /// maximum position in heap -static const caddr_t heap_max[NUM_HEAPS] = {(caddr_t)&__heap1_max};//,(caddr_t)&__heap3_max,(caddr_t)&__heap2_max}; +static const caddr_t heap_max[NUM_HEAPS] = {(caddr_t) &__heap1_max}; //,(caddr_t)&__heap3_max,(caddr_t)&__heap2_max}; // start position in heap -static const caddr_t heap_start[NUM_HEAPS] = {(caddr_t)&__heap1_start};//,(caddr_t)&__heap3_start,(caddr_t)&__heap2_start}; +static const caddr_t heap_start[NUM_HEAPS] = {(caddr_t) &__heap1_start}; //,(caddr_t)&__heap3_start,(caddr_t)&__heap2_start}; // current heap in use volatile static uint8_t iUsedHeap = 0; /** @} */ /*-----------------------------------------------------------------------------------*/ -void heap_stats(void) { - for(int i = 0; i < NUM_HEAPS; i++) - printf("# heap %i: %p -- %p -> %p (%li of %li free)\n", i, heap_start[i], heap[i], heap_max[i], - (uint32_t)heap_max[i] - (uint32_t)heap[i], (uint32_t)heap_max[i] - (uint32_t)heap_start[i]); +void heap_stats(void) +{ + for (int i = 0; i < NUM_HEAPS; i++) + printf("# heap %i: %p -- %p -> %p (%li of %li free)\n", i, heap_start[i], heap[i], heap_max[i], + (uint32_t)heap_max[i] - (uint32_t)heap[i], (uint32_t)heap_max[i] - (uint32_t)heap_start[i]); } /*-----------------------------------------------------------------------------------*/ void __assert_func(const char *file, int line, const char *func, const char *failedexpr) { #if SYSLOG_CONF_ASSERT - trace_number(TRACELOG_EV_ASSERTION, line); - syslog(SL_EMERGENCY, "assert", "%s() in %s:%u\n", func, file, line); + trace_number(TRACELOG_EV_ASSERTION, line); + syslog(SL_EMERGENCY, "assert", "%s() in %s:%u\n", func, file, line); #endif - printf("#! assertion %s failed\n\t%s() in %s:%u\n", failedexpr, func, file, line ); - _exit(3); + printf("#! assertion %s failed\n\t%s() in %s:%u\n", failedexpr, func, file, line); + _exit(3); } /*-----------------------------------------------------------------------------------*/ void __assert(const char *file, int line, const char *failedexpr) { - __assert_func(file, line, "?", failedexpr); + __assert_func(file, line, "?", failedexpr); } /*-----------------------------------------------------------------------------------*/ caddr_t _sbrk_r(struct _reent *r, size_t incr) { - if(incr < 0) - { + if (incr < 0) { puts("[syscalls] Negative Values for _sbrk_r are not supported"); r->_errno = ENOMEM; return NULL; @@ -132,201 +133,230 @@ caddr_t _sbrk_r(struct _reent *r, size_t incr) uint32_t cpsr = disableIRQ(); /* check all heaps for a chunk of the requested size */ - for( ; iUsedHeap < NUM_HEAPS; iUsedHeap++ ) { - caddr_t new_heap = heap[iUsedHeap] + incr; - - #ifdef MODULE_TRACELOG - trace_pointer(TRACELOG_EV_MEMORY, heap[iUsedHeap]); - #endif - if( new_heap <= heap_max[iUsedHeap] ) { - caddr_t prev_heap = heap[iUsedHeap]; - #ifdef MODULE_TRACELOG - trace_pointer(TRACELOG_EV_MEMORY, new_heap); - #endif - heap[iUsedHeap] = new_heap; - - r->_errno = 0; - restoreIRQ(cpsr); - return prev_heap; - } - } - restoreIRQ(cpsr); - #ifdef MODULE_TRACELOG - trace_string(TRACELOG_EV_MEMORY, "heap!"); // heap full - #endif - - r->_errno = ENOMEM; - return NULL; + for (; iUsedHeap < NUM_HEAPS; iUsedHeap++) { + caddr_t new_heap = heap[iUsedHeap] + incr; + +#ifdef MODULE_TRACELOG + trace_pointer(TRACELOG_EV_MEMORY, heap[iUsedHeap]); +#endif + + if (new_heap <= heap_max[iUsedHeap]) { + caddr_t prev_heap = heap[iUsedHeap]; +#ifdef MODULE_TRACELOG + trace_pointer(TRACELOG_EV_MEMORY, new_heap); +#endif + heap[iUsedHeap] = new_heap; + + r->_errno = 0; + restoreIRQ(cpsr); + return prev_heap; + } + } + + restoreIRQ(cpsr); +#ifdef MODULE_TRACELOG + trace_string(TRACELOG_EV_MEMORY, "heap!"); // heap full +#endif + + r->_errno = ENOMEM; + return NULL; } /*---------------------------------------------------------------------------*/ int _isatty_r(struct _reent *r, int fd) { - r->_errno = 0; - if( fd == STDOUT_FILENO || fd == STDERR_FILENO ) - return 1; - else - return 0; + r->_errno = 0; + + if (fd == STDOUT_FILENO || fd == STDERR_FILENO) { + return 1; + } + else { + return 0; + } } /*---------------------------------------------------------------------------*/ _off_t _lseek_r(struct _reent *r, int fd, _off_t pos, int whence) { - _off_t result = -1; - PRINTF("lseek [%i] pos %li whence %i\n", fd, pos, whence); + _off_t result = -1; + PRINTF("lseek [%i] pos %li whence %i\n", fd, pos, whence); - r->_errno = ENODEV; + r->_errno = ENODEV; #ifdef MODULE_FAT result = ff_lseek_r(r, fd, pos, whence); #endif - PRINTF("lseek returned %li (0 is success)\n", result); - return result; + PRINTF("lseek returned %li (0 is success)\n", result); + return result; } /*---------------------------------------------------------------------------*/ int _open_r(struct _reent *r, const char *name, int mode) { - int ret = -1; - PRINTF("open '%s' mode %#x\n", name, mode); + int ret = -1; + PRINTF("open '%s' mode %#x\n", name, mode); - r->_errno = ENODEV; // no such device + r->_errno = ENODEV; // no such device #ifdef MODULE_FAT - ret = ff_open_r(r,name,mode); + ret = ff_open_r(r, name, mode); #endif - PRINTF("open [%i] errno %i\n", ret, r->_errno); - return ret; + PRINTF("open [%i] errno %i\n", ret, r->_errno); + return ret; } /*---------------------------------------------------------------------------*/ int _stat_r(struct _reent *r, char *name, struct stat *st) { - int ret = -1; - PRINTF("_stat_r '%s' \n", name); - r->_errno = ENODEV; // no such device + int ret = -1; + PRINTF("_stat_r '%s' \n", name); + r->_errno = ENODEV; // no such device #ifdef MODULE_FAT - ret = ff_stat_r(r,name,st); + ret = ff_stat_r(r, name, st); #endif - PRINTF("_stat_r [%i] errno %i\n", ret, r->_errno); - return ret; + PRINTF("_stat_r [%i] errno %i\n", ret, r->_errno); + return ret; } /*---------------------------------------------------------------------------*/ -int _fstat_r(struct _reent *r, int fd, struct stat * st) +int _fstat_r(struct _reent *r, int fd, struct stat *st) { - int ret = -1; + int ret = -1; + + r->_errno = 0; + memset(st, 0, sizeof(*st)); - r->_errno = 0; - memset(st, 0, sizeof(*st)); - if( fd == STDOUT_FILENO || fd == STDERR_FILENO ) { - st->st_mode = S_IFCHR; - ret = 0; - } else { + if (fd == STDOUT_FILENO || fd == STDERR_FILENO) { + st->st_mode = S_IFCHR; + ret = 0; + } + else { #ifdef MODULE_FAT - PRINTF("_fstat_r '%i' \n", fd); + PRINTF("_fstat_r '%i' \n", fd); - ret = ff_fstat_r(r,fd,st); - PRINTF("_fstat_r [%i] errno %i\n", ret, r->_errno); + ret = ff_fstat_r(r, fd, st); + PRINTF("_fstat_r [%i] errno %i\n", ret, r->_errno); #else - r->_errno = ENODEV; + r->_errno = ENODEV; #endif - } - return ret; + } + + return ret; } /*---------------------------------------------------------------------------*/ int _write_r(struct _reent *r, int fd, const void *data, unsigned int count) { - int result = EOF; - r->_errno = EBADF; - - switch(fd) { - case STDOUT_FILENO: - case STDERR_FILENO: - { - #if FEUERWARE_CONF_ENABLE_HAL - if( stdio != NULL ) - result = chardevice_write(stdio, (char*)data, count); - else if( hal_state == HAL_NOT_INITIALIZED ) - result = fw_puts((char*)data, count); - #else - //FIXME impl fw_puts - - - char* chars = (char*) data; - for(int i = 0;i < count;i++) { - USART_SendData(USART2, chars[i]); - - /* Loop until the end of transmission */ - while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET){} - } - - return count; - //result = fw_puts((char*)data, count); - #endif - } - break; - - default: - #ifdef MODULE_FAT - result = ff_write_r(r, fd, data, count); - #endif - break; - } - - return result; + int result = EOF; + r->_errno = EBADF; + + switch (fd) { + case STDOUT_FILENO: + case STDERR_FILENO: { +#if FEUERWARE_CONF_ENABLE_HAL + + if (stdio != NULL) { + result = chardevice_write(stdio, (char *)data, count); + } + else if (hal_state == HAL_NOT_INITIALIZED) { + result = fw_puts((char *)data, count); + } + +#else + //FIXME impl fw_puts + + + char *chars = (char *) data; + + for (int i = 0; i < count; i++) { + USART_SendData(USART2, chars[i]); + + /* Loop until the end of transmission */ + while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET) {} + } + + return count; + //result = fw_puts((char*)data, count); +#endif + } + break; + + default: +#ifdef MODULE_FAT + result = ff_write_r(r, fd, data, count); +#endif + break; + } + + return result; } /*---------------------------------------------------------------------------*/ int _read_r(struct _reent *r, int fd, void *buffer, unsigned int count) { - int result = -1; - r->_errno = EBADF; + int result = -1; + r->_errno = EBADF; + + switch (fd) { + case STDIN_FILENO: { + /* Loop until ready to read */ + while (USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET) {} + + ((char *)buffer)[0] = USART_ReceiveData(USART2); + + return 1; + } + break; + + default: #ifdef MODULE_FAT - result = ff_read_r(r, fd, buffer, count); + result = ff_read_r(r, fd, buffer, count); #endif - return result; + break; + } + + return result; } /*---------------------------------------------------------------------------*/ int _close_r(struct _reent *r, int fd) { - int ret = -1; - r->_errno = EBADF; - #ifdef MODULE_FAT - ret = ff_close_r(r, fd); - #endif - return ret; + int ret = -1; + r->_errno = EBADF; +#ifdef MODULE_FAT + ret = ff_close_r(r, fd); +#endif + return ret; } /*---------------------------------------------------------------------------*/ -int _unlink_r(struct _reent *r, char* path) +int _unlink_r(struct _reent *r, char *path) { - int ret = -1; - r->_errno = ENODEV; + int ret = -1; + r->_errno = ENODEV; #ifdef MODULE_FAT - ret = ff_unlink_r(r, path); + ret = ff_unlink_r(r, path); #endif - return ret; + return ret; } /*---------------------------------------------------------------------------*/ void _exit(int n) { #ifdef MODULE_TRACELOG - trace_number(TRACELOG_EV_EXIT, n); + trace_number(TRACELOG_EV_EXIT, n); #endif - printf("#! exit %i: resetting\n", n); + printf("#! exit %i: resetting\n", n); + + //FIXME write out all peripherie buffers stdout flush + NVIC_SystemReset(); - //FIXME write out all peripherie buffers stdout flush - NVIC_SystemReset(); - while(1); + while (1); } /*---------------------------------------------------------------------------*/ int _getpid(void) { - return active_thread->pid; + return active_thread->pid; } /*---------------------------------------------------------------------------*/ int _kill_r(struct _reent *r, int pid, int sig) { - /* not implemented */ - r->_errno = ESRCH; // no such process - return -1; + /* not implemented */ + r->_errno = ESRCH; // no such process + return -1; } /*---------------------------------------------------------------------------*/ -void _init(void){} -void _fini(void){} +void _init(void) {} +void _fini(void) {}