mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
19251: tests/driver_dac_dds: fix output of sine and saw functions r=benpicco a=benpicco 19254: cpu/gd32v: add periph_rtc_mem support r=benpicco a=gschorcht ### Contribution description This PR provides the `periph_rtc_mem` support for GD32VF103. A modified version of this driver could also be used for STM32F1. ### Testing procedure `tests/periph_rtt` should work on any GD32V board, for example: ``` BOARD=sipeed-longan-nano make -C tests/periph_rtt flash ``` ``` Help: Press s to start test, r to print it is ready START main(): This is RIOT! (Version: 2023.04-devel-319-gebc86-cpu/gd32v/periph_rtc_mem) RIOT RTT low-level driver test RTT configuration: RTT_MAX_VALUE: 0xffffffff RTT_FREQUENCY: 32768 Testing the tick conversion Trying to convert 1 to seconds and back Trying to convert 256 to seconds and back Trying to convert 65536 to seconds and back Trying to convert 16777216 to seconds and back Trying to convert 2147483648 to seconds and back All ok Initializing the RTT driver RTC mem OK This test will now display 'Hello' every 5 seconds RTT now: 1 Setting initial alarm to now + 5 s (163841) rtt_get_alarm() PASSED RTC mem OK ``` ### Issues/PRs references Co-authored-by: Benjamin Valentin <benjamin.valentin@ml-pa.com> Co-authored-by: Gunar Schorcht <gunar@schorcht.net>
This commit is contained in:
commit
af393878d1
@ -18,6 +18,7 @@ config CPU_FAM_GD32V
|
||||
select HAS_PERIPH_FLASHPAGE_PAGEWISE
|
||||
select HAS_PERIPH_PM
|
||||
select HAS_PERIPH_RTC
|
||||
select HAS_PERIPH_RTC_MEM
|
||||
select HAS_PERIPH_RTT
|
||||
select HAS_PERIPH_TIMER
|
||||
select HAS_PERIPH_TIMER_PERIODIC
|
||||
|
@ -5,6 +5,7 @@ FEATURES_PROVIDED += periph_clic
|
||||
FEATURES_PROVIDED += periph_gpio
|
||||
FEATURES_PROVIDED += periph_gpio_irq
|
||||
FEATURES_PROVIDED += periph_rtc
|
||||
FEATURES_PROVIDED += periph_rtc_mem
|
||||
FEATURES_PROVIDED += periph_rtt
|
||||
FEATURES_PROVIDED += periph_timer
|
||||
FEATURES_PROVIDED += periph_timer_periodic
|
||||
|
107
cpu/gd32v/periph/rtc_mem.c
Normal file
107
cpu/gd32v/periph/rtc_mem.c
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Gunar Schorcht
|
||||
*
|
||||
* 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_gd32v
|
||||
* @{
|
||||
* @file
|
||||
* @brief Low-level RTC backup memory implementation for GD32VF103
|
||||
*
|
||||
* @author Gunar Schorcht <gunar@schorcht.net>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "periph/rtc_mem.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#define RTC_MEM_SIZE 84 /* RTC data register size in byte */
|
||||
|
||||
extern void rtc_lock(void);
|
||||
extern void rtc_unlock(void);
|
||||
|
||||
/* Since the registers are only 16-bit, but 32-bit aligned and not linearly
|
||||
* addressed, it makes more sense to write and read byte by byte instead of
|
||||
* using memcpy */
|
||||
|
||||
static volatile uint16_t *_rtc_mem_data_reg(unsigned addr)
|
||||
{
|
||||
/* This function determines the register address of the 16-bit BKP data
|
||||
* register which are 32-bit aligned and not addressed linearly. The
|
||||
* layout is the following:
|
||||
*
|
||||
* addr 0, 1, ..., 9 are @0x40006c00 + 0x04, 0x08, ...,0x28
|
||||
* addr 10, 11, ..., 41 are @0x40006c00 + 0x40, 0x44, ...,0xbc
|
||||
*/
|
||||
|
||||
/* 16-bit data register index */
|
||||
unsigned reg_index = addr >> 1;
|
||||
/* 16-bit data register address as multiple of 32 bit */
|
||||
return (reg_index < 10) ? &BKP->DATA0 + (reg_index << 1)
|
||||
: &BKP->DATA10 + ((reg_index - 10) << 1);
|
||||
}
|
||||
|
||||
static void _rtc_mem_write_byte(unsigned addr, uint8_t byte)
|
||||
{
|
||||
volatile uint16_t *reg = _rtc_mem_data_reg(addr);
|
||||
if (addr % 2) {
|
||||
/* high byte */
|
||||
*reg &= 0x00ff;
|
||||
*reg |= (uint16_t)byte << 8;
|
||||
}
|
||||
else {
|
||||
/* low byte */
|
||||
*reg &= 0xff00;
|
||||
*reg |= byte;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t _rtc_mem_read_byte(unsigned addr)
|
||||
{
|
||||
volatile uint16_t *reg = _rtc_mem_data_reg(addr);
|
||||
return (addr % 2) ? (*reg & 0xff00) >> 8 : *reg & 0x00ff;
|
||||
}
|
||||
|
||||
size_t rtc_mem_size(void)
|
||||
{
|
||||
return RTC_MEM_SIZE;
|
||||
}
|
||||
|
||||
void rtc_mem_write(unsigned offset, const void *data, size_t len)
|
||||
{
|
||||
assert(offset + len <= rtc_mem_size());
|
||||
|
||||
/* enable APB1 clocks */
|
||||
RCU->APB1EN |= RCU_APB1EN_PMUEN_Msk | RCU_APB1EN_BKPIEN_Msk;
|
||||
|
||||
/* enable write access to backup domain registers */
|
||||
PMU->CTL |= PMU_CTL_BKPWEN_Msk;
|
||||
|
||||
for (unsigned i = 0; i < len; i++) {
|
||||
_rtc_mem_write_byte(offset++, ((uint8_t *)data)[i]);
|
||||
}
|
||||
|
||||
/* disable write access to backup domain registers */
|
||||
PMU->CTL &= ~PMU_CTL_BKPWEN_Msk;
|
||||
}
|
||||
|
||||
void rtc_mem_read(unsigned offset, void *data, size_t len)
|
||||
{
|
||||
assert(offset + len <= rtc_mem_size());
|
||||
|
||||
/* enable APB1 clocks */
|
||||
RCU->APB1EN |= RCU_APB1EN_PMUEN_Msk | RCU_APB1EN_BKPIEN_Msk;
|
||||
|
||||
for (unsigned i = 0; i < len; i++) {
|
||||
((uint8_t *)data)[i] = _rtc_mem_read_byte(offset++);
|
||||
}
|
||||
}
|
@ -98,24 +98,17 @@ typedef void (*sample_gen_t)(uint8_t *dst, size_t len, uint16_t period);
|
||||
|
||||
static void _fill_saw_samples_8(uint8_t *buf, size_t len, uint16_t period)
|
||||
{
|
||||
uint8_t x = 0;
|
||||
unsigned step = 0xFF / period;
|
||||
|
||||
for (uint16_t i = 0; i < len; ++i) {
|
||||
x += step;
|
||||
buf[i] = x;
|
||||
buf[i] = (i * 0xFFUL) / period;
|
||||
}
|
||||
}
|
||||
|
||||
static void _fill_saw_samples_16(uint8_t *buf, size_t len, uint16_t period)
|
||||
{
|
||||
uint16_t x = 0;
|
||||
unsigned step = 0xFFFF / period;
|
||||
|
||||
for (uint16_t i = 0; i < len; ++i) {
|
||||
x += step;
|
||||
buf[i] = x;
|
||||
buf[++i] = x >> 8;
|
||||
uint16_t y = (i * 0xFFFFUL) / period;
|
||||
buf[i] = y;
|
||||
buf[++i] = y >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,8 +119,7 @@ static void _fill_sine_samples_8(uint8_t *buf, size_t len, uint16_t period)
|
||||
|
||||
for (uint16_t i = 0; i < period; ++i) {
|
||||
x += step;
|
||||
buf[i] = isin(x) >> 5;
|
||||
buf[i] += INT8_MAX + 1;
|
||||
buf[i] = (isin(x) + 4096) >> 6;
|
||||
}
|
||||
|
||||
for (uint16_t i = period; i < len; i += period) {
|
||||
@ -145,8 +137,7 @@ static void _fill_sine_samples_16(uint8_t *buf, size_t len, uint16_t period)
|
||||
for (uint16_t i = 0; i < period; ++i) {
|
||||
x += step;
|
||||
|
||||
uint16_t y = isin(x);
|
||||
y += INT16_MAX + 1;
|
||||
uint16_t y = (isin(x) + 4096) << 2;
|
||||
buf[i] = y;
|
||||
buf[++i] = y >> 8;
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ static void _set_rtc_mem(void)
|
||||
|
||||
static void _get_rtc_mem(void)
|
||||
{
|
||||
char buf[4];
|
||||
char buf[sizeof(riot_msg) - 1];
|
||||
rtc_mem_read(riot_msg_offset, buf, sizeof(buf));
|
||||
|
||||
if (memcmp(buf, riot_msg, sizeof(buf))) {
|
||||
|
Loading…
Reference in New Issue
Block a user