mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #16212 from nandojve/xmega_pm
cpu/atxmega: Add periph power management
This commit is contained in:
commit
ac774f3404
@ -36,6 +36,7 @@ extern "C" {
|
||||
static const timer_conf_t timer_config[] = {
|
||||
{
|
||||
.dev = (void *)&TCC1,
|
||||
.pwr = PWR_RED_REG(PWR_PORT_C, PR_TC1_bm),
|
||||
.type = TC_TYPE_1,
|
||||
.int_lvl = { CPU_INT_LVL_LOW,
|
||||
CPU_INT_LVL_OFF,
|
||||
@ -44,6 +45,7 @@ static const timer_conf_t timer_config[] = {
|
||||
},
|
||||
{
|
||||
.dev = (void *)&TCC0,
|
||||
.pwr = PWR_RED_REG(PWR_PORT_C, PR_TC0_bm),
|
||||
.type = TC_TYPE_0,
|
||||
.int_lvl = { CPU_INT_LVL_LOW,
|
||||
CPU_INT_LVL_LOW,
|
||||
@ -69,6 +71,7 @@ static const timer_conf_t timer_config[] = {
|
||||
static const uart_conf_t uart_config[] = {
|
||||
{ /* CDC-ACM */
|
||||
.dev = &USARTE0,
|
||||
.pwr = PWR_RED_REG(PWR_PORT_E, PR_USART0_bm),
|
||||
.rx_pin = GPIO_PIN(PORT_E, 2),
|
||||
.tx_pin = GPIO_PIN(PORT_E, 3),
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "cpu.h"
|
||||
#include "cpu_clock.h"
|
||||
#include "cpu_pm.h"
|
||||
#include "panic.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
@ -63,18 +64,7 @@ void avr8_reset_cause(void)
|
||||
|
||||
void __attribute__((weak)) avr8_clk_init(void)
|
||||
{
|
||||
volatile uint8_t *reg = (uint8_t *)&PR.PRGEN;
|
||||
uint8_t i;
|
||||
|
||||
/* Turn off all peripheral clocks that can be turned off. */
|
||||
for (i = 0; i <= 7; i++) {
|
||||
reg[i] = 0xff;
|
||||
}
|
||||
|
||||
/* Turn on all peripheral clocks that can be turned on. */
|
||||
for (i = 0; i <= 7; i++) {
|
||||
reg[i] = 0x00;
|
||||
}
|
||||
pm_periph_power_off();
|
||||
|
||||
/* XMEGA A3U [DATASHEET] p.23 After reset, the device starts up running
|
||||
* from the 2MHz internal oscillator. The other clock sources, DFLLs
|
||||
|
41
cpu/atxmega/include/cpu_pm.h
Normal file
41
cpu/atxmega/include/cpu_pm.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_atxmega
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Power Management and Power Reduction API
|
||||
*
|
||||
* This help to save power disabling all non used peripherals. It can help to
|
||||
* save power when in active or sleep modes. For any other low power modes
|
||||
* xmega will freeze all peripherals clock.
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*/
|
||||
|
||||
#include "periph_cpu.h"
|
||||
|
||||
#ifndef CPU_PM_H
|
||||
#define CPU_PM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void pm_periph_enable(pwr_reduction_t pwr);
|
||||
void pm_periph_disable(pwr_reduction_t pwr);
|
||||
void pm_periph_power_off(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CPU_PM_H */
|
||||
/** @} */
|
@ -68,6 +68,29 @@ enum {
|
||||
PORT_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Power Reduction Peripheral Mask
|
||||
*/
|
||||
typedef uint16_t pwr_reduction_t;
|
||||
|
||||
/**
|
||||
* @brief Define a CPU specific Power Reduction index macro
|
||||
*/
|
||||
#define PWR_RED_REG(reg, dev) ((reg << 8) | dev)
|
||||
|
||||
/**
|
||||
* @brief Define a CPU specific Power Reduction index macro
|
||||
*/
|
||||
enum {
|
||||
PWR_GENERAL_POWER,
|
||||
PWR_PORT_A,
|
||||
PWR_PORT_B,
|
||||
PWR_PORT_C,
|
||||
PWR_PORT_D,
|
||||
PWR_PORT_E,
|
||||
PWR_PORT_F,
|
||||
};
|
||||
|
||||
/**
|
||||
* @name Power management configuration
|
||||
* @{
|
||||
@ -190,6 +213,7 @@ typedef enum {
|
||||
*/
|
||||
typedef struct {
|
||||
USART_t *dev; /**< pointer to the used UART device */
|
||||
pwr_reduction_t pwr; /**< Power Management */
|
||||
gpio_t rx_pin; /**< pin used for RX */
|
||||
gpio_t tx_pin; /**< pin used for TX */
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
@ -235,6 +259,7 @@ typedef enum {
|
||||
*/
|
||||
typedef struct {
|
||||
TC0_t *dev; /**< Pointer to the used as Timer device */
|
||||
pwr_reduction_t pwr; /**< Power Management */
|
||||
timer_type_t type; /**< Timer Type */
|
||||
cpu_int_lvl_t int_lvl[TIMER_CH_MAX_NUMOF]; /**< Interrupt channels level */
|
||||
} timer_conf_t;
|
||||
|
@ -23,10 +23,41 @@
|
||||
|
||||
#include "periph_conf.h"
|
||||
#include "periph/pm.h"
|
||||
#include "cpu_pm.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#define PWR_REG_BASE ((uint16_t)&PR)
|
||||
#define PWR_REG_OFFSET (0x01)
|
||||
|
||||
/**
|
||||
* @brief Extract the device id of the given power reduction mask
|
||||
*/
|
||||
static inline uint8_t _device_mask(pwr_reduction_t pwr)
|
||||
{
|
||||
return (pwr & 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Extract the register id of the given power reduction mask
|
||||
*/
|
||||
static inline uint8_t _register_id(pwr_reduction_t pwr)
|
||||
{
|
||||
return (pwr >> 8) & 0xff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate the register index of the given power reduction mask
|
||||
*/
|
||||
static inline uint8_t *_register_addr(pwr_reduction_t pwr)
|
||||
{
|
||||
uint8_t id = _register_id(pwr);
|
||||
uint16_t addr = PWR_REG_BASE + (id * PWR_REG_OFFSET);
|
||||
|
||||
return (uint8_t *)addr;
|
||||
}
|
||||
|
||||
void pm_reboot(void)
|
||||
{
|
||||
DEBUG("Reboot Software Reset\n" );
|
||||
@ -78,3 +109,30 @@ void pm_set(unsigned mode)
|
||||
sleep_disable();
|
||||
irq_restore(irq_state);
|
||||
}
|
||||
|
||||
void pm_periph_enable(pwr_reduction_t pwr)
|
||||
{
|
||||
uint8_t mask = _device_mask(pwr);
|
||||
uint8_t *reg = _register_addr(pwr);
|
||||
|
||||
*reg &= ~mask;
|
||||
}
|
||||
|
||||
void pm_periph_disable(pwr_reduction_t pwr)
|
||||
{
|
||||
uint8_t mask = _device_mask(pwr);
|
||||
uint8_t *reg = _register_addr(pwr);
|
||||
|
||||
*reg |= mask;
|
||||
}
|
||||
|
||||
void pm_periph_power_off(void)
|
||||
{
|
||||
uint8_t *reg = _register_addr(PWR_GENERAL_POWER);
|
||||
uint8_t i;
|
||||
|
||||
/* Freeze all peripheral clocks */
|
||||
for (i = 0; i <= 7; i++) {
|
||||
reg[i] = 0xff;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "cpu_pm.h"
|
||||
#include "thread.h"
|
||||
|
||||
#include "periph/timer.h"
|
||||
@ -112,6 +113,8 @@ int timer_init(tim_t tim, unsigned long freq, timer_cb_t cb, void *arg)
|
||||
return -1;
|
||||
}
|
||||
|
||||
pm_periph_enable(timer_config[tim].pwr);
|
||||
|
||||
dev = timer_config[tim].dev;
|
||||
|
||||
/* stop and reset timer */
|
||||
@ -301,6 +304,7 @@ void timer_stop(tim_t tim)
|
||||
DEBUG("timer_stop\n");
|
||||
timer_config[tim].dev->CTRLA = 0;
|
||||
timer_config[tim].dev->CTRLFSET = TC_CMD_RESTART_gc;
|
||||
pm_periph_disable(timer_config[tim].pwr);
|
||||
}
|
||||
|
||||
void timer_start(tim_t tim)
|
||||
@ -310,6 +314,7 @@ void timer_start(tim_t tim)
|
||||
}
|
||||
|
||||
DEBUG("timer_start\n");
|
||||
pm_periph_enable(timer_config[tim].pwr);
|
||||
timer_config[tim].dev->CTRLA = ctx[tim].prescaler;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include "board.h"
|
||||
#include "cpu.h"
|
||||
#include "cpu_pm.h"
|
||||
#include "sched.h"
|
||||
#include "thread.h"
|
||||
#include "periph/uart.h"
|
||||
@ -257,6 +258,8 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
isr_ctx[uart].rx_cb = rx_cb;
|
||||
isr_ctx[uart].arg = arg;
|
||||
|
||||
pm_periph_enable(uart_config[uart].pwr);
|
||||
|
||||
/* disable and reset UART */
|
||||
dev(uart)->CTRLA = 0;
|
||||
dev(uart)->CTRLB = 0;
|
||||
@ -315,14 +318,12 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len)
|
||||
|
||||
void uart_poweron(uart_t uart)
|
||||
{
|
||||
(void)uart;
|
||||
/* not implemented (yet) */
|
||||
pm_periph_enable(uart_config[uart].pwr);
|
||||
}
|
||||
|
||||
void uart_poweroff(uart_t uart)
|
||||
{
|
||||
(void)uart;
|
||||
/* not implemented (yet) */
|
||||
pm_periph_disable(uart_config[uart].pwr);
|
||||
}
|
||||
|
||||
static inline void _rx_isr_handler(int num)
|
||||
|
Loading…
Reference in New Issue
Block a user