From 919008c51e8296f8dccad05ae507243ace717eb3 Mon Sep 17 00:00:00 2001 From: raiden00pl Date: Wed, 14 Jul 2021 14:41:25 +0200 Subject: [PATCH] add upper-half CORDIC driver --- drivers/Kconfig | 1 + drivers/Makefile | 1 + drivers/math/Kconfig | 28 ++++ drivers/math/Make.defs | 30 ++++ drivers/math/cordic.c | 247 ++++++++++++++++++++++++++++++++ include/nuttx/fs/ioctl.h | 12 +- include/nuttx/math/cordic.h | 190 ++++++++++++++++++++++++ include/nuttx/math/math_ioctl.h | 43 ++++++ 8 files changed, 549 insertions(+), 3 deletions(-) create mode 100644 drivers/math/Kconfig create mode 100644 drivers/math/Make.defs create mode 100644 drivers/math/cordic.c create mode 100644 include/nuttx/math/cordic.h create mode 100644 include/nuttx/math/math_ioctl.h diff --git a/drivers/Kconfig b/drivers/Kconfig index 09e7817777..a36cf3b35b 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -131,3 +131,4 @@ source "drivers/platform/Kconfig" source "drivers/rf/Kconfig" source "drivers/rc/Kconfig" source "drivers/motor/Kconfig" +source "drivers/math/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 88c5339aa1..ee419624d1 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -29,6 +29,7 @@ include audio/Make.defs include bch/Make.defs include can/Make.defs include crypto/Make.defs +include math/Make.defs include motor/Make.defs include i2c/Make.defs include i2s/Make.defs diff --git a/drivers/math/Kconfig b/drivers/math/Kconfig new file mode 100644 index 0000000000..3d29356281 --- /dev/null +++ b/drivers/math/Kconfig @@ -0,0 +1,28 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +menu "MATH Acceleration Support" + +config MATH_CORDIC + bool "MATH CORDIC support" + default n + ---help--- + This selection enables building of the "upper-half" CORDIC driver. + See include/nuttx/math/cordic.h for further CORDIC driver information. + +if MATH_CORDIC + +choice + prompt "MATH CORDIC numeric type" + default MATH_CORDIC_USE_Q31 + +config MATH_CORDIC_USE_Q31 + bool "CORDIC uses Q1.31" + +endchoice + +endif + +endmenu # MATH Acceleration Information diff --git a/drivers/math/Make.defs b/drivers/math/Make.defs new file mode 100644 index 0000000000..b628198bf8 --- /dev/null +++ b/drivers/math/Make.defs @@ -0,0 +1,30 @@ +############################################################################ +# drivers/math/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +# Include CORDIC support + +ifeq ($(CONFIG_MATH_CORDIC),y) +CSRCS += cordic.c +endif + +# Include build support + +DEPPATH += --dep-path math +VPATH += :math diff --git a/drivers/math/cordic.c b/drivers/math/cordic.c new file mode 100644 index 0000000000..ae6fe2d1fa --- /dev/null +++ b/drivers/math/cordic.c @@ -0,0 +1,247 @@ +/**************************************************************************** + * drivers/math/cordic.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +/* This structure describes the state of the upper half driver */ + +struct cordic_upperhalf_s +{ + FAR struct cordic_lowerhalf_s *lower; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int cordic_open(FAR struct file *filep); +static int cordic_close(FAR struct file *filep); +static ssize_t cordic_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t cordic_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +static int cordic_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_cordicops = +{ + cordic_open, /* open */ + cordic_close, /* close */ + cordic_read, /* read */ + cordic_write, /* write */ + NULL, /* seek */ + cordic_ioctl, /* ioctl */ + NULL /* poll */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cordic_open + * + * Description: + * This function is called whenever the cordic timer device is opened. + * + ****************************************************************************/ + +static int cordic_open(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: cordic_close + * + * Description: + * This function is called when the cordic timer device is closed. + * + ****************************************************************************/ + +static int cordic_close(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: cordic_read + * + * Description: + * A dummy read method. This is provided only to satisfy the VFS layer. + * + ****************************************************************************/ + +static ssize_t cordic_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + /* Return zero -- usually meaning end-of-file */ + + return 0; +} + +/**************************************************************************** + * Name: cordic_write + * + * Description: + * A dummy write method. This is provided only to satisfy the VFS layer. + * + ****************************************************************************/ + +static ssize_t cordic_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) +{ + return 0; +} + +/**************************************************************************** + * Name: cordic_ioctl + * + * Description: + * The standard ioctl method. This is where ALL of the cordic timer + * work is done. + * + ****************************************************************************/ + +static int cordic_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct cordic_upperhalf_s *upper = NULL; + FAR struct cordic_lowerhalf_s *lower = NULL; + int ret = 0; + irqstate_t flags; + + _info("cmd: %d arg: %lu\n", cmd, arg); + upper = inode->i_private; + DEBUGASSERT(upper != NULL); + lower = upper->lower; + DEBUGASSERT(lower != NULL); + + flags = enter_critical_section(); + + switch (cmd) + { + /* CORDIC calulcate */ + + case MATHIOC_CORDIC_CALC: + { + FAR struct cordic_calc_s *calc = + (FAR struct cordic_calc_s *)((uintptr_t)arg); + + ret = lower->ops->calc(lower, calc); + + break; + } + + /* Not supported */ + + default: + { + ret = -ENOTTY; + + break; + } + } + + leave_critical_section(flags); + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cordic_register + * + * Description: + * Register a CORDIC driver. + * + ****************************************************************************/ + +int cordic_register(FAR const char *path, + FAR struct cordic_lowerhalf_s *lower) +{ + FAR struct cordic_upperhalf_s *upper = NULL; + int ret = OK; + + DEBUGASSERT(path); + DEBUGASSERT(lower); + + /* Allocate the upper-half data structure */ + + upper = (FAR struct cordic_upperhalf_s *) + kmm_zalloc(sizeof(struct cordic_upperhalf_s)); + if (!upper) + { + _err("Upper half allocation failed\n"); + goto errout; + } + + /* Initialize the CORDIC device structure */ + + upper->lower = lower; + + /* Register the cordic timer device */ + + ret = register_driver(path, &g_cordicops, 0666, upper); + if (ret < 0) + { + _err("register_driver failed: %d\n", ret); + kmm_free(upper); + } + +errout: + return ret; +} diff --git a/include/nuttx/fs/ioctl.h b/include/nuttx/fs/ioctl.h index d93390f248..7eb5118ef3 100644 --- a/include/nuttx/fs/ioctl.h +++ b/include/nuttx/fs/ioctl.h @@ -84,9 +84,10 @@ #define _NOTECTLBASE (0x2c00) /* Note filter control ioctl commands*/ #define _NOTERAMBASE (0x2d00) /* Noteram device ioctl commands*/ #define _RCIOCBASE (0x2e00) /* Remote Control device ioctl commands */ -#define _HIMEMBASE (0x2f00) /* Himem device ioctl commands*/ -#define _EFUSEBASE (0x3000) /* Efuse device ioctl commands*/ -#define _MTRIOBASE (0x3100) /* Motor device ioctl commands*/ +#define _HIMEMBASE (0x2f00) /* Himem device ioctl commands */ +#define _EFUSEBASE (0x3000) /* Efuse device ioctl commands */ +#define _MTRIOBASE (0x3100) /* Motor device ioctl commands */ +#define _MATHIOBASE (0x3200) /* MATH device ioctl commands */ #define _WLIOCBASE (0x8b00) /* Wireless modules ioctl network commands */ /* boardctl() commands share the same number space */ @@ -550,6 +551,11 @@ #define _MTRIOCVALID(c) (_IOC_TYPE(c) == _MTRIOBASE) #define _MTRIOC(nr) _IOC(_MTRIOBASE, nr) +/* MATH drivers *************************************************************/ + +#define _MATHIOCVALID(c) (_IOC_TYPE(c) == _MATHIOBASE) +#define _MATHIOC(nr) _IOC(_MATHIOBASE, nr) + /* Wireless driver network ioctl definitions ********************************/ /* (see nuttx/include/wireless/wireless.h */ diff --git a/include/nuttx/math/cordic.h b/include/nuttx/math/cordic.h new file mode 100644 index 0000000000..fc83bdfc61 --- /dev/null +++ b/include/nuttx/math/cordic.h @@ -0,0 +1,190 @@ +/**************************************************************************** + * include/nuttx/math/cordic.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_MATH_CORDIC_H +#define __INCLUDE_NUTTX_MATH_CORDIC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_MATH_CORDIC_USE_Q31 + +/* q1.31 conversion */ + +# define ftoq31(f32_val) ((f32_val) * 0x80000000) +# define q31tof(q31_val) ((float)(q31_val) / (float)0x80000000) +# define b16toq31(b16_val) ((b16_val) * 0x8000) +# define q31tob16(q31_val) ((q31_val) / 0x8000) +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifdef CONFIG_MATH_CORDIC_USE_Q31 +/* q1.31 as int32_t */ + +typedef int32_t cordic_num_t; +#endif + +/* CORDIC functions */ + +enum cordic_calc_func_e +{ + CORDIC_CALC_FUNC_INVAL = 0, + CORDIC_CALC_FUNC_COS = 1, /* Primary result: cosine * m, + * secondary result: sine * m, + * primary argument: angle, + * secondary argument: modulus m + */ + CORDIC_CALC_FUNC_SIN = 2, /* Primary result: sine * m, + * secondary result: cosine * m, + * primary argument: angle, + * secondary argument: modulus m + */ + CORDIC_CALC_FUNC_PHASE = 3, /* Primary result: phase (atan2), + * secondary result: modulus, + * primary argument: x, + * secondary argument: y + */ + CORDIC_CALC_FUNC_MOD = 4, /* Primary result: modulus, + * secondary result: phase (atan2), + * primary argument: x, + * secondary argument: y + */ + CORDIC_CALC_FUNC_ARCTAN = 5, /* Primary result: arctangent, + * secondary result: none, + * primary argument: x, + * secondary argument: none + */ + CORDIC_CALC_FUNC_HCOS = 6, /* Primary result: hyperbolic cosine, + * secondary result: hyperbolic sine, + * primary argument: x, + * secondary argument: none + */ + CORDIC_CALC_FUNC_HSIN = 7, /* Primary result: hyperbolic sine, + * secondary result: hyperbolic cosine, + * primary argument: x, + * secondary argument: none + */ + CORDIC_CALC_FUNC_HARCTAN = 8, /* Primary result: hyperbolic arctangent, + * secondary result: none, + * primary argument: x, + * secondary argument: none + */ + CORDIC_CALC_FUNC_LN = 9, /* Primary result: natural logarithm, + * secondary result: none, + * primary argument: x, + * secondary argument: none + */ + CORDIC_CALC_FUNC_SQRT = 10, /* Primary result: square root, + * secondary result: none, + * primary argument: x, + * secondary argument: none + */ + CORDIC_CALC_FUNC_LAST +}; + +/* CORDIC calculate request */ + +struct cordic_calc_s +{ + /* CORDIC request configuration */ + + uint8_t func; /* CORDIC function */ + bool res2_incl; /* Include secondary result if available */ + + /* Input data */ + + cordic_num_t arg1; + cordic_num_t arg2; + + /* Output data */ + + cordic_num_t res1; + cordic_num_t res2; +}; + +/* This structure provides the "lower-half" driver operations available to + * the "upper-half" driver. + */ + +struct cordic_lowerhalf_s; +struct cordic_ops_s +{ + /* CORDIC calculate request */ + + CODE int (*calc)(FAR struct cordic_lowerhalf_s *lower, + FAR struct cordic_calc_s *calc); +}; + +/* This structure provides the publicly visible representation of the + * "lower-half" driver state structure. "lower half" drivers will have an + * internal structure definition that will be cast-compatible with this + * structure definitions. + */ + +struct cordic_lowerhalf_s +{ + /* Publicly visible portion of the "lower-half" driver state structure. */ + + FAR const struct cordic_ops_s *ops; /* Lower half operations */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: cordic_register + * + * Description: + * Register a CORDIC driver. + * + ****************************************************************************/ + +int cordic_register(FAR const char *path, + FAR struct cordic_lowerhalf_s *lower); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_MATH_CORDIC_H */ diff --git a/include/nuttx/math/math_ioctl.h b/include/nuttx/math/math_ioctl.h new file mode 100644 index 0000000000..c051c46dd1 --- /dev/null +++ b/include/nuttx/math/math_ioctl.h @@ -0,0 +1,43 @@ +/**************************************************************************** + * include/nuttx/math/math_ioctl.h + * NuttX MATH-related IOCTLs definitions + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_MATH_MATH_IOCTL_H +#define __INCLUDE_NUTTX_MATH_MATH_IOCTL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* All MATH-related IOCTL commands must be defined in this header file + * in order to assure that every IOCTL command is unique and will not be + * aliased. + */ + +#define MATHIOC_CORDIC_CALC _MATHIOC(1) + +#endif /* __INCLUDE_NUTTX_MATH_MATH_IOCTL_H */