1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-17 05:12:57 +01:00

cc26x2_cc13x2: add function to change AUX opmode

This function is needed to setup the AUX operational mode at startup,
also used for managing low-power states.

Signed-off-by: Jean Pierre Dudey <jeandudey@hotmail.com>
This commit is contained in:
Jean Pierre Dudey 2020-04-29 09:38:36 -05:00
parent 549d7ff24f
commit 2921944c66
No known key found for this signature in database
GPG Key ID: 631A70D74E41F1AD
2 changed files with 117 additions and 0 deletions

91
cpu/cc26x2_cc13x2/aux.c Normal file
View File

@ -0,0 +1,91 @@
/*
* Copyright (C) 2020 Locha Inc
*
* 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_cc26x2_cc13x2
* @{
*
* @file
* @brief CC26x2, CC13x2 AUX functions
* @author Jean Pierre Dudey <jeandudey@hotmail.com>
* @}
*/
#include <assert.h>
#include "cpu.h"
/**
* @brief Order of operation modes
*
* This is to calculate which mode follows the other, to change step-by-step
* the mode.
*
* @{
*/
#define OPMODE_PDA_ORDER (0)
#define OPMODE_A_ORDER (1)
#define OPMODE_LP_ORDER (2)
#define OPMODE_PDLP_ORDER (3)
/** @} */
/** Array to map an operation mode to it's order when changing it */
static const uint8_t _opmode_to_order[4] = {
OPMODE_A_ORDER,
OPMODE_LP_ORDER,
OPMODE_PDA_ORDER,
OPMODE_PDLP_ORDER
};
/** Array to map an order to an operation mode, used to get the next operation
* mode. This is because we need to change the operation in ordered steps */
static const uint8_t _order_to_opmode[4] = {
AUX_SYSIF_OPMODEREQ_REQ_PDA,
AUX_SYSIF_OPMODEREQ_REQ_A,
AUX_SYSIF_OPMODEREQ_REQ_LP,
AUX_SYSIF_OPMODEREQ_REQ_PDLP
};
void aux_sysif_opmode_change(uint32_t target_opmode)
{
assert((target_opmode == AUX_SYSIF_OPMODEREQ_REQ_PDLP) ||
(target_opmode == AUX_SYSIF_OPMODEREQ_REQ_PDA) ||
(target_opmode == AUX_SYSIF_OPMODEREQ_REQ_LP) ||
(target_opmode == AUX_SYSIF_OPMODEREQ_REQ_A));
uint32_t current_opmode;
uint32_t next_mode;
/* Change AUX operation mode following hardware rules, operation mode
* change needs to be done in order, and one step at a time:
*
* PDA -> A -> LP -> PDLP
*/
do {
current_opmode = AUX_SYSIF->OPMODEREQ;
/* Wait for change ACK */
while (current_opmode != AUX_SYSIF->OPMODEACK) {}
if (current_opmode == target_opmode) {
break;
}
/* At this point we aren't in the mode we want, now we calculate which
* mode follows this and make the change to that mode, this is repeated
* in this loop until we get to the desired mode */
uint32_t current_order = _opmode_to_order[current_opmode];
if (current_order < _opmode_to_order[target_opmode]) {
next_mode = _order_to_opmode[current_order + 1];
}
else {
next_mode = _order_to_opmode[current_order - 1];
}
/* Request next mode */
AUX_SYSIF->OPMODEREQ = next_mode;
} while (current_opmode != target_opmode);
}

View File

@ -217,6 +217,17 @@ typedef struct {
reg32_t SWPWRPROF; /**< Software Power Profiler */
} aux_sysif_regs_t;
/**
* @brief AUX_SYSIF register values
* @{
*/
#define AUX_SYSIF_OPMODEREQ_REQ_PDLP 0x00000003
#define AUX_SYSIF_OPMODEREQ_REQ_PDA 0x00000002
#define AUX_SYSIF_OPMODEREQ_REQ_LP 0x00000001
#define AUX_SYSIF_OPMODEREQ_REQ_A 0x00000000
/** @} */
/**
* @ingroup cpu_specific_peripheral_memory_map
* @{
@ -232,6 +243,21 @@ typedef struct {
*/
#define AUX_SYSIF ((aux_sysif_regs_t *) (AUX_SYSIF_BASE))
/**
* @brief AUX_SYSIF functions
* @{
*/
/**
* @brief Changes the AUX operational mode
*
* @note Only this function should be used to change the operational mode,
* because it needs to be done in order.
*
* @param[in] target_opmode The opmode we want to change to.
*/
void aux_sysif_opmode_change(uint32_t target_opmode);
/** @} */
/**
* @brief AUX_TIMER01 registers
*/