Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: stm32l4: example for DFSDM irq #250

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions examples/stm32/l4/stm32l476rg-nucleo/dfsdm_irq/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
##
## This file is part of the libopencm3 project.
##
## This library is free software: you can redistribute it and/or modify
## it under the terms of the GNU Lesser General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public License
## along with this library. If not, see <http://www.gnu.org/licenses/>.
##

BINARY=dfsdm_irq
OBJS = usart_stdio.o syscalls.o
DEVICE=stm32l476rg

include ../../Makefile.include
6 changes: 6 additions & 0 deletions examples/stm32/l4/stm32l476rg-nucleo/dfsdm_irq/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
This demonstrates the DFSDM on the L476RG nucleo board.

* printf via usart1 TX on Pin A9 115200@8n1
* this example assumes that there is a sigma delta modulator connected to pins B1 (CLK) and C2 (DATA) e.g. TI AMC1306
* pll configuration from hsi
* dfsdm0_isr reads the data regularily as soon as they are available.
151 changes: 151 additions & 0 deletions examples/stm32/l4/stm32l476rg-nucleo/dfsdm_irq/dfsdm_irq.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2024 Karl Palsson <[email protected]>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/

#include <errno.h>
#include <unistd.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/exti.h>
#include <libopencm3/stm32/flash.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/timer.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/dma.h>

#include <libopencm3/stm32/l4/dfsdm.h>

#include <stdio.h>
#include "usart_stdio.h"

#define LED_GREEN_PORT GPIOA
#define LED_GREEN_PIN GPIO5

/* CPU core clock setup */
static void clock_setup(void)
{
rcc_clock_setup_pll(&rcc_hsi16_configs[RCC_CLOCK_VRANGE1_80MHZ]);
}

static void gpio_setup(void)
{
rcc_periph_clock_enable(RCC_GPIOA);

gpio_mode_setup(LED_GREEN_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_GREEN_PIN);
}

void dfsdm_filter_setup(void)
{
dfsdm_flt_set_regular_ch(0, 0);
dfsdm_flt_rcont_repeat(0);
// dfsdm_flt_rcont_once(0);
dfsdm_flt_reg_end_of_conv_irq_enable(0);

dfsdm_flt_set_sinc_filter_order(0, 3);

/* (FOSR = FOSR[9:0] +1) same as with clock divider */
dfsdm_flt_set_sinc_oversample_ratio(0, 63);
dfsdm_flt_set_integrator_oversample_ratio(0, 0);

/* enable rdma */
dfsdm_flt_rdma_enable(0);
dfsdm_flt_filter_enable(0);

printf("DFSDM_FLTxCR1: %lx\r\n", DFSDM_FLTxCR1(0));
printf("DFSDM_FLTxCR1: %lx\r\n", DFSDM_FLTxCR2(0));
}

void dfsdm_setup(void)
{
/* Setup GPIO pins for AF5 for SPI1 signals. */
rcc_periph_clock_enable(RCC_GPIOB);
gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO1);
gpio_set_af(GPIOB, GPIO_AF6, GPIO1);

rcc_periph_clock_enable(RCC_GPIOC);
gpio_mode_setup(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2);
gpio_set_af(GPIOC, GPIO_AF6, GPIO2);

rcc_periph_clock_enable(RCC_DFSDM);

dfsdm_set_ckout_src_sys(0);

/* the actual divider is (Divider = CKOUTDIV+1), so we need to subtract by one: 80MHz/8 would be 10MHz sampling rate */
dfsdm_set_ckout_divider(0,7);

dfsdm_set_datpack_standard(0);
dfsdm_set_datmpx_external(0);
dfsdm_set_chinsel_same_channel(0);
dfsdm_set_ckaben_disable(0);
dfsdm_set_scden_disable(0);
dfsdm_set_spi_clock_ckout(0);
dfsdm_set_sitp_spi_rise_edge(0);

dfsdm_set_offset(0, 0);
dfsdm_set_data_shift(0, 0);

dfsdm_set_chen_enable(0);

printf("DFSDM_CHyCFGR1: %lx\r\n", DFSDM_CHyCFGR1(0));
printf("DFSDM_CHyCFGR2: %lx\r\n", DFSDM_CHyCFGR2(0));
}

/*
* The rate isr will be called is calculated like this:
* fCKIN/(Fosr*(Iosr-1+Ford)+(Ford+1))
* Taken from the reference manual STM32L476RG (24.4.13 Data unit block).
* So e.g. fCKIN = 10MHz, Fosr = 16, Iosr = 0 (so in this formular I think we should use 1),
* Ford = 3 (Sinc3) this gives:
* 10000000/(16*(1-1+3)+(3+1)) = 192307.69230
*/
void dfsdm0_isr(void)
{
if(dfsdm_flt_get_eof_regular_conv_flag(0))
{
int32_t tmp_data = dfsdm_flt_get_regular_ch_conv_data(0);

/* here you can do something with the converted data */
(void) tmp_data;

gpio_toggle(LED_GREEN_PORT, LED_GREEN_PIN);
}
}

int main(void)
{
clock_setup();
gpio_setup();
usart_setup();

printf("Hello from stm32476rg nucleo DFSDM IRQ example!\r\n");

nvic_enable_irq(NVIC_DFSDM0_IRQ);

dfsdm_setup();
dfsdm_filter_setup();
dfsdm_enable(0);

/* start regular conversion */
dfsdm_flt_rswstart(0);

while (1)
{
}

return 0;
}
198 changes: 198 additions & 0 deletions examples/stm32/l4/stm32l476rg-nucleo/dfsdm_irq/syscalls.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/*
* newlib_stubs.c
*
* Created on: 2 Nov 2010
* Author: nanoage.co.uk
*
* From "The STM32 discovery Scrapbook":
* "Getting Newlib and printf to work with the STM32 and Code Sourcery Lite EABI"
* https://sites.google.com/site/stm32discovery/open-source-development-with-the-stm32-discovery/getting-newlib-to-work-with-stm32-and-code-sourcery-lite-eabi
*
* Note that the read/write function here haven't actually been used. They should probably be revised to use the getchar/putchar
* interrupt-based functions defined in usart.c. An example of how to do this is given at http://www.cs.indiana.edu/~geobrown/book.pdf
*/
#include <errno.h>
#include <sys/stat.h>
#include <sys/times.h>
#include <sys/unistd.h>
#include <libopencm3/stm32/usart.h>

#undef errno
extern int errno;

/*
environ
A pointer to a list of environment variables and their values.
For a minimal environment, this empty list is adequate:
*/
char *__env[1] = { 0 };
char **environ = __env;

int _write(int file, char *ptr, int len);

void _exit(int status) {
_write(1, "exit", 4);
while (1) {
;
}
}

int _close(int file) {
return -1;
}
/*
execve
Transfer control to a new process. Minimal implementation (for a system without processes):
*/
int _execve(char *name, char **argv, char **env) {
errno = ENOMEM;
return -1;
}
/*
fork
Create a new process. Minimal implementation (for a system without processes):
*/

int _fork() {
errno = EAGAIN;
return -1;
}
/*
fstat
Status of an open file. For consistency with other minimal implementations in these examples,
all files are regarded as character special devices.
The `sys/stat.h' header file required is distributed in the `include' subdirectory for this C library.
*/
int _fstat(int file, struct stat *st) {
st->st_mode = S_IFCHR;
return 0;
}

/*
getpid
Process-ID; this is sometimes used to generate strings unlikely to conflict with other processes. Minimal implementation, for a system without processes:
*/

int _getpid() {
return 1;
}

/*
isatty
Query whether output stream is a terminal. For consistency with the other minimal implementations,
*/
int _isatty(int file) {
switch (file) {
case STDOUT_FILENO:
case STDERR_FILENO:
case STDIN_FILENO:
return 1;
default:
//errno = ENOTTY;
errno = EBADF;
return 0;
}
}

/*
kill
Send a signal. Minimal implementation:
*/
int _kill(int pid, int sig) {
errno = EINVAL;
return (-1);
}

/*
link
Establish a new name for an existing file. Minimal implementation:
*/

int _link(char *old, char *new) {
errno = EMLINK;
return -1;
}

/*
lseek
Set position in a file. Minimal implementation:
*/
int _lseek(int file, int ptr, int dir) {
return 0;
}

/*
read
Read a character to a file. `libc' subroutines will use this system routine for input from all files, including stdin
Returns -1 on error or blocks until the number of characters have been read.
*/

int _read(int file, char *ptr, int len) {
return -1;
}

/*
stat
Status of a file (by name). Minimal implementation:
int _EXFUN(stat,( const char *__path, struct stat *__sbuf ));
*/

int _stat(const char *filepath, struct stat *st) {
st->st_mode = S_IFCHR;
return 0;
}

/*
times
Timing information for current process. Minimal implementation:
*/

clock_t _times(struct tms *buf) {
return -1;
}

/*
unlink
Remove a file's directory entry. Minimal implementation:
*/
int _unlink(char *name) {
errno = ENOENT;
return -1;
}

/*
wait
Wait for a child process. Minimal implementation:
*/
int _wait(int *status) {
errno = ECHILD;
return -1;
}

/*
* Called by libc stdio fwrite functions
*/
int
_write(int fd, char *ptr, int len)
{
int i = 0;

/*
* Write "len" of char from "ptr" to file id "fd"
* Return number of char written.
*
* Only work for STDOUT, STDIN, and STDERR
*/
if (fd > 2) {
return -1;
}
while (*ptr && (i < len)) {
usart_send_blocking(USART1, *ptr);
if (*ptr == '\n') {
usart_send_blocking(USART1, '\r');
}
i++;
ptr++;
}
return i;
}
Loading