MCU specific sleep feature is now defined in MCU specific file.
This commit is contained in:
10
ChangeLog
10
ChangeLog
@@ -1,5 +1,15 @@
|
|||||||
2017-11-17 NIIBE Yutaka <gniibe@fsij.org>
|
2017-11-17 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* rules.mk (CSRC): Add mcu/chx-$(CHIP).c.
|
||||||
|
|
||||||
|
* chopstx-cortex-m.c (idle, chx_sleep_mode): Remove.
|
||||||
|
(chx_sched, preempt): Call chx_idle.
|
||||||
|
* mcu/chx-mkl27z.c, mcu/chx-stm32f0.c, mcu/chx-stm32f103.c: New.
|
||||||
|
* mcu/stm32.h: New.
|
||||||
|
|
||||||
|
* chopstx-gnu-linux.c (chx_sleep_mode): Move to...
|
||||||
|
* mcu/chx-gnu-linux.c: Here.
|
||||||
|
|
||||||
* mcu/stm32f103.h (DBGMCU): New.
|
* mcu/stm32f103.h (DBGMCU): New.
|
||||||
|
|
||||||
* mcu/cortex-m.h: New.
|
* mcu/cortex-m.h: New.
|
||||||
|
|||||||
@@ -229,24 +229,6 @@ chx_cpu_sched_unlock (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void __attribute__((naked, used))
|
|
||||||
idle (void)
|
|
||||||
{
|
|
||||||
int sleep_enabled;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
asm ("ldr %0, %1" : "=r" (sleep_enabled): "m" (chx_allow_sleep));
|
|
||||||
if (!sleep_enabled)
|
|
||||||
continue;
|
|
||||||
if ((sleep_enabled & 0x80))
|
|
||||||
asm volatile ("wfe" : : : "memory");
|
|
||||||
else
|
|
||||||
asm volatile ("wfi" : : : "memory");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
chx_handle_intr (void)
|
chx_handle_intr (void)
|
||||||
{
|
{
|
||||||
@@ -388,7 +370,7 @@ chx_sched (uint32_t yield)
|
|||||||
/* Spawn an IDLE thread. */
|
/* Spawn an IDLE thread. */
|
||||||
"ldr r1, =__main_stack_end__\n\t"
|
"ldr r1, =__main_stack_end__\n\t"
|
||||||
"mov sp, r1\n\t"
|
"mov sp, r1\n\t"
|
||||||
"ldr r0, =idle\n\t" /* PC = idle */
|
"ldr r0, =chx_idle\n\t" /* PC = idle */
|
||||||
/**/
|
/**/
|
||||||
/* Unmask interrupts. */
|
/* Unmask interrupts. */
|
||||||
"cpsie i\n\t"
|
"cpsie i\n\t"
|
||||||
@@ -637,7 +619,7 @@ preempt (void)
|
|||||||
"mov r3, #0\n\t"
|
"mov r3, #0\n\t"
|
||||||
"stm r0!, {r1, r2, r3}\n\t"
|
"stm r0!, {r1, r2, r3}\n\t"
|
||||||
"stm r0!, {r1, r2, r3}\n\t"
|
"stm r0!, {r1, r2, r3}\n\t"
|
||||||
"ldr r1, =idle\n\t" /* PC = idle */
|
"ldr r1, =chx_idle\n\t" /* PC = idle */
|
||||||
"mov r2, #0x010\n\t"
|
"mov r2, #0x010\n\t"
|
||||||
"lsl r2, r2, #20\n\t" /* xPSR = T-flag set (Thumb) */
|
"lsl r2, r2, #20\n\t" /* xPSR = T-flag set (Thumb) */
|
||||||
"stm r0!, {r1, r2}\n\t"
|
"stm r0!, {r1, r2}\n\t"
|
||||||
@@ -708,97 +690,3 @@ svc (void)
|
|||||||
: /* no output */ : "r" (tp) : "memory");
|
: /* no output */ : "r" (tp) : "memory");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MCU_STM32F0
|
|
||||||
struct SCB
|
|
||||||
{
|
|
||||||
volatile uint32_t CPUID;
|
|
||||||
volatile uint32_t ICSR;
|
|
||||||
volatile uint32_t VTOR;
|
|
||||||
volatile uint32_t AIRCR;
|
|
||||||
volatile uint32_t SCR;
|
|
||||||
volatile uint32_t CCR;
|
|
||||||
volatile uint8_t SHP[12];
|
|
||||||
volatile uint32_t SHCSR;
|
|
||||||
volatile uint32_t CFSR;
|
|
||||||
volatile uint32_t HFSR;
|
|
||||||
volatile uint32_t DFSR;
|
|
||||||
volatile uint32_t MMFAR;
|
|
||||||
volatile uint32_t BFAR;
|
|
||||||
volatile uint32_t AFSR;
|
|
||||||
volatile uint32_t PFR[2];
|
|
||||||
volatile uint32_t DFR;
|
|
||||||
volatile uint32_t ADR;
|
|
||||||
volatile uint32_t MMFR[4];
|
|
||||||
volatile uint32_t ISAR[5];
|
|
||||||
/* Cortex-M3 has more... */
|
|
||||||
};
|
|
||||||
static struct SCB *const SCB = ((struct SCB *)0xE000ED00);
|
|
||||||
#define SCB_SCR_SLEEPDEEP (1 << 2)
|
|
||||||
|
|
||||||
struct PWR
|
|
||||||
{
|
|
||||||
volatile uint32_t CR;
|
|
||||||
volatile uint32_t CSR;
|
|
||||||
};
|
|
||||||
static struct PWR *const PWR = ((struct PWR *)0x40007000);
|
|
||||||
#define PWR_CR_LPDS 0x0001 /* Low-power deepsleep */
|
|
||||||
#define PWR_CR_PDDS 0x0002 /* Power down deepsleep */
|
|
||||||
#define PWR_CR_CWUF 0x0004 /* Clear wakeup flag */
|
|
||||||
|
|
||||||
void
|
|
||||||
chx_sleep_mode (int how)
|
|
||||||
{
|
|
||||||
PWR->CR |= PWR_CR_CWUF;
|
|
||||||
PWR->CR &= ~(PWR_CR_PDDS|PWR_CR_LPDS);
|
|
||||||
|
|
||||||
if (how == 0 || how == 1 /* Sleep only (not deepsleep) */)
|
|
||||||
SCB->SCR &= ~SCB_SCR_SLEEPDEEP;
|
|
||||||
else
|
|
||||||
{ /* Deepsleep */
|
|
||||||
/* how == 2: deepsleep but regulator ON */
|
|
||||||
if (how == 3)
|
|
||||||
PWR->CR |= PWR_CR_LPDS; /* regulator low-power mode */
|
|
||||||
else if (how == 4)
|
|
||||||
PWR->CR |= PWR_CR_PDDS; /* Power down: All OFF */
|
|
||||||
|
|
||||||
SCB->SCR |= SCB_SCR_SLEEPDEEP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
struct RCC {
|
|
||||||
volatile uint32_t CR;
|
|
||||||
volatile uint32_t CFGR;
|
|
||||||
/* And more... */
|
|
||||||
};
|
|
||||||
static struct RCC *const RCC = (struct RCC *)0x40021000;
|
|
||||||
#define STM32_SW_PLL (2 << 0)
|
|
||||||
#define RCC_CFGR_SWS 0x0000000C
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Deepsleep is only useful with RTC, Watch Dog, or WKUP pin.
|
|
||||||
* So, we can't use deepsleep.
|
|
||||||
*
|
|
||||||
* On sleep mode, clock is HSI, while it's PLL when running.
|
|
||||||
* This can achieve lower power consumption on sleep.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
chx_sleep_mode (int how)
|
|
||||||
{
|
|
||||||
uint32_t cfg_sw;
|
|
||||||
|
|
||||||
if (how == 0)
|
|
||||||
{
|
|
||||||
RCC->CFGR |= STM32_SW_PLL;
|
|
||||||
cfg_sw = STM32_SW_PLL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RCC->CFGR &= ~3;
|
|
||||||
cfg_sw = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((RCC->CFGR & RCC_CFGR_SWS) != (cfg_sw << 2))
|
|
||||||
;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -342,9 +342,3 @@ chopstx_create_arch (uintptr_t stack_addr, size_t stack_size,
|
|||||||
chx_cpu_sched_unlock ();
|
chx_cpu_sched_unlock ();
|
||||||
return tp;
|
return tp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
chx_sleep_mode (int enable_sleep)
|
|
||||||
{
|
|
||||||
(void)enable_sleep;
|
|
||||||
}
|
|
||||||
|
|||||||
5
mcu/chx-gnu-linux.c
Normal file
5
mcu/chx-gnu-linux.c
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
void
|
||||||
|
chx_sleep_mode (int enable_sleep)
|
||||||
|
{
|
||||||
|
(void)enable_sleep;
|
||||||
|
}
|
||||||
23
mcu/chx-mkl27z.c
Normal file
23
mcu/chx-mkl27z.c
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
extern int chx_allow_sleep;
|
||||||
|
|
||||||
|
void
|
||||||
|
chx_sleep_mode (int enable_sleep)
|
||||||
|
{
|
||||||
|
(void)enable_sleep;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__((naked))
|
||||||
|
chx_idle (void)
|
||||||
|
{
|
||||||
|
int sleep_enabled;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
asm ("ldr %0, %1" : "=r" (sleep_enabled): "m" (chx_allow_sleep));
|
||||||
|
if (sleep_enabled)
|
||||||
|
{
|
||||||
|
asm volatile ("wfi" : : : "memory");
|
||||||
|
/* NOTE: it never comes here. Don't add lines after this. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
mcu/chx-stm32f0.c
Normal file
41
mcu/chx-stm32f0.c
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <mcu/cortex-m.h>
|
||||||
|
#include <mcu/stm32.h>
|
||||||
|
|
||||||
|
extern int chx_allow_sleep;
|
||||||
|
|
||||||
|
void
|
||||||
|
chx_sleep_mode (int how)
|
||||||
|
{
|
||||||
|
PWR->CR |= PWR_CR_CWUF;
|
||||||
|
PWR->CR &= ~(PWR_CR_PDDS|PWR_CR_LPDS);
|
||||||
|
|
||||||
|
if (how == 0 || how == 1 /* Sleep only (not deepsleep) */)
|
||||||
|
SCB->SCR &= ~SCB_SCR_SLEEPDEEP;
|
||||||
|
else
|
||||||
|
{ /* Deepsleep */
|
||||||
|
/* how == 2: deepsleep but regulator ON */
|
||||||
|
if (how == 3)
|
||||||
|
PWR->CR |= PWR_CR_LPDS; /* regulator low-power mode */
|
||||||
|
else if (how == 4)
|
||||||
|
PWR->CR |= PWR_CR_PDDS; /* Power down: All OFF */
|
||||||
|
|
||||||
|
SCB->SCR |= SCB_SCR_SLEEPDEEP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__((naked))
|
||||||
|
chx_idle (void)
|
||||||
|
{
|
||||||
|
int sleep_enabled;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
asm ("ldr %0, %1" : "=r" (sleep_enabled): "m" (chx_allow_sleep));
|
||||||
|
if (sleep_enabled)
|
||||||
|
{
|
||||||
|
asm volatile ("wfi" : : : "memory");
|
||||||
|
/* NOTE: it never comes here. Don't add lines after this. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
60
mcu/chx-stm32f103.c
Normal file
60
mcu/chx-stm32f103.c
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <mcu/stm32f103.h>
|
||||||
|
|
||||||
|
extern int chx_allow_sleep;
|
||||||
|
|
||||||
|
static void
|
||||||
|
configure_clock (uint32_t cfg_sw)
|
||||||
|
{
|
||||||
|
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW_MASK) | cfg_sw;
|
||||||
|
while ((RCC->CFGR & RCC_CFGR_SWS) != (cfg_sw << 2))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When HOW=0 or HOW=1, clock is PLL (72MHz).
|
||||||
|
* When HOW=2, clock will be HSI (8MHz) on sleep.
|
||||||
|
*
|
||||||
|
* With HSI clock, it can achieve lower power consumption.
|
||||||
|
*
|
||||||
|
* Implementation note: Deepsleep is only useful with RTC, Watch Dog,
|
||||||
|
* or WKUP pin. We can't use deepsleep for USB, it never wakes up.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
chx_sleep_mode (int how)
|
||||||
|
{
|
||||||
|
if (how == 0 || how == 1)
|
||||||
|
configure_clock (RCC_CFGR_SW_PLL);
|
||||||
|
|
||||||
|
/* how == 2: Defer setting to 8MHz clock to the idle function */
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__((naked))
|
||||||
|
chx_idle (void)
|
||||||
|
{
|
||||||
|
int sleep_enabled;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
asm ("ldr %0, %1" : "=r" (sleep_enabled): "m" (chx_allow_sleep));
|
||||||
|
if (sleep_enabled)
|
||||||
|
{
|
||||||
|
asm volatile ("cpsid i" : : : "memory");
|
||||||
|
if (sleep_enabled == 1)
|
||||||
|
{
|
||||||
|
/* Allow JTAG/SWD access on sleep. */
|
||||||
|
DBGMCU->CR |= DBG_SLEEP;
|
||||||
|
}
|
||||||
|
else if (sleep_enabled == 2)
|
||||||
|
{
|
||||||
|
DBGMCU->CR &= ~DBG_SLEEP; /* Disable HCLK on sleep */
|
||||||
|
configure_clock (RCC_CFGR_SW_HCI);
|
||||||
|
}
|
||||||
|
asm volatile ("cpsie i" : : : "memory");
|
||||||
|
|
||||||
|
asm volatile ("wfi" : : : "memory");
|
||||||
|
/* NOTE: it never comes here. Don't add lines after this. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
mcu/stm32.h
Normal file
9
mcu/stm32.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
struct PWR
|
||||||
|
{
|
||||||
|
volatile uint32_t CR;
|
||||||
|
volatile uint32_t CSR;
|
||||||
|
};
|
||||||
|
static struct PWR *const PWR = ((struct PWR *)0x40007000);
|
||||||
|
#define PWR_CR_LPDS 0x0001 /* Low-power deepsleep */
|
||||||
|
#define PWR_CR_PDDS 0x0002 /* Power down deepsleep */
|
||||||
|
#define PWR_CR_CWUF 0x0004 /* Clear wakeup flag */
|
||||||
6
rules.mk
6
rules.mk
@@ -6,6 +6,12 @@ ifneq ($(USE_EVENTFLAG),)
|
|||||||
CSRC += $(CHOPSTX)/eventflag.c
|
CSRC += $(CHOPSTX)/eventflag.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(EMULATION),)
|
||||||
|
CSRC += $(CHOPSTX)/mcu/chx-$(CHIP).c
|
||||||
|
else
|
||||||
|
CSRC += $(CHOPSTX)/mcu/chx-gnu-linux.c
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq ($(USE_SYS),)
|
ifneq ($(USE_SYS),)
|
||||||
CSRC += $(CHOPSTX)/mcu/sys-$(CHIP).c
|
CSRC += $(CHOPSTX)/mcu/sys-$(CHIP).c
|
||||||
endif
|
endif
|
||||||
|
|||||||
Reference in New Issue
Block a user