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>
|
||||
|
||||
* 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/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
|
||||
chx_handle_intr (void)
|
||||
{
|
||||
@@ -388,7 +370,7 @@ chx_sched (uint32_t yield)
|
||||
/* Spawn an IDLE thread. */
|
||||
"ldr r1, =__main_stack_end__\n\t"
|
||||
"mov sp, r1\n\t"
|
||||
"ldr r0, =idle\n\t" /* PC = idle */
|
||||
"ldr r0, =chx_idle\n\t" /* PC = idle */
|
||||
/**/
|
||||
/* Unmask interrupts. */
|
||||
"cpsie i\n\t"
|
||||
@@ -637,7 +619,7 @@ preempt (void)
|
||||
"mov r3, #0\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"
|
||||
"lsl r2, r2, #20\n\t" /* xPSR = T-flag set (Thumb) */
|
||||
"stm r0!, {r1, r2}\n\t"
|
||||
@@ -708,97 +690,3 @@ svc (void)
|
||||
: /* no output */ : "r" (tp) : "memory");
|
||||
}
|
||||
#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 ();
|
||||
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 */
|
||||
Reference in New Issue
Block a user