change Nuttx to Nuttx_Fusion_XiUOS
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
############################################################################
|
||||
# apps/Makefile
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
export APPDIR = $(CURDIR)
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
include $(APPDIR)/../../../APP_Framework/Make.defs
|
||||
|
||||
# Symbol table for loadable apps.
|
||||
|
||||
SYMTABSRC = symtab_apps.c
|
||||
SYMTABOBJ = $(SYMTABSRC:.c=$(OBJEXT))
|
||||
|
||||
# Build targets
|
||||
|
||||
# We first remove libapps.a before letting the other rules add objects to it
|
||||
# so that we ensure libapps.a does not contain objects from prior build
|
||||
|
||||
all:
|
||||
$(RM) $(BIN)
|
||||
$(MAKE) $(BIN)
|
||||
|
||||
.PHONY: import install dirlinks export .depdirs preconfig depend clean distclean
|
||||
.PHONY: context clean_context context_all register register_all
|
||||
.PRECIOUS: $(BIN)
|
||||
|
||||
$(foreach SDIR, $(CONFIGURED_APPS), $(eval $(call SDIR_template,$(SDIR),all)))
|
||||
$(foreach SDIR, $(CONFIGURED_APPS), $(eval $(call SDIR_template,$(SDIR),install)))
|
||||
$(foreach SDIR, $(CONFIGURED_APPS), $(eval $(call SDIR_template,$(SDIR),context)))
|
||||
$(foreach SDIR, $(CONFIGURED_APPS), $(eval $(call SDIR_template,$(SDIR),register)))
|
||||
$(foreach SDIR, $(CONFIGURED_APPS), $(eval $(call SDIR_template,$(SDIR),depend)))
|
||||
$(foreach SDIR, $(CLEANDIRS), $(eval $(call SDIR_template,$(SDIR),clean)))
|
||||
$(foreach SDIR, $(CLEANDIRS), $(eval $(call SDIR_template,$(SDIR),distclean)))
|
||||
|
||||
$(MKDEP): $(TOPDIR)/tools/mkdeps.c
|
||||
$(HOSTCC) $(HOSTINCLUDES) $(HOSTCFLAGS) $< -o $@
|
||||
|
||||
$(INCDIR): $(TOPDIR)/tools/incdir.c
|
||||
$(HOSTCC) $(HOSTINCLUDES) $(HOSTCFLAGS) $< -o $@
|
||||
|
||||
IMPORT_TOOLS = $(MKDEP) $(INCDIR)
|
||||
|
||||
# In the KERNEL build, we must build and install all of the modules. No
|
||||
# symbol table is needed
|
||||
|
||||
ifeq ($(CONFIG_BUILD_KERNEL),y)
|
||||
|
||||
install: $(foreach SDIR, $(CONFIGURED_APPS), $(SDIR)_install)
|
||||
|
||||
.import: $(foreach SDIR, $(CONFIGURED_APPS), $(SDIR)_all)
|
||||
$(Q) $(MAKE) install
|
||||
|
||||
import: $(IMPORT_TOOLS)
|
||||
$(Q) $(MAKE) context TOPDIR="$(APPDIR)$(DELIM)import"
|
||||
$(Q) $(MAKE) register TOPDIR="$(APPDIR)$(DELIM)import"
|
||||
$(Q) $(MAKE) depend TOPDIR="$(APPDIR)$(DELIM)import"
|
||||
$(Q) $(MAKE) .import TOPDIR="$(APPDIR)$(DELIM)import"
|
||||
|
||||
else
|
||||
|
||||
# In FLAT and protected modes, the modules have already been created. A
|
||||
# symbol table is required.
|
||||
|
||||
ifeq ($(CONFIG_BUILD_LOADABLE),)
|
||||
|
||||
$(BIN): $(foreach SDIR, $(CONFIGURED_APPS), $(SDIR)_all)
|
||||
$(Q) for app in ${CONFIGURED_APPS}; do \
|
||||
$(MAKE) -C "$${app}" archive ; \
|
||||
done
|
||||
|
||||
else
|
||||
|
||||
$(SYMTABSRC): $(foreach SDIR, $(CONFIGURED_APPS), $(SDIR)_all)
|
||||
$(Q) for app in ${CONFIGURED_APPS}; do \
|
||||
$(MAKE) -C "$${app}" archive ; \
|
||||
done
|
||||
$(Q) $(MAKE) install
|
||||
$(Q) $(APPDIR)$(DELIM)tools$(DELIM)mksymtab.sh $(BINDIR) >$@.tmp
|
||||
$(Q) $(call TESTANDREPLACEFILE, $@.tmp, $@)
|
||||
|
||||
$(SYMTABOBJ): %$(OBJEXT): %.c
|
||||
$(call COMPILE, -fno-lto $<, $@)
|
||||
|
||||
$(BIN): $(SYMTABOBJ)
|
||||
ifeq ($(CONFIG_CYGWIN_WINTOOL),y)
|
||||
$(call ARCHIVE_ADD, "${shell cygpath -w $(BIN)}", $^)
|
||||
else
|
||||
$(call ARCHIVE_ADD, $(BIN), $^)
|
||||
endif
|
||||
|
||||
endif # !CONFIG_BUILD_LOADABLE
|
||||
|
||||
install: $(foreach SDIR, $(CONFIGURED_APPS), $(SDIR)_install)
|
||||
|
||||
# Link nuttx
|
||||
|
||||
HEAD_OBJ += $(wildcard $(APPDIR)$(DELIM)import$(DELIM)startup$(DELIM)*$(OBJEXT))
|
||||
HEAD_OBJ += $(wildcard $(APPDIR)$(DELIM)builtin$(DELIM)*$(OBJEXT))
|
||||
|
||||
.import: $(BIN) install
|
||||
$(Q) echo "LD: nuttx"
|
||||
$(Q) $(LD) --entry=__start $(LDFLAGS) $(LDLIBPATH) $(EXTRA_LIBPATHS) \
|
||||
-L$(APPDIR)$(DELIM)import$(DELIM)scripts -T$(LDNAME) \
|
||||
-o nuttx$(EXEEXT) $(HEAD_OBJ) $(EXTRA_OBJS) $(LDSTARTGROUP) \
|
||||
$(BIN) $(LDLIBS) $(EXTRA_LIBS) $(LDENDGROUP)
|
||||
ifeq ($(CONFIG_INTELHEX_BINARY),y)
|
||||
$(Q) echo "CP: nuttx.hex"
|
||||
$(Q) $(OBJCOPY) $(OBJCOPYARGS) -O ihex nuttx$(EXEEXT) nuttx.hex
|
||||
endif
|
||||
ifeq ($(CONFIG_RAW_BINARY),y)
|
||||
$(Q) echo "CP: nuttx.bin"
|
||||
$(Q) $(OBJCOPY) $(OBJCOPYARGS) -O binary nuttx$(EXEEXT) nuttx.bin
|
||||
endif
|
||||
$(call POSTBUILD, $(APPDIR))
|
||||
|
||||
import: $(IMPORT_TOOLS)
|
||||
$(Q) $(MAKE) context TOPDIR="$(APPDIR)$(DELIM)import"
|
||||
$(Q) $(MAKE) register TOPDIR="$(APPDIR)$(DELIM)import"
|
||||
$(Q) $(MAKE) depend TOPDIR="$(APPDIR)$(DELIM)import"
|
||||
$(Q) $(MAKE) .import TOPDIR="$(APPDIR)$(DELIM)import"
|
||||
|
||||
endif # CONFIG_BUILD_KERNEL
|
||||
|
||||
dirlinks:
|
||||
$(Q) $(MAKE) -C platform dirlinks
|
||||
|
||||
context_all: $(foreach SDIR, $(CONFIGURED_APPS), $(SDIR)_context)
|
||||
register_all: $(foreach SDIR, $(CONFIGURED_APPS), $(SDIR)_register)
|
||||
|
||||
context:
|
||||
$(Q) $(MAKE) context_all
|
||||
$(Q) $(MAKE) register_all
|
||||
|
||||
Kconfig:
|
||||
$(foreach SDIR, $(CONFIGDIRS), $(call MAKE_template,$(SDIR),preconfig))
|
||||
$(Q) $(MKKCONFIG)
|
||||
|
||||
preconfig: Kconfig
|
||||
|
||||
export:
|
||||
ifneq ($(EXPORTDIR),)
|
||||
ifneq ($(BUILTIN_REGISTRY),)
|
||||
$(Q) mkdir -p "${EXPORTDIR}"/registry || exit 1; \
|
||||
for f in "${BUILTIN_REGISTRY}"/*.bdat "${BUILTIN_REGISTRY}"/*.pdat ; do \
|
||||
[ -f "$${f}" ] && cp -f "$${f}" "${EXPORTDIR}"/registry ; \
|
||||
done
|
||||
endif
|
||||
endif
|
||||
|
||||
.depdirs: $(foreach SDIR, $(CONFIGURED_APPS), $(SDIR)_depend)
|
||||
|
||||
.depend: Makefile .depdirs
|
||||
$(Q) touch $@
|
||||
|
||||
depend: .depend
|
||||
|
||||
clean_context:
|
||||
$(Q) $(MAKE) -C platform clean_context
|
||||
$(Q) $(MAKE) -C builtin clean_context
|
||||
|
||||
clean: $(foreach SDIR, $(CLEANDIRS), $(SDIR)_clean)
|
||||
$(call DELFILE, $(SYMTABSRC))
|
||||
$(call DELFILE, $(SYMTABOBJ))
|
||||
$(call DELFILE, $(BIN))
|
||||
$(call DELFILE, Kconfig)
|
||||
$(call DELDIR, $(BINDIR))
|
||||
$(call CLEAN)
|
||||
|
||||
distclean: $(foreach SDIR, $(CLEANDIRS), $(SDIR)_distclean)
|
||||
ifeq ($(CONFIG_WINDOWS_NATIVE),y)
|
||||
$(Q) ( if exist external ( \
|
||||
echo ********************************************************" \
|
||||
echo * The external directory/link must be removed manually *" \
|
||||
echo ********************************************************" \
|
||||
)
|
||||
else
|
||||
$(Q) ( if [ -e external ]; then \
|
||||
echo "********************************************************"; \
|
||||
echo "* The external directory/link must be removed manually *"; \
|
||||
echo "********************************************************"; \
|
||||
fi; \
|
||||
)
|
||||
endif
|
||||
$(call DELFILE, .depend)
|
||||
$(call DELFILE, $(SYMTABSRC))
|
||||
$(call DELFILE, $(SYMTABOBJ))
|
||||
$(call DELFILE, $(BIN))
|
||||
$(call DELFILE, Kconfig)
|
||||
$(call DELDIR, $(BINDIR))
|
||||
$(call CLEAN)
|
||||
+608
@@ -0,0 +1,608 @@
|
||||
/****************************************************************************
|
||||
* apps/examples/sx127x_demo/sx127x_demo.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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file sx127x_demo.c
|
||||
* @brief nuttx source code
|
||||
* https://github.com/apache/incubator-nuttx-apps
|
||||
* @version 10.2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <nuttx/wireless/lpwan/sx127x.h>
|
||||
#include <nuttx/input/buttons.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ADAPTER_SX1278_DRIVER
|
||||
# define DEV_NAME CONFIG_ADAPTER_SX1278_DRIVER
|
||||
#else
|
||||
# define DEV_NAME "/dev/sx127x"
|
||||
#endif
|
||||
|
||||
#define TX_BUFFER_MAX 255
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
enum app_mode_e
|
||||
{
|
||||
APP_MODE_RX = 0,
|
||||
APP_MODE_TX = 1,
|
||||
APP_MODE_RXTX = 2,
|
||||
APP_MODE_SCAN = 3
|
||||
};
|
||||
|
||||
enum app_modulation_e
|
||||
{
|
||||
APP_MODULATION_LORA = 0,
|
||||
APP_MODULATION_FSK = 1,
|
||||
APP_MODULATION_OOK = 2,
|
||||
};
|
||||
|
||||
/* Application arguments */
|
||||
|
||||
struct args_s
|
||||
{
|
||||
uint32_t frequency;
|
||||
int16_t interval;
|
||||
int16_t time;
|
||||
uint8_t app_mode;
|
||||
uint8_t modulation;
|
||||
uint8_t datalen;
|
||||
int8_t power;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
struct args_s g_args;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sx127x_help
|
||||
****************************************************************************/
|
||||
|
||||
static void sx127x_help(FAR struct args_s *args)
|
||||
{
|
||||
printf("Usage: sx127x [OPTIONS]\n\n");
|
||||
printf(" [-m modulation] modulation scheme (default=0)\n");
|
||||
printf(" 0 - LORA\n");
|
||||
printf(" 1 - FSK\n");
|
||||
printf(" 2 - OOK\n");
|
||||
printf(" [-f frequency Hz] RF frequency (default=%d)\n",
|
||||
CONFIG_EXAMPLES_SX127X_RFFREQ);
|
||||
printf(" [-i interval sec] radio access time interval (default=%d)\n",
|
||||
CONFIG_EXAMPLES_SX127X_INTERVAL);
|
||||
printf(" [-l datalen] data length for TX (default=%d)\n",
|
||||
CONFIG_EXAMPLES_SX127X_TXDATA);
|
||||
printf(" [-d time sec] demo time, 0 if infinity (default=%d)\n",
|
||||
CONFIG_EXAMPLES_SX127X_TIME);
|
||||
printf(" [-r/-t/-x/-s] select app mode (default=r)\n");
|
||||
printf(" r - RX\n");
|
||||
printf(" t - TX\n");
|
||||
printf(" x - RX/TX (not supported yet)\n");
|
||||
printf(" s - SCAN\n");
|
||||
printf(" [-p power dBm] TX power (default=%d)\n",
|
||||
CONFIG_EXAMPLES_SX127X_TXPOWER);
|
||||
printf(" [-h] print this message\n");
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arg_string
|
||||
****************************************************************************/
|
||||
|
||||
static int arg_string(FAR char **arg, FAR char **value)
|
||||
{
|
||||
FAR char *ptr = *arg;
|
||||
|
||||
if (ptr[2] == '\0')
|
||||
{
|
||||
*value = arg[1];
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*value = &ptr[2];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arg_decimal
|
||||
****************************************************************************/
|
||||
|
||||
static int arg_decimal(FAR char **arg, FAR int *value)
|
||||
{
|
||||
FAR char *string;
|
||||
int ret;
|
||||
|
||||
ret = arg_string(arg, &string);
|
||||
*value = atoi(string);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: parse_args
|
||||
****************************************************************************/
|
||||
|
||||
static void parse_args(FAR struct args_s *args, int argc, FAR char **argv)
|
||||
{
|
||||
FAR char *ptr;
|
||||
int index;
|
||||
int nargs;
|
||||
int i_value;
|
||||
|
||||
for (index = 1; index < argc; )
|
||||
{
|
||||
ptr = argv[index];
|
||||
if (ptr[0] != '-')
|
||||
{
|
||||
printf("Invalid options format: %s\n", ptr);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
switch (ptr[1])
|
||||
{
|
||||
/* Interval between RX/TX operations */
|
||||
|
||||
case 'i':
|
||||
{
|
||||
nargs = arg_decimal(&argv[index], &i_value);
|
||||
index += nargs;
|
||||
|
||||
args->interval = i_value;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Demo time */
|
||||
|
||||
case 'd':
|
||||
{
|
||||
nargs = arg_decimal(&argv[index], &i_value);
|
||||
index += nargs;
|
||||
|
||||
args->time = i_value;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Data length for TX */
|
||||
|
||||
case 'l':
|
||||
{
|
||||
nargs = arg_decimal(&argv[index], &i_value);
|
||||
index += nargs;
|
||||
|
||||
args->datalen = i_value;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Modem RF frequency */
|
||||
|
||||
case 'f':
|
||||
{
|
||||
nargs = arg_decimal(&argv[index], &i_value);
|
||||
index += nargs;
|
||||
|
||||
args->frequency = i_value;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Modem modulation scheme */
|
||||
|
||||
case 'm':
|
||||
{
|
||||
nargs = arg_decimal(&argv[index], &i_value);
|
||||
index += nargs;
|
||||
|
||||
args->modulation = i_value;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Modem TX power */
|
||||
|
||||
case 'p':
|
||||
{
|
||||
nargs = arg_decimal(&argv[index], &i_value);
|
||||
index += nargs;
|
||||
|
||||
args->power = i_value;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* RX mode */
|
||||
|
||||
case 'r':
|
||||
{
|
||||
args->app_mode = APP_MODE_RX;
|
||||
index += 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* TX mode */
|
||||
|
||||
case 't':
|
||||
{
|
||||
args->app_mode = APP_MODE_TX;
|
||||
index += 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* RX-TX mode */
|
||||
|
||||
case 'x':
|
||||
{
|
||||
args->app_mode = APP_MODE_RXTX;
|
||||
index += 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Scan mode */
|
||||
|
||||
case 's':
|
||||
{
|
||||
args->app_mode = APP_MODE_SCAN;
|
||||
index += 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Print help message */
|
||||
|
||||
case 'h':
|
||||
{
|
||||
sx127x_help(args);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Unsupported option */
|
||||
|
||||
default:
|
||||
{
|
||||
printf("Unsupported option: %s\n", ptr);
|
||||
sx127x_help(args);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: validate_args
|
||||
****************************************************************************/
|
||||
|
||||
static int validate_args(FAR struct args_s *args)
|
||||
{
|
||||
int ret = OK;
|
||||
|
||||
/* TODO */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: print_hex
|
||||
****************************************************************************/
|
||||
|
||||
static void print_hex(uint8_t *data, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
printf("empty buffer!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0 ; i < len ; i += 1)
|
||||
{
|
||||
printf("0x%02x ", data[i]);
|
||||
|
||||
if ((i + 1) % 10 == 0)
|
||||
{
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: modulation_set
|
||||
****************************************************************************/
|
||||
|
||||
static int modulation_set(int fd, uint8_t modulation)
|
||||
{
|
||||
int ret = OK;
|
||||
|
||||
switch (modulation)
|
||||
{
|
||||
case APP_MODULATION_LORA:
|
||||
{
|
||||
printf("LORA modulation\n");
|
||||
|
||||
modulation = SX127X_MODULATION_LORA;
|
||||
ret = ioctl(fd, SX127XIOC_MODULATIONSET,
|
||||
(unsigned long)&modulation);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("failed change modulation %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case APP_MODULATION_FSK:
|
||||
{
|
||||
printf("FSK modulation\n");
|
||||
|
||||
modulation = SX127X_MODULATION_FSK;
|
||||
ret = ioctl(fd, SX127XIOC_MODULATIONSET,
|
||||
(unsigned long)&modulation);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("failed change modulation %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case APP_MODULATION_OOK:
|
||||
{
|
||||
printf("OOK modulation\n");
|
||||
|
||||
modulation = SX127X_MODULATION_OOK;
|
||||
ret = ioctl(fd, SX127XIOC_MODULATIONSET,
|
||||
(unsigned long)&modulation);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("failed change modulation %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
printf("Unsupported app modulation %d!\n", modulation);
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int main(int argc, FAR char *argv[])
|
||||
{
|
||||
#ifdef CONFIG_LPWAN_SX127X_RXSUPPORT
|
||||
struct sx127x_read_hdr_s data;
|
||||
#endif
|
||||
struct sx127x_chanscan_ioc_s chanscan;
|
||||
struct args_s *args;
|
||||
struct timespec tstart;
|
||||
struct timespec tnow;
|
||||
uint8_t buffer[TX_BUFFER_MAX];
|
||||
uint8_t opmode;
|
||||
uint8_t i;
|
||||
int ret;
|
||||
int fd;
|
||||
|
||||
/* Initialize buffer with data */
|
||||
|
||||
for (i = 0; i < TX_BUFFER_MAX; i += 1)
|
||||
{
|
||||
buffer[i] = i;
|
||||
}
|
||||
|
||||
/* Initialize variables */
|
||||
|
||||
args = &g_args;
|
||||
args->app_mode = APP_MODE_RX;
|
||||
args->modulation = APP_MODULATION_LORA;
|
||||
args->frequency = CONFIG_EXAMPLES_SX127X_RFFREQ;
|
||||
args->power = CONFIG_EXAMPLES_SX127X_TXPOWER;
|
||||
args->interval = CONFIG_EXAMPLES_SX127X_INTERVAL;
|
||||
args->time = CONFIG_EXAMPLES_SX127X_TIME;
|
||||
args->datalen = CONFIG_EXAMPLES_SX127X_TXDATA;
|
||||
|
||||
/* Parse the command line */
|
||||
|
||||
parse_args(args, argc, argv);
|
||||
|
||||
/* Validate arguments */
|
||||
|
||||
ret = validate_args(args);
|
||||
if (ret != OK)
|
||||
{
|
||||
printf("sx127x_main: validate arguments failed!\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
printf("Start sx127x_demo\n");
|
||||
|
||||
/* Open device */
|
||||
|
||||
fd = open(DEV_NAME, O_RDWR);
|
||||
if (fd < 0)
|
||||
{
|
||||
int errcode = errno;
|
||||
printf("ERROR: Failed to open device %s: %d\n", DEV_NAME, errcode);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Get start time */
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &tstart);
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (args->app_mode)
|
||||
{
|
||||
#ifdef CONFIG_LPWAN_SX127X_TXSUPPORT
|
||||
/* Transmit some data */
|
||||
|
||||
case APP_MODE_TX:
|
||||
{
|
||||
printf("\nSend %d bytes\n", args->datalen);
|
||||
|
||||
ret = write(fd, buffer, args->datalen);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("write failed %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LPWAN_SX127X_RXSUPPORT
|
||||
/* Receive data */
|
||||
|
||||
case APP_MODE_RX:
|
||||
{
|
||||
printf("Waiting for data\n");
|
||||
|
||||
ret = read(fd, &data, sizeof(struct sx127x_read_hdr_s));
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("Read failed %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
printf("\nReceived:\n");
|
||||
printf("SNR = %d\n", data.snr);
|
||||
printf("RSSI = %d\n", data.rssi);
|
||||
printf("len = %d\n", data.datalen);
|
||||
print_hex(data.data, data.datalen);
|
||||
printf("\n");
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Send some data and wait for response */
|
||||
|
||||
case APP_MODE_RXTX:
|
||||
{
|
||||
printf("TODO: APP RXTX\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Scan channel */
|
||||
|
||||
case APP_MODE_SCAN:
|
||||
{
|
||||
/* TODO: Configure this from command line */
|
||||
|
||||
chanscan.freq = args->frequency;
|
||||
chanscan.rssi_thr = -30;
|
||||
chanscan.stime = 2;
|
||||
chanscan.free = false;
|
||||
chanscan.rssi_max = 0;
|
||||
|
||||
ret = ioctl(fd, SX127XIOC_CHANSCAN, (unsigned long)&chanscan);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("failed chanscan %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
printf("freq = %" PRId32 " max = %d min = %d free = %d\n",
|
||||
chanscan.freq,
|
||||
chanscan.rssi_max, chanscan.rssi_min, chanscan.free);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
printf("Unsupported app mode!\n");
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
printf("wait %d sec ...\n", args->interval);
|
||||
sleep(args->interval);
|
||||
|
||||
if (args->time > 0)
|
||||
{
|
||||
/* Get time now */
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &tnow);
|
||||
|
||||
if (tnow.tv_sec - tstart.tv_sec >= args->time)
|
||||
{
|
||||
printf("Timeout - force exit!\n");
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errout:
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,116 @@
|
||||
############################################################################
|
||||
# apps/nshlib/Makefile
|
||||
#
|
||||
# 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 $(APPDIR)/Make.defs
|
||||
|
||||
# NSH Library
|
||||
|
||||
CSRCS = nsh_init.c nsh_parse.c nsh_console.c nsh_script.c nsh_system.c
|
||||
CSRCS += nsh_command.c nsh_fscmds.c nsh_ddcmd.c nsh_proccmds.c nsh_mmcmds.c
|
||||
CSRCS += nsh_timcmds.c nsh_envcmds.c nsh_syscmds.c nsh_dbgcmds.c nsh_Applicationscmd.c
|
||||
|
||||
ifeq ($(CONFIG_FILE_STREAM),y)
|
||||
CSRCS += nsh_session.c
|
||||
ifeq ($(CONFIG_NSH_CONSOLE_LOGIN),y)
|
||||
CSRCS += nsh_login.c
|
||||
endif
|
||||
else
|
||||
CSRCS += nsh_stdsession.c
|
||||
ifeq ($(CONFIG_NSH_CONSOLE_LOGIN),y)
|
||||
CSRCS += nsh_stdlogin.c
|
||||
endif
|
||||
endif
|
||||
|
||||
CSRCS += nsh_fsutils.c
|
||||
|
||||
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
|
||||
CSRCS += nsh_builtin.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_FILE_APPS),y)
|
||||
CSRCS += nsh_fileapps.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_VARS),y)
|
||||
CSRCS += nsh_vars.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_ROMFSETC),y)
|
||||
CSRCS += nsh_romfsetc.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NET),y)
|
||||
CSRCS += nsh_netcmds.c
|
||||
|
||||
ifeq ($(CONFIG_NET_ROUTE),y)
|
||||
CSRCS += nsh_routecmds.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y)
|
||||
CSRCS += nsh_mntcmds.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MODULE),y)
|
||||
ifneq ($(CONFIG_NSH_DISABLE_MODCMDS),y)
|
||||
CSRCS += nsh_modcmds.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_CONSOLE),y)
|
||||
CSRCS += nsh_consolemain.c
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_NSH_DISABLE_PRINTF),y)
|
||||
CSRCS += nsh_printf.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_TELNET),y)
|
||||
CSRCS += nsh_telnetd.c
|
||||
ifeq ($(CONFIG_NSH_TELNET_LOGIN),y)
|
||||
CSRCS += nsh_telnetlogin.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_NSH_DISABLESCRIPT),y)
|
||||
CSRCS += nsh_test.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USBDEV),y)
|
||||
CSRCS += nsh_usbconsole.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_ALTCONDEV),y)
|
||||
CSRCS += nsh_altconsole.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_USBDEV_TRACE),y)
|
||||
CSRCS += nsh_usbtrace.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NETUTILS_CODECS),y)
|
||||
CSRCS += nsh_codeccmd.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_LOGIN_PASSWD),y)
|
||||
CSRCS += nsh_passwdcmds.c
|
||||
endif
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file nsh_Applicationscmd.c
|
||||
* @brief nsh cmd function support
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.03.17
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <libgen.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
extern int FrameworkInit(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_Hcho1os
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_APPLICATION_SENSOR_HCHO_TB600B_WQ_HCHO1OS) && !defined(CONFIG_NSH_DISABLE_HCHO_TB600B_WQ_HCHO1OS)
|
||||
extern void HchoTb600bHcho1os(void);
|
||||
int cmd_Hcho1os(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
HchoTb600bHcho1os();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_Tvoc10
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_APPLICATION_SENSOR_TVOC_TB600B_TVOC10) && !defined(CONFIG_NSH_DISABLE_TB600B_TVOC10)
|
||||
extern void TvocTb600bTvoc10(void);
|
||||
int cmd_Tvoc10(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
TvocTb600bTvoc10();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_Iaq10
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_APPLICATION_SENSOR_IAQ) && !defined(CONFIG_NSH_DISABLE_TB600B_IAQ10)
|
||||
extern void IaqTb600bIaq10(void);
|
||||
int cmd_Iaq10(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
IaqTb600bIaq10();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_As830
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_APPLICATION_SENSOR_CH4_AS830) && !defined(CONFIG_NSH_DISABLE_CH4_AS830)
|
||||
extern void Ch4As830(void);
|
||||
int cmd_As830(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
Ch4As830();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_Co2Zg09
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_APPLICATION_SENSOR_CO2_ZG09) && !defined(CONFIG_NSH_DISABLE_CO2ZG09)
|
||||
extern void Co2Zg09(void);
|
||||
int cmd_Co2Zg09(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
Co2Zg09();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_Pm10Ps5308
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_APPLICATION_SENSOR_PM1_0_PS5308) && !defined(CONFIG_NSH_DISABLE_PM1_0PS5308)
|
||||
extern void Pm10Ps5308(void);
|
||||
int cmd_Pm10Ps5308(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
Pm10Ps5308();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_Pm25Ps5308
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_APPLICATION_SENSOR_PM2_5_PS5308) && !defined(CONFIG_NSH_DISABLE_PM2_5PS5308)
|
||||
extern void Pm25Ps5308(void);
|
||||
int cmd_Pm25Ps5308(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
Pm25Ps5308();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_Pm10Ps5308
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_APPLICATION_SENSOR_PM10_PS5308) && !defined(CONFIG_NSH_DISABLE_PM10PS5308)
|
||||
extern void Pm100Ps5308(void);
|
||||
int cmd_Pm100Ps5308(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
Pm100Ps5308();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_VoiceD124
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_APPLICATION_SENSOR_VOICE_D124) && !defined(CONFIG_NSH_DISABLE_VOICED124)
|
||||
extern void VoiceD124(void);
|
||||
int cmd_VoiceD124(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
VoiceD124();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_TempHs300x
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_APPLICATION_SENSOR_TEMPERATURE_HS300X) && !defined(CONFIG_NSH_DISABLE_TEMPHS300X)
|
||||
extern void TempHs300x(void);
|
||||
int cmd_TempHs300x(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
TempHs300x();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_HumiHs300x
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_APPLICATION_SENSOR_HUMIDITY_HS300X) && !defined(CONFIG_NSH_DISABLE_HUMIHS300X)
|
||||
extern void HumiHs300x(void);
|
||||
int cmd_HumiHs300x(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
HumiHs300x();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_WindDirectionQsFx
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_APPLICATION_SENSOR_WINDDIRECTION_QS_FX) && !defined(CONFIG_NSH_DISABLE_QS_FX)
|
||||
extern void WindDirectionQsFx(void);
|
||||
int cmd_WindDirectionQsFx(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
WindDirectionQsFx();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_WindSpeedQsFs
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_APPLICATION_SENSOR_WINDSPEED_QS_FS) && !defined(CONFIG_NSH_DISABLE_QS_FS)
|
||||
extern void WindSpeedQsFs(void);
|
||||
int cmd_WindSpeedQsFs(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
WindSpeedQsFs();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_openzigbee
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_CONNECTION_ADAPTER_ZIGBEE) && !defined(CONFIG_NSH_DISABLE_OPENZIGBEE)
|
||||
extern int openzigbee(void);
|
||||
int cmd_openzigbee(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
openzigbee();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(CONFIG_CONNECTION_ADAPTER_ZIGBEE) && !defined(CONFIG_NSH_DISABLE_SENDZIGBEE)
|
||||
extern int sendzigbee(int argc, char *argv[]);
|
||||
int cmd_sendzigbee(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
sendzigbee(argc,argv);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CONNECTION_ADAPTER_ZIGBEE) && !defined(CONFIG_NSH_DISABLE_RECVZIGBEE)
|
||||
extern int recvzigbee(void);
|
||||
int cmd_recvzigbee(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
recvzigbee();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ADAPTER_SX1278) && !defined(CONFIG_NSH_DISABLE_ADAPTER_LORATEST)
|
||||
extern int AdapterLoraTest(void);
|
||||
int cmd_AdapterLoraTest(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, world!\n");
|
||||
FrameworkInit();
|
||||
AdapterLoraTest();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_K210_FFT_TEST) && !defined(CONFIG_NSH_DISABLE_K210_FFT)
|
||||
extern void nuttx_k210_fft_test(void);
|
||||
int cmd_fft(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "Hello, fft!\n");
|
||||
nuttx_k210_fft_test();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
export current=$(pwd)
|
||||
export nuttx=$current/..
|
||||
export top=$current/../../..
|
||||
|
||||
cd $top
|
||||
git submodule
|
||||
git submodule init
|
||||
git submodule update Ubiquitous/Nuttx_Fusion_XiUOS/apps
|
||||
git submodule update Ubiquitous/Nuttx_Fusion_XiUOS/nuttx
|
||||
cd $current
|
||||
|
||||
chmod -R +x $top
|
||||
find $top -name Kconfig -exec dos2unix -q {} \;
|
||||
|
||||
cp -rf $current/nuttx $nuttx
|
||||
cp -rf $current/apps $nuttx
|
||||
cp -rf $nuttx/aiit_board/aiit-arm32-board $nuttx/nuttx/boards/arm/stm32
|
||||
cp -rf $nuttx/aiit_board/aiit-riscv64-board $nuttx/nuttx/boards/risc-v/k210
|
||||
cp -rf $nuttx/aiit_board/xidatong $nuttx/nuttx/boards/arm/imxrt
|
||||
|
||||
cd ../nuttx
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,48 @@
|
||||
############################################################################
|
||||
# Makefile
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
# Check if the system has been configured
|
||||
|
||||
ifeq ($(wildcard .config),)
|
||||
.DEFAULT default:
|
||||
@echo "NuttX has not been configured!"
|
||||
@echo "To configure the project:"
|
||||
@echo " tools/configure.sh <config>"
|
||||
@echo "For a list of available configurations:"
|
||||
@echo " tools/configure.sh -L"
|
||||
else
|
||||
include .config
|
||||
|
||||
# Build any necessary tools needed early in the build.
|
||||
# incdir - Is needed immediately by all Make.defs file.
|
||||
|
||||
TOPDIR := ${shell echo $(CURDIR) | sed -e 's/ /\\ /g'}
|
||||
DUMMY := ${shell $(MAKE) -C tools -f Makefile.host incdir \
|
||||
INCDIR="$(TOPDIR)/tools/incdir.sh"}
|
||||
|
||||
# Include the correct Makefile for the selected architecture.
|
||||
|
||||
ifeq ($(CONFIG_WINDOWS_NATIVE),y)
|
||||
include tools/Makefile.win
|
||||
else
|
||||
export KERNEL_ROOT = $(CURDIR)
|
||||
include tools/Makefile.unix
|
||||
endif
|
||||
endif
|
||||
@@ -0,0 +1,120 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/include/imxrt/chip.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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file chip.h
|
||||
* @brief nuttx source code
|
||||
* https://github.com/apache/incubator-nuttx.git
|
||||
* @version 10.2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-23
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM_INCLUDE_IMXRT_CHIP_H
|
||||
#define __ARCH_ARM_INCLUDE_IMXRT_CHIP_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* Get customizations for each supported chip */
|
||||
|
||||
#if defined(CONFIG_ARCH_CHIP_MIMXRT1021CAG4A) || \
|
||||
defined(CONFIG_ARCH_CHIP_MIMXRT1021CAF4A) || \
|
||||
defined(CONFIG_ARCH_CHIP_MIMXRT1021DAF5A) || \
|
||||
defined(CONFIG_ARCH_CHIP_MIMXRT1021DAG5A)
|
||||
|
||||
/* MIMXRT1021CAG4A - 144 pin, 400MHz Industrial
|
||||
* MIMXRT1021CAF4A - 100 pin, 400MHz Industrial
|
||||
* MIMXRT1021DAF5A - 100 pin, 500MHz Consumer
|
||||
* MIMXRT1021DAG5A - 144 pin, 500MHz Consumer
|
||||
*/
|
||||
|
||||
# define IMXRT_OCRAM_SIZE (256 * 1024) /* 256Kb OCRAM */
|
||||
# define IMXRT_GPIO_NPORTS 5 /* Five total ports */
|
||||
/* but 4 doesn't exist */
|
||||
|
||||
#elif defined(CONFIG_ARCH_CHIP_MIMXRT1051DVL6A) || \
|
||||
defined(CONFIG_ARCH_CHIP_MIMXRT1051CVL5A) || \
|
||||
defined(CONFIG_ARCH_CHIP_MIMXRT1052DVL6A) || \
|
||||
defined(CONFIG_ARCH_CHIP_MIMXRT1052CVL5A) || \
|
||||
defined(CONFIG_ARCH_CHIP_MIMXRT1052CVL5B)
|
||||
/* MIMXRT1051CVL5A - Industrial, Reduced Features, 528MHz
|
||||
* MIMXRT1051DVL6A - Consumer, Reduced Features, 600MHz
|
||||
* MIMXRT1052CVL5A - Industrial, Full Feature, 528MHz
|
||||
* MIMXRT1052CVL5B - Industrial, Full Feature, 528MHz
|
||||
* MIMXRT1052DVL6A - Consumer, Full Feature, 600MHz
|
||||
*/
|
||||
|
||||
# define IMXRT_OCRAM_SIZE (512 * 1024) /* 512Kb OCRAM */
|
||||
# define IMXRT_GPIO_NPORTS 5 /* Five total ports */
|
||||
|
||||
#elif defined(CONFIG_ARCH_CHIP_MIMXRT1061DVL6A) || \
|
||||
defined(CONFIG_ARCH_CHIP_MIMXRT1061CVL5A) || \
|
||||
defined(CONFIG_ARCH_CHIP_MIMXRT1062DVL6A) || \
|
||||
defined(CONFIG_ARCH_CHIP_MIMXRT1062CVL5A) || \
|
||||
defined(CONFIG_ARCH_CHIP_MIMXRT1064DVL6A) || \
|
||||
defined(CONFIG_ARCH_CHIP_MIMXRT1064CVL5A)
|
||||
/* MIMXRT1061CVL5A - Industrial, Reduced Features, 528MHz
|
||||
* MIMXRT1061DVL6A - Consumer, Reduced Features, 600MHz
|
||||
* MIMXRT1062CVL5A - Industrial, Full Feature, 528MHz
|
||||
* MIMXRT1062DVL6A - Consumer, Full Feature, 600MHz
|
||||
* MIMXRT1064CVL5A - Industrial, Full Feature, 528MHz
|
||||
* MIMXRT1064DVL6A - Consumer, Full Feature, 600MHz
|
||||
*/
|
||||
|
||||
# define IMXRT_OCRAM_SIZE (1024 * 1024) /* 1024Kb OCRAM */
|
||||
# define IMXRT_GPIO_NPORTS 9 /* Nine total ports */
|
||||
#else
|
||||
# error "Unknown i.MX RT chip type"
|
||||
#endif
|
||||
|
||||
/* NVIC priority levels *****************************************************/
|
||||
|
||||
/* Each priority field holds an 8-bit priority value, 0-15. The lower the
|
||||
* value, the greater the priority of the corresponding interrupt. The i.MX
|
||||
* RT processor implements only bits[7:4] of each field, bits[3:0] read as
|
||||
* zero and ignore writes.
|
||||
*/
|
||||
|
||||
#define NVIC_SYSH_PRIORITY_MIN 0xf0 /* All bits[7:4] set is min pri */
|
||||
#define NVIC_SYSH_PRIORITY_DEFAULT 0x80 /* Midpoint is the default */
|
||||
#define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */
|
||||
#define NVIC_SYSH_PRIORITY_STEP 0x40 /* Two bits of interrupt pri used */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#endif /* __ARCH_ARM_INCLUDE_IMXRT_CHIP_H */
|
||||
File diff suppressed because it is too large
Load Diff
+1844
File diff suppressed because it is too large
Load Diff
+3417
File diff suppressed because it is too large
Load Diff
+260
@@ -0,0 +1,260 @@
|
||||
/****************************************************************************
|
||||
* arch/risc-v/src/common/riscv_internal.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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file riscv_internal.h
|
||||
* @brief nuttx source code
|
||||
* https://github.com/apache/incubator-nuttx.git
|
||||
* @version 10.2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_RISCV_SRC_COMMON_UP_INTERNAL_H
|
||||
#define __ARCH_RISCV_SRC_COMMON_UP_INTERNAL_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
# include <nuttx/compiler.h>
|
||||
# include <sys/types.h>
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* This is the value used to mark the stack for subsequent stack monitoring
|
||||
* logic.
|
||||
*/
|
||||
|
||||
#define STACK_COLOR 0xdeadbeef
|
||||
#define INTSTACK_COLOR 0xdeadbeef
|
||||
#define HEAP_COLOR 'h'
|
||||
|
||||
/* In the RISC_V model, the state is copied from the stack to the TCB, but
|
||||
* only a referenced is passed to get the state from the TCB.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ARCH_RV64GC
|
||||
#define riscv_savestate(regs) riscv_copystate(regs, (uint64_t*)CURRENT_REGS)
|
||||
#define riscv_restorestate(regs) (CURRENT_REGS = regs)
|
||||
#else
|
||||
#define riscv_savestate(regs) riscv_copystate(regs, (uint32_t*)g_current_regs)
|
||||
#define riscv_restorestate(regs) (g_current_regs = regs)
|
||||
#endif
|
||||
|
||||
#define _START_TEXT &_stext
|
||||
#define _END_TEXT &_etext
|
||||
#define _START_BSS &_sbss
|
||||
#define _END_BSS &_ebss
|
||||
#define _DATA_INIT &_eronly
|
||||
#define _START_DATA &_sdata
|
||||
#define _END_DATA &_edata
|
||||
#define _START_TDATA &_stdata
|
||||
#define _END_TDATA &_etdata
|
||||
#define _START_TBSS &_stbss
|
||||
#define _END_TBSS &_etbss
|
||||
|
||||
/* Determine which (if any) console driver to use. If a console is enabled
|
||||
* and no other console device is specified, then a serial console is
|
||||
* assumed.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_DEV_CONSOLE
|
||||
# undef USE_SERIALDRIVER
|
||||
# undef USE_EARLYSERIALINIT
|
||||
#else
|
||||
# if defined(CONFIG_CONSOLE_SYSLOG)
|
||||
# undef USE_SERIALDRIVER
|
||||
# undef USE_EARLYSERIALINIT
|
||||
# else
|
||||
# define USE_SERIALDRIVER 1
|
||||
# define USE_EARLYSERIALINIT 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef CONFIG_ARCH_RV64GC
|
||||
#ifdef CONFIG_SMP
|
||||
EXTERN volatile uint64_t *g_current_regs[CONFIG_SMP_NCPUS];
|
||||
# define CURRENT_REGS (g_current_regs[up_cpu_index()])
|
||||
#else
|
||||
EXTERN volatile uint64_t *g_current_regs[1];
|
||||
# define CURRENT_REGS (g_current_regs[0])
|
||||
#endif
|
||||
EXTERN uintptr_t g_idle_topstack;
|
||||
#else
|
||||
EXTERN volatile uint32_t *g_current_regs;
|
||||
# define CURRENT_REGS (g_current_regs)
|
||||
EXTERN uint32_t g_idle_topstack;
|
||||
#endif
|
||||
|
||||
/* Address of the saved user stack pointer */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||
EXTERN uint32_t g_intstackalloc; /* Allocated stack base */
|
||||
EXTERN uint32_t g_intstacktop; /* Initial top of interrupt stack */
|
||||
#endif
|
||||
|
||||
/* These 'addresses' of these values are setup by the linker script. They
|
||||
* are not actual uint32_t storage locations! They are only used meaningfully
|
||||
* in the following way:
|
||||
*
|
||||
* - The linker script defines, for example, the symbol_sdata.
|
||||
* - The declareion extern uint32_t _sdata; makes C happy. C will believe
|
||||
* that the value _sdata is the address of a uint32_t variable _data (it
|
||||
* is not!).
|
||||
* - We can recoved the linker value then by simply taking the address of
|
||||
* of _data. like: uint32_t *pdata = &_sdata;
|
||||
*/
|
||||
|
||||
EXTERN uint32_t _stext; /* Start of .text */
|
||||
EXTERN uint32_t _etext; /* End_1 of .text + .rodata */
|
||||
EXTERN const uint32_t _eronly; /* End+1 of read only section (.text + .rodata) */
|
||||
EXTERN uint32_t _sdata; /* Start of .data */
|
||||
EXTERN uint32_t _edata; /* End+1 of .data */
|
||||
EXTERN uint32_t _sbss; /* Start of .bss */
|
||||
EXTERN uint32_t _ebss; /* End+1 of .bss */
|
||||
EXTERN uint32_t _stdata; /* Start of .tdata */
|
||||
EXTERN uint32_t _etdata; /* End+1 of .tdata */
|
||||
EXTERN uint32_t _stbss; /* Start of .tbss */
|
||||
EXTERN uint32_t _etbss; /* End+1 of .tbss */
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* Memory allocation ********************************************************/
|
||||
|
||||
#if CONFIG_MM_REGIONS > 1
|
||||
void riscv_addregion(void);
|
||||
#else
|
||||
# define riscv_addregion()
|
||||
#endif
|
||||
|
||||
void up_allocat_eheap(FAR void **heap_start, size_t *heap_size);
|
||||
|
||||
/* IRQ initialization *******************************************************/
|
||||
|
||||
void up_irqinitialize(void);
|
||||
void riscv_ack_irq(int irq);
|
||||
|
||||
#ifdef CONFIG_ARCH_RV64GC
|
||||
void riscv_copystate(uint64_t *dest, uint64_t *src);
|
||||
void riscv_copyfullstate(uint64_t *dest, uint64_t *src);
|
||||
#else
|
||||
void riscv_copystate(uint32_t *dest, uint32_t *src);
|
||||
void riscv_copyfullstate(uint32_t *dest, uint32_t *src);
|
||||
#endif
|
||||
|
||||
void riscv_sigdeliver(void);
|
||||
int riscv_swint(int irq, void *context, void *arg);
|
||||
uint32_t riscv_get_newintctx(void);
|
||||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
#ifdef CONFIG_ARCH_RV64GC
|
||||
void riscv_savefpu(uint64_t *regs);
|
||||
void riscv_restorefpu(const uint64_t *regs);
|
||||
#else /* !CONFIG_ARCH_RV64GC */
|
||||
void riscv_savefpu(uint32_t *regs);
|
||||
void riscv_restorefpu(const uint32_t *regs);
|
||||
#endif /* CONFIG_ARCH_RV64GC */
|
||||
#else
|
||||
# define riscv_savefpu(regs)
|
||||
# define riscv_restorefpu(regs)
|
||||
#endif
|
||||
|
||||
/* RISC-V PMP Config ********************************************************/
|
||||
|
||||
void riscv_config_pmp_region(uintptr_t region, uintptr_t attr,
|
||||
uintptr_t base, uintptr_t size);
|
||||
|
||||
/* Power management *********************************************************/
|
||||
|
||||
void up_timer_initialize(void);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
void riscv_pminitialize(void);
|
||||
#else
|
||||
# define riscv_pminitialize()
|
||||
#endif
|
||||
|
||||
/* Low level serial output **************************************************/
|
||||
void up_serialinit(void);
|
||||
void riscv_lowputc(char ch);
|
||||
void riscv_lowputs(const char *str);
|
||||
void up_puts(const char *str);
|
||||
|
||||
#ifdef USE_SERIALDRIVER
|
||||
void riscv_serialinit(void);
|
||||
#endif
|
||||
|
||||
#ifdef USE_EARLYSERIALINIT
|
||||
void riscv_earlyserialinit(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RPMSG_UART
|
||||
void rpmsg_serialinit(void);
|
||||
#endif
|
||||
|
||||
/* Exception Handler ********************************************************/
|
||||
|
||||
void riscv_exception(uint32_t mcause, uint32_t *regs);
|
||||
|
||||
/* Debug ********************************************************************/
|
||||
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
void riscv_stack_color(void *stackbase, size_t nbytes);
|
||||
#endif
|
||||
|
||||
/* The OS start routine **************************************************/
|
||||
|
||||
void nx_start(void);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __ARCH_RISCV_SRC_COMMON_UP_INTERNAL_H */
|
||||
@@ -0,0 +1,45 @@
|
||||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
comment "K210 Configuration Options"
|
||||
|
||||
config K210_ENABLE_DPFPU
|
||||
bool "K210 DP_FPU Support"
|
||||
default y
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_DPFPU
|
||||
select LIBC_FLOATINGPOINT
|
||||
---help---
|
||||
Enable the RISC-V Double-Precision Floating Point Unit (DP-FPU).
|
||||
|
||||
menu "K210 Peripheral Support"
|
||||
|
||||
# These "hidden" settings determine whether a peripheral option is available
|
||||
# for the selected MCU
|
||||
|
||||
config K210_HAVE_UART0
|
||||
bool
|
||||
default y
|
||||
select UART0_SERIALDRIVER
|
||||
select ARCH_HAVE_SERIAL_TERMIOS
|
||||
|
||||
# These are the peripheral selections proper
|
||||
|
||||
config K210_UART0
|
||||
bool "UART0"
|
||||
default y
|
||||
select ARCH_HAVE_UART0
|
||||
select ARCH_HAVE_SERIAL_TERMIOS
|
||||
select K210_UART
|
||||
|
||||
endmenu
|
||||
|
||||
menu "K210 Others"
|
||||
|
||||
config K210_WITH_QEMU
|
||||
bool "qemu support"
|
||||
default n
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,74 @@
|
||||
############################################################################
|
||||
# arch/risc-v/src/k210/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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
# Specify our HEAD assembly file. This will be linked as
|
||||
# the first object file, so it will appear at address 0
|
||||
HEAD_ASRC = k210_vectors.S
|
||||
|
||||
# Specify our general Assembly files
|
||||
CHIP_ASRCS = k210_head.S riscv_syscall.S
|
||||
|
||||
CMN_ASRCS += riscv_testset.S
|
||||
|
||||
# Specify C code within the common directory to be included
|
||||
CMN_CSRCS += riscv_initialize.c riscv_swint.c
|
||||
CMN_CSRCS += riscv_createstack.c riscv_exit.c riscv_fault.c
|
||||
CMN_CSRCS += riscv_assert.c riscv_blocktask.c riscv_copystate.c riscv_initialstate.c
|
||||
CMN_CSRCS += riscv_interruptcontext.c riscv_modifyreg32.c riscv_puts.c
|
||||
CMN_CSRCS += riscv_releasepending.c riscv_reprioritizertr.c
|
||||
CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
|
||||
CMN_CSRCS += riscv_sigdeliver.c riscv_unblocktask.c riscv_usestack.c
|
||||
CMN_CSRCS += riscv_mdelay.c riscv_copyfullstate.c
|
||||
|
||||
ifeq ($(CONFIG_STACK_COLORATION),y)
|
||||
CMN_CSRCS += riscv_checkstack.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_HAVE_VFORK),y)
|
||||
CMN_CSRCS += riscv_vfork.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_FPU),y)
|
||||
CMN_ASRCS += riscv_fpu.S
|
||||
endif
|
||||
|
||||
# Specify our C code within this directory to be included
|
||||
CHIP_CSRCS = k210_arch.c
|
||||
CHIP_CSRCS += k210_allocateheap.c k210_clockconfig.c
|
||||
CHIP_CSRCS += k210_idle.c k210_irq.c k210_irq_dispatch.c
|
||||
CHIP_CSRCS += k210_lowputc.c k210_serial.c k210_fpioa.c
|
||||
CHIP_CSRCS += k210_start.c k210_timerisr.c k210_gpiohs.c
|
||||
CHIP_CSRCS += interrupt.c syscalls.c
|
||||
CHIP_CSRCS += uarths.c plic.c sysctl.c fpioa.c clint.c gpio.c gpiohs.c utils.c
|
||||
CHIP_CSRCS += dmac.c fft.c i2s.c apu.c
|
||||
|
||||
ifeq ($(CONFIG_SMP), y)
|
||||
CHIP_CSRCS += k210_cpuidlestack.c k210_cpuindex.c
|
||||
CHIP_CSRCS += k210_cpupause.c k210_cpustart.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BUILD_PROTECTED),y)
|
||||
CMN_CSRCS += riscv_task_start.c
|
||||
CMN_CSRCS += riscv_pthread_start.c riscv_pthread_exit.c
|
||||
CMN_CSRCS += riscv_signal_dispatch.c riscv_pmp.c
|
||||
CMN_UASRCS += riscv_signal_handler.S
|
||||
|
||||
CHIP_CSRCS += k210_userspace.c
|
||||
endif
|
||||
@@ -0,0 +1,540 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file apu.c
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#include <debug.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include "syscalls.h"
|
||||
#include "sysctl.h"
|
||||
#include "apu.h"
|
||||
|
||||
#define BEAFORMING_BASE_ADDR (0x50250200)
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846264338327950288
|
||||
#endif
|
||||
|
||||
volatile apu_reg_t *const apu = (volatile apu_reg_t *)BEAFORMING_BASE_ADDR;
|
||||
|
||||
/*
|
||||
Voice strength average value right shift factor. When performing sound direction detect,
|
||||
the average value of samples from different channels is required, this right shift factor
|
||||
is used to perform division.
|
||||
0x0: no right shift; 0x1: right shift by 1-bit;
|
||||
. . . . . .
|
||||
0xF: right shift by 15-bit.
|
||||
*/
|
||||
void apu_set_audio_gain(uint16_t gain)
|
||||
{
|
||||
apu_ch_cfg_t ch_cfg = apu->bf_ch_cfg_reg;
|
||||
|
||||
ch_cfg.we_bf_target_dir = 0;
|
||||
ch_cfg.we_bf_sound_ch_en = 0;
|
||||
ch_cfg.we_data_src_mode = 0;
|
||||
ch_cfg.we_audio_gain = 1;
|
||||
ch_cfg.audio_gain = gain;
|
||||
apu->bf_ch_cfg_reg = ch_cfg;
|
||||
}
|
||||
|
||||
/*set sampling shift*/
|
||||
void apu_set_smpl_shift(uint8_t smpl_shift)
|
||||
{
|
||||
apu_dwsz_cfg_t tmp = apu->bf_dwsz_cfg_reg;
|
||||
|
||||
tmp.smpl_shift_bits = smpl_shift;
|
||||
apu->bf_dwsz_cfg_reg = tmp;
|
||||
}
|
||||
|
||||
/*get sampling shift*/
|
||||
uint8_t apu_get_smpl_shift(void)
|
||||
{
|
||||
apu_dwsz_cfg_t tmp = apu->bf_dwsz_cfg_reg;
|
||||
|
||||
return tmp.smpl_shift_bits;
|
||||
}
|
||||
|
||||
/*
|
||||
* APU unit sound channel enable control bits. Bit 'x' corresponds to enable bit for sound
|
||||
* channel 'x' (x = 0, 1, 2, . . ., 7). APU sound channels are related with I2S host RX channels.
|
||||
* APU sound channel 0/1 correspond to the left/right channel of I2S RX0; APU channel 2/3 correspond
|
||||
* to left/right channels of I2S RX1; and things like that. Software write '1' to enable a sound
|
||||
* channel and hardware automatically clear the bit after the sample buffers used for direction
|
||||
* searching is filled full.
|
||||
* 0x1: writing '1' to enable the corresponding APU sound channel.
|
||||
*/
|
||||
void apu_set_channel_enabled(uint8_t channel_bit)
|
||||
{
|
||||
apu_ch_cfg_t ch_cfg;
|
||||
|
||||
ch_cfg.we_audio_gain = 0;
|
||||
ch_cfg.we_bf_target_dir = 0;
|
||||
ch_cfg.we_bf_sound_ch_en = 1;
|
||||
ch_cfg.bf_sound_ch_en = channel_bit;
|
||||
apu->bf_ch_cfg_reg = ch_cfg;
|
||||
}
|
||||
|
||||
/*
|
||||
* APU unit sound channel enable control bits. Bit 'x' corresponds to enable bit for sound
|
||||
* channel 'x' (x = 0, 1, 2, . . ., 7). APU sound channels are related with I2S host RX channels.
|
||||
* APU sound channel 0/1 correspond to the left/right channel of I2S RX0; APU channel 2/3 correspond
|
||||
* to left/right channels of I2S RX1; and things like that. Software write '1' to enable a sound
|
||||
* channel and hardware automatically clear the bit after the sample buffers used for direction
|
||||
* searching is filled full.
|
||||
* 0x1: writing '1' to enable the corresponding APU sound channel.
|
||||
*/
|
||||
void apu_channel_enable(uint8_t channel_bit)
|
||||
{
|
||||
apu_ch_cfg_t ch_cfg = apu->bf_ch_cfg_reg;
|
||||
|
||||
ch_cfg.we_audio_gain = 0;
|
||||
ch_cfg.we_bf_target_dir = 0;
|
||||
ch_cfg.we_data_src_mode = 0;
|
||||
ch_cfg.we_bf_sound_ch_en = 1;
|
||||
ch_cfg.bf_sound_ch_en = channel_bit;
|
||||
apu->bf_ch_cfg_reg = ch_cfg;
|
||||
}
|
||||
|
||||
/*
|
||||
* audio data source configure parameter. This parameter controls where the audio data source comes from.
|
||||
* 0x0: audio data directly sourcing from apu internal buffer;
|
||||
* 0x1: audio data sourcing from FFT result buffer.
|
||||
*/
|
||||
void apu_set_src_mode(uint8_t src_mode)
|
||||
{
|
||||
apu_ch_cfg_t ch_cfg = apu->bf_ch_cfg_reg;
|
||||
|
||||
ch_cfg.we_audio_gain = 0;
|
||||
ch_cfg.we_bf_target_dir = 0;
|
||||
ch_cfg.we_bf_sound_ch_en = 0;
|
||||
ch_cfg.we_data_src_mode = 1;
|
||||
ch_cfg.data_src_mode = src_mode;
|
||||
apu->bf_ch_cfg_reg = ch_cfg;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2S host beam-forming direction sample ibuffer read index configure register
|
||||
*/
|
||||
void apu_set_direction_delay(uint8_t dir_num, uint8_t *dir_bidx)
|
||||
{
|
||||
apu->bf_dir_bidx[dir_num][0] =(apu_dir_bidx_t)
|
||||
{
|
||||
.dir_rd_idx0 = dir_bidx[0],
|
||||
.dir_rd_idx1 = dir_bidx[1],
|
||||
.dir_rd_idx2 = dir_bidx[2],
|
||||
.dir_rd_idx3 = dir_bidx[3]
|
||||
};
|
||||
apu->bf_dir_bidx[dir_num][1] =(apu_dir_bidx_t)
|
||||
{
|
||||
.dir_rd_idx0 = dir_bidx[4],
|
||||
.dir_rd_idx1 = dir_bidx[5],
|
||||
.dir_rd_idx2 = dir_bidx[6],
|
||||
.dir_rd_idx3 = dir_bidx[7]
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* radius mic_num_a_circle: the num of mic per circle; center: 0: no center mic, 1:have center mic
|
||||
*/
|
||||
void apu_set_delay(float radius, uint8_t mic_num_a_circle, uint8_t center)
|
||||
{
|
||||
uint8_t offsets[16][8];
|
||||
int i,j;
|
||||
float seta[8], delay[8], hudu_jiao;
|
||||
float cm_tick = (float)SOUND_SPEED * 100 / I2S_FS;/*distance per tick (cm)*/
|
||||
float min;
|
||||
|
||||
for (i = 0; i < mic_num_a_circle; ++i)
|
||||
{
|
||||
seta[i] = 360 * i / mic_num_a_circle;
|
||||
hudu_jiao = 2 * M_PI * seta[i] / 360;
|
||||
delay[i] = radius * (1 - cos(hudu_jiao)) / cm_tick;
|
||||
}
|
||||
if(center)
|
||||
delay[mic_num_a_circle] = radius / cm_tick;
|
||||
|
||||
for (i = 0; i < mic_num_a_circle + center; ++i)
|
||||
{
|
||||
offsets[0][i] = (int)(delay[i] + 0.5);
|
||||
}
|
||||
for(; i < 8; i++)
|
||||
offsets[0][i] = 0;
|
||||
|
||||
|
||||
for (j = 1; j < DIRECTION_RES; ++j)
|
||||
{
|
||||
for (i = 0; i < mic_num_a_circle; ++i)
|
||||
{
|
||||
seta[i] -= 360 / DIRECTION_RES;
|
||||
hudu_jiao = 2 * M_PI * seta[i] / 360;
|
||||
delay[i] = radius * (1 - cos(hudu_jiao)) / cm_tick;
|
||||
}
|
||||
if(center)
|
||||
delay[mic_num_a_circle] = radius / cm_tick;
|
||||
|
||||
min = 2 * radius;
|
||||
for (i = 0; i < mic_num_a_circle; ++i)
|
||||
{
|
||||
if(delay[i] < min)
|
||||
min = delay[i];
|
||||
}
|
||||
if(min)
|
||||
{
|
||||
for (i = 0; i < mic_num_a_circle + center; ++i)
|
||||
{
|
||||
delay[i] = delay[i] - min;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < mic_num_a_circle + center; ++i)
|
||||
{
|
||||
offsets[j][i] = (int)(delay[i] + 0.5);
|
||||
}
|
||||
for(; i < 8; i++)
|
||||
offsets[0][i] = 0;
|
||||
}
|
||||
for (i = 0; i < DIRECTION_RES; i++)
|
||||
{
|
||||
apu_set_direction_delay(i, offsets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Sound direction searching enable bit. Software writes '1' to start sound direction searching function.
|
||||
When all the sound sample buffers are filled full, this bit is cleared by hardware (this sample buffers
|
||||
are used for direction detect only).
|
||||
0x1: enable direction searching.
|
||||
*/
|
||||
void apu_dir_enable(void)
|
||||
{
|
||||
apu_ctl_t bf_en_tmp = apu->bf_ctl_reg;
|
||||
|
||||
bf_en_tmp.we_bf_dir_search_en = 1;
|
||||
bf_en_tmp.bf_dir_search_en = 1;
|
||||
apu->bf_ctl_reg = bf_en_tmp;
|
||||
}
|
||||
|
||||
void apu_dir_reset(void)
|
||||
{
|
||||
apu_ctl_t bf_en_tmp = apu->bf_ctl_reg;
|
||||
|
||||
bf_en_tmp.we_search_path_rst = 1;
|
||||
bf_en_tmp.search_path_reset = 1;
|
||||
apu->bf_ctl_reg = bf_en_tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
Valid voice sample stream generation enable bit. After sound direction searching is done, software can
|
||||
configure this bit to generate a stream of voice samples for voice recognition.
|
||||
0x1: enable output of voice sample stream.
|
||||
0x0: stop the voice samlpe stream output.
|
||||
*/
|
||||
void apu_voc_enable(uint8_t enable_flag)
|
||||
{
|
||||
apu_ctl_t bf_en_tmp = apu->bf_ctl_reg;
|
||||
|
||||
bf_en_tmp.we_bf_stream_gen = 1;
|
||||
bf_en_tmp.bf_stream_gen_en = enable_flag;
|
||||
apu->bf_ctl_reg = bf_en_tmp;
|
||||
}
|
||||
|
||||
void apu_voc_reset(void)
|
||||
{
|
||||
apu_ctl_t bf_en_tmp = apu->bf_ctl_reg;
|
||||
|
||||
bf_en_tmp.we_voice_gen_path_rst = 1;
|
||||
bf_en_tmp.voice_gen_path_reset = 1;
|
||||
apu->bf_ctl_reg = bf_en_tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
Target direction select for valid voice output. When the source voice direaction searching
|
||||
is done, software can use this field to select one from 16 sound directions for the following
|
||||
voice recognition
|
||||
0x0: select sound direction 0; 0x1: select sound direction 1;
|
||||
. . . . . .
|
||||
0xF: select sound direction 15.
|
||||
*/
|
||||
void apu_voc_set_direction(en_bf_dir_t direction)
|
||||
{
|
||||
apu_ch_cfg_t ch_cfg = apu->bf_ch_cfg_reg;
|
||||
|
||||
ch_cfg.we_bf_sound_ch_en = 0;
|
||||
ch_cfg.we_audio_gain = 0;
|
||||
ch_cfg.we_data_src_mode = 0;
|
||||
ch_cfg.we_bf_target_dir = 1;
|
||||
ch_cfg.bf_target_dir = direction;
|
||||
apu->bf_ch_cfg_reg = ch_cfg;
|
||||
|
||||
apu_ctl_t bf_en_tmp = apu->bf_ctl_reg;
|
||||
|
||||
bf_en_tmp.we_update_voice_dir = 1;
|
||||
bf_en_tmp.update_voice_dir = 1;
|
||||
apu->bf_ctl_reg = bf_en_tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
*I2S host beam-forming Filter FIR16 Coefficient Register
|
||||
*/
|
||||
void apu_dir_set_prev_fir(uint16_t *fir_coef)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
apu->bf_pre_fir0_coef[i] =
|
||||
(apu_fir_coef_t){
|
||||
.fir_tap0 = fir_coef[i * 2],
|
||||
.fir_tap1 = i == 8 ? 0 : fir_coef[i * 2 + 1]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void apu_dir_set_post_fir(uint16_t *fir_coef)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
apu->bf_post_fir0_coef[i] =
|
||||
(apu_fir_coef_t){
|
||||
.fir_tap0 = fir_coef[i * 2],
|
||||
.fir_tap1 = i == 8 ? 0 : fir_coef[i * 2 + 1]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void apu_voc_set_prev_fir(uint16_t *fir_coef)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
apu->bf_pre_fir1_coef[i] =
|
||||
(apu_fir_coef_t){
|
||||
.fir_tap0 = fir_coef[i * 2],
|
||||
.fir_tap1 = i == 8 ? 0 : fir_coef[i * 2 + 1]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void apu_voc_set_post_fir(uint16_t *fir_coef)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
apu->bf_post_fir1_coef[i] =
|
||||
(apu_fir_coef_t){
|
||||
.fir_tap0 = fir_coef[i * 2],
|
||||
.fir_tap1 = i == 8 ? 0 : fir_coef[i * 2 + 1]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void apu_set_fft_shift_factor(uint8_t enable_flag, uint16_t shift_factor)
|
||||
{
|
||||
apu->bf_fft_cfg_reg =
|
||||
(apu_fft_cfg_t){
|
||||
.fft_enable = enable_flag,
|
||||
.fft_shift_factor = shift_factor
|
||||
};
|
||||
|
||||
apu_ch_cfg_t ch_cfg = apu->bf_ch_cfg_reg;
|
||||
|
||||
ch_cfg.we_data_src_mode = 1;
|
||||
ch_cfg.data_src_mode = enable_flag;
|
||||
apu->bf_ch_cfg_reg = ch_cfg;
|
||||
}
|
||||
|
||||
void apu_dir_set_down_size(uint8_t dir_dwn_size)
|
||||
{
|
||||
apu_dwsz_cfg_t tmp = apu->bf_dwsz_cfg_reg;
|
||||
|
||||
tmp.dir_dwn_siz_rate = dir_dwn_size;
|
||||
apu->bf_dwsz_cfg_reg = tmp;
|
||||
}
|
||||
|
||||
void apu_dir_set_interrupt_mask(uint8_t dir_int_mask)
|
||||
{
|
||||
apu_int_mask_t tmp = apu->bf_int_mask_reg;
|
||||
|
||||
tmp.dir_data_rdy_msk = dir_int_mask;
|
||||
apu->bf_int_mask_reg = tmp;
|
||||
}
|
||||
|
||||
void apu_voc_set_down_size(uint8_t voc_dwn_size)
|
||||
{
|
||||
apu_dwsz_cfg_t tmp = apu->bf_dwsz_cfg_reg;
|
||||
|
||||
tmp.voc_dwn_siz_rate = voc_dwn_size;
|
||||
apu->bf_dwsz_cfg_reg = tmp;
|
||||
}
|
||||
|
||||
void apu_voc_set_interrupt_mask(uint8_t voc_int_mask)
|
||||
{
|
||||
apu_int_mask_t tmp = apu->bf_int_mask_reg;
|
||||
|
||||
tmp.voc_buf_rdy_msk = voc_int_mask;
|
||||
apu->bf_int_mask_reg = tmp;
|
||||
}
|
||||
|
||||
void apu_set_down_size(uint8_t dir_dwn_size, uint8_t voc_dwn_size)
|
||||
{
|
||||
apu_dwsz_cfg_t tmp = apu->bf_dwsz_cfg_reg;
|
||||
|
||||
tmp.dir_dwn_siz_rate = dir_dwn_size;
|
||||
tmp.voc_dwn_siz_rate = voc_dwn_size;
|
||||
apu->bf_dwsz_cfg_reg = tmp;
|
||||
}
|
||||
|
||||
void apu_set_interrupt_mask(uint8_t dir_int_mask, uint8_t voc_int_mask)
|
||||
{
|
||||
apu->bf_int_mask_reg =
|
||||
(apu_int_mask_t){
|
||||
.dir_data_rdy_msk = dir_int_mask,
|
||||
.voc_buf_rdy_msk = voc_int_mask
|
||||
};
|
||||
}
|
||||
|
||||
void apu_dir_clear_int_state(void)
|
||||
{
|
||||
apu->bf_int_stat_reg =
|
||||
(apu_int_stat_t){
|
||||
.dir_search_data_rdy = 1
|
||||
};
|
||||
}
|
||||
|
||||
void apu_voc_clear_int_state(void)
|
||||
{
|
||||
apu->bf_int_stat_reg =
|
||||
(apu_int_stat_t){
|
||||
.voc_buf_data_rdy = 1
|
||||
};
|
||||
}
|
||||
|
||||
/* reset saturation_counter */
|
||||
void apu_voc_reset_saturation_counter(void)
|
||||
{
|
||||
apu->saturation_counter = 1<<31;
|
||||
}
|
||||
|
||||
/*get saturation counter*/
|
||||
/*heigh 16 bit is counter, low 16 bit is total.*/
|
||||
uint32_t apu_voc_get_saturation_counter(void)
|
||||
{
|
||||
return apu->saturation_counter;
|
||||
}
|
||||
|
||||
/*set saturation limit*/
|
||||
void apu_voc_set_saturation_limit(uint16_t upper, uint16_t bottom)
|
||||
{
|
||||
apu->saturation_limits = (uint32_t)bottom<<16 | upper;
|
||||
}
|
||||
|
||||
/*get saturation limit*/
|
||||
/*heigh 16 bit is counter, low 16 bit is total.*/
|
||||
uint32_t apu_voc_get_saturation_limit(void)
|
||||
{
|
||||
return apu->saturation_limits;
|
||||
}
|
||||
|
||||
static void print_fir(const char *member_name, volatile apu_fir_coef_t *pfir)
|
||||
{
|
||||
syslog(LOG_INFO," for(int i = 0; i < 9; i++){\n");
|
||||
for (int i = 0; i < 9; i++) {
|
||||
apu_fir_coef_t fir = pfir[i];
|
||||
|
||||
syslog(LOG_INFO," apu->%s[%d] = (apu_fir_coef_t){\n", member_name, i);
|
||||
syslog(LOG_INFO," .fir_tap0 = 0x%x,\n", fir.fir_tap0);
|
||||
syslog(LOG_INFO," .fir_tap1 = 0x%x\n", fir.fir_tap1);
|
||||
syslog(LOG_INFO," };\n");
|
||||
}
|
||||
syslog(LOG_INFO," }\n");
|
||||
}
|
||||
|
||||
void apu_print_setting(void)
|
||||
{
|
||||
syslog(LOG_INFO,"void apu_setting(void) {\n");
|
||||
apu_ch_cfg_t bf_ch_cfg_reg = apu->bf_ch_cfg_reg;
|
||||
|
||||
syslog(LOG_INFO," apu->bf_ch_cfg_reg = (apu_ch_cfg_t){\n");
|
||||
syslog(LOG_INFO," .we_audio_gain = 1, .we_bf_target_dir = 1, .we_bf_sound_ch_en = 1,\n");
|
||||
syslog(LOG_INFO," .audio_gain = 0x%x, .bf_target_dir = %d, .bf_sound_ch_en = %d, .data_src_mode = %d\n",
|
||||
bf_ch_cfg_reg.audio_gain, bf_ch_cfg_reg.bf_target_dir, bf_ch_cfg_reg.bf_sound_ch_en, bf_ch_cfg_reg.data_src_mode);
|
||||
syslog(LOG_INFO," };\n");
|
||||
|
||||
apu_ctl_t bf_ctl_reg = apu->bf_ctl_reg;
|
||||
|
||||
syslog(LOG_INFO," apu->bf_ctl_reg = (apu_ctl_t){\n");
|
||||
syslog(LOG_INFO," .we_bf_stream_gen = 1, .we_bf_dir_search_en = 1,\n");
|
||||
syslog(LOG_INFO," .bf_stream_gen_en = %d, .bf_dir_search_en = %d\n",
|
||||
bf_ctl_reg.bf_stream_gen_en, bf_ctl_reg.bf_dir_search_en);
|
||||
syslog(LOG_INFO," };\n");
|
||||
|
||||
syslog(LOG_INFO," for(int i = 0; i < 16; i++){\n");
|
||||
for (int i = 0; i < 16; i++) {
|
||||
apu_dir_bidx_t bidx0 = apu->bf_dir_bidx[i][0];
|
||||
apu_dir_bidx_t bidx1 = apu->bf_dir_bidx[i][1];
|
||||
|
||||
syslog(LOG_INFO," apu->bf_dir_bidx[%d][0] = (apu_dir_bidx_t){\n", i);
|
||||
syslog(LOG_INFO," .dir_rd_idx0 = 0x%x,\n", bidx0.dir_rd_idx0);
|
||||
syslog(LOG_INFO," .dir_rd_idx1 = 0x%x,\n", bidx0.dir_rd_idx1);
|
||||
syslog(LOG_INFO," .dir_rd_idx2 = 0x%x,\n", bidx0.dir_rd_idx2);
|
||||
syslog(LOG_INFO," .dir_rd_idx3 = 0x%x\n", bidx0.dir_rd_idx3);
|
||||
syslog(LOG_INFO," };\n");
|
||||
syslog(LOG_INFO," apu->bf_dir_bidx[%d][1] = (apu_dir_bidx_t){\n", i);
|
||||
syslog(LOG_INFO," .dir_rd_idx0 = 0x%x,\n", bidx1.dir_rd_idx0);
|
||||
syslog(LOG_INFO," .dir_rd_idx1 = 0x%x,\n", bidx1.dir_rd_idx1);
|
||||
syslog(LOG_INFO," .dir_rd_idx2 = 0x%x,\n", bidx1.dir_rd_idx2);
|
||||
syslog(LOG_INFO," .dir_rd_idx3 = 0x%x\n", bidx1.dir_rd_idx3);
|
||||
syslog(LOG_INFO," };\n");
|
||||
}
|
||||
syslog(LOG_INFO," }\n");
|
||||
|
||||
print_fir("bf_pre_fir0_coef", apu->bf_pre_fir0_coef);
|
||||
print_fir("bf_post_fir0_coef", apu->bf_post_fir0_coef);
|
||||
print_fir("bf_pre_fir1_coef", apu->bf_pre_fir1_coef);
|
||||
print_fir("bf_post_fir1_coef", apu->bf_post_fir1_coef);
|
||||
|
||||
|
||||
apu_dwsz_cfg_t bf_dwsz_cfg_reg = apu->bf_dwsz_cfg_reg;
|
||||
|
||||
syslog(LOG_INFO," apu->bf_dwsz_cfg_reg = (apu_dwsz_cfg_t){\n");
|
||||
syslog(LOG_INFO," .dir_dwn_siz_rate = %d, .voc_dwn_siz_rate = %d\n",
|
||||
bf_dwsz_cfg_reg.dir_dwn_siz_rate, bf_dwsz_cfg_reg.voc_dwn_siz_rate);
|
||||
syslog(LOG_INFO," };\n");
|
||||
|
||||
apu_fft_cfg_t bf_fft_cfg_reg = apu->bf_fft_cfg_reg;
|
||||
|
||||
syslog(LOG_INFO," apu->bf_fft_cfg_reg = (apu_fft_cfg_t){\n");
|
||||
syslog(LOG_INFO," .fft_enable = %d, .fft_shift_factor = 0x%x\n",
|
||||
bf_fft_cfg_reg.fft_enable, bf_fft_cfg_reg.fft_shift_factor);
|
||||
syslog(LOG_INFO," };\n");
|
||||
|
||||
apu_int_mask_t bf_int_mask_reg = apu->bf_int_mask_reg;
|
||||
|
||||
syslog(LOG_INFO," apu->bf_int_mask_reg = (apu_int_mask_t){\n");
|
||||
syslog(LOG_INFO," .dir_data_rdy_msk = %d, .voc_buf_rdy_msk = %d\n",
|
||||
bf_int_mask_reg.dir_data_rdy_msk, bf_int_mask_reg.voc_buf_rdy_msk);
|
||||
syslog(LOG_INFO," };\n");
|
||||
|
||||
syslog(LOG_INFO,"}\n");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,571 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file apu.h
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _apu_H_
|
||||
#define _apu_H_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DIRECTION_RES 16
|
||||
#define I2S_FS 44100
|
||||
#define SOUND_SPEED 340
|
||||
|
||||
typedef enum en_bf_dir
|
||||
{
|
||||
APU_DIR0 = 0,
|
||||
APU_DIR1,
|
||||
APU_DIR2,
|
||||
APU_DIR3,
|
||||
APU_DIR4,
|
||||
APU_DIR5,
|
||||
APU_DIR6,
|
||||
APU_DIR7,
|
||||
APU_DIR8,
|
||||
APU_DIR9,
|
||||
APU_DIR10,
|
||||
APU_DIR11,
|
||||
APU_DIR12,
|
||||
APU_DIR13,
|
||||
APU_DIR14,
|
||||
APU_DIR15,
|
||||
} en_bf_dir_t;
|
||||
|
||||
typedef struct _apu_ch_cfg
|
||||
{
|
||||
/**
|
||||
* BF unit sound channel enable control bits.
|
||||
* Bit 'x' corresponds to enable bit for sound channel 'x' (x = 0, 1, 2,
|
||||
* . . ., 7). BF sound channels are related with I2S host RX channels.
|
||||
* BF sound channel 0/1 correspond to the left/right channel of I2S RX0;
|
||||
* BF channel 2/3 correspond to left/right channels of I2S RX1; and
|
||||
* things like that. 0x1: writing '1' to enable the corresponding BF
|
||||
* sound channel. 0x0: writing '0' to close the corresponding BF sound
|
||||
* channel.
|
||||
*/
|
||||
uint32_t bf_sound_ch_en : 8;
|
||||
/**
|
||||
* Target direction select for valid voice output.
|
||||
* When the source voice direaction searching is done, software can use
|
||||
* this field to select one from 16 sound directions for the following
|
||||
* voice recognition. 0x0: select sound direction 0; 0x1: select sound
|
||||
* direction 1; . . . . . . 0xF: select sound direction 15.
|
||||
*/
|
||||
uint32_t bf_target_dir : 4;
|
||||
/**
|
||||
* This is the audio sample gain factor. Using this gain factor to
|
||||
* enhance or reduce the stength of the sum of at most 8 source
|
||||
* sound channel outputs. This is a unsigned 11-bit fix-point number,
|
||||
* bit 10 is integer part and bit 9~0 are the fractional part.
|
||||
*/
|
||||
uint32_t audio_gain : 11;
|
||||
uint32_t reserved1 : 1;
|
||||
/**
|
||||
* audio data source configure parameter. This parameter controls where
|
||||
* the audio data source comes from. 0x0: audio data directly sourcing
|
||||
* from apu internal buffer; 0x1: audio data sourcing from
|
||||
* FFT result buffer.
|
||||
*/
|
||||
uint32_t data_src_mode : 1;
|
||||
uint32_t reserved2 : 3;
|
||||
/**
|
||||
* write enable for bf_sound_ch_en parameter.
|
||||
* 0x1: allowing updates made to 'bf_sound_ch_en'.
|
||||
* Access Mode: write only
|
||||
*/
|
||||
uint32_t we_bf_sound_ch_en : 1;
|
||||
/**
|
||||
* write enable for bf_target_dir parameter.
|
||||
* 0x1: allowing updates made to 'bf_target_dir'.
|
||||
* Access Mode: write only
|
||||
*/
|
||||
uint32_t we_bf_target_dir : 1;
|
||||
/**
|
||||
* write enable for audio_gain parameter.
|
||||
* 0x1: allowing updates made to 'audio_gain'.
|
||||
* Access Mode: write only
|
||||
*/
|
||||
uint32_t we_audio_gain : 1;
|
||||
/**
|
||||
* write enable for data_out_mode parameter.
|
||||
* 0x1: allowing updates made to 'data_src_mode'.
|
||||
*/
|
||||
uint32_t we_data_src_mode : 1;
|
||||
} __attribute__((packed, aligned(4))) apu_ch_cfg_t;
|
||||
|
||||
typedef struct _apu_ctl_t
|
||||
{
|
||||
/**
|
||||
* Sound direction searching enable bit.
|
||||
* Software writes '1' to start sound direction searching function.
|
||||
* When all the sound sample buffers are filled full, this bit is
|
||||
* cleared by hardware (this sample buffers are used for direction
|
||||
* detect only). 0x1: enable direction searching.
|
||||
*/
|
||||
uint32_t bf_dir_search_en : 1;
|
||||
/*
|
||||
*use this parameter to reset all the control logic on direction search processing path. This bit is self-clearing.
|
||||
* 0x1: apply reset to direction searching control logic;
|
||||
* 0x0: No operation.
|
||||
*/
|
||||
uint32_t search_path_reset : 1;
|
||||
uint32_t reserved : 2;
|
||||
/**
|
||||
* Valid voice sample stream generation enable bit.
|
||||
* After sound direction searching is done, software can configure this
|
||||
* bit to generate a stream of voice samples for voice recognition. 0x1:
|
||||
* enable output of voice sample stream. 0x0: stop the voice samlpe
|
||||
* stream output.
|
||||
*/
|
||||
uint32_t bf_stream_gen_en : 1;
|
||||
/*
|
||||
*use this parameter to reset all the control logic on voice stream generating path. This bit is self-clearing.
|
||||
* 0x1: apply reset to voice stream generating control logic;
|
||||
* 0x0: No operation.
|
||||
*/
|
||||
uint32_t voice_gen_path_reset : 1;
|
||||
/*
|
||||
*use this parameter to switch to a new voice source direction. Software write '1' here and hardware will automatically clear it.
|
||||
* 0x1: write '1' here to request switching to new voice source direction.
|
||||
*/
|
||||
uint32_t update_voice_dir : 1;
|
||||
|
||||
uint32_t reserved1 : 1;
|
||||
//write enable for 'bf_dir_search_en' parameter.
|
||||
uint32_t we_bf_dir_search_en : 1;
|
||||
uint32_t we_search_path_rst : 1;
|
||||
uint32_t we_bf_stream_gen : 1;
|
||||
uint32_t we_voice_gen_path_rst : 1;
|
||||
uint32_t we_update_voice_dir : 1;
|
||||
uint32_t reserved2 : 19;
|
||||
|
||||
} __attribute__((packed, aligned(4))) apu_ctl_t;
|
||||
|
||||
typedef struct _apu_dir_bidx
|
||||
{
|
||||
uint32_t dir_rd_idx0 : 6;
|
||||
uint32_t reserved : 2;
|
||||
uint32_t dir_rd_idx1 : 6;
|
||||
uint32_t reserved1 : 2;
|
||||
uint32_t dir_rd_idx2 : 6;
|
||||
uint32_t reserved2 : 2;
|
||||
uint32_t dir_rd_idx3 : 6;
|
||||
uint32_t reserved3 : 2;
|
||||
} __attribute__((packed, aligned(4))) apu_dir_bidx_t;
|
||||
|
||||
typedef struct _apu_fir_coef
|
||||
{
|
||||
uint32_t fir_tap0 : 16;
|
||||
uint32_t fir_tap1 : 16;
|
||||
} __attribute__((packed, aligned(4))) apu_fir_coef_t;
|
||||
|
||||
typedef struct _apu_dwsz_cfg
|
||||
{
|
||||
/**
|
||||
* The down-sizing ratio used for direction searching.
|
||||
* 0x0: no down-sizing;
|
||||
* 0x1: 1/2 down sizing;
|
||||
* 0x2: 1/3 down sizing;
|
||||
* . . . . . .
|
||||
* 0xF: 1/16 down sizing.
|
||||
*/
|
||||
uint32_t dir_dwn_siz_rate : 4;
|
||||
/**
|
||||
* The down-sizing ratio used for voice stream generation.
|
||||
* 0x0: no down-sizing;
|
||||
* 0x1: 1/2 down sizing;
|
||||
* 0x2: 1/3 down sizing;
|
||||
* . . . . . .
|
||||
* 0xF: 1/16 down sizing.
|
||||
*/
|
||||
uint32_t voc_dwn_siz_rate : 4;
|
||||
/**
|
||||
* This bit field is used to perform sample precision reduction when
|
||||
* the source sound sample (from I2S0 host receiving channels)
|
||||
* precision is 20/24/32 bits.
|
||||
* 0x0: take bits 15~0 from the source sound sample;
|
||||
* 0x1: take bits 16~1 from the source sound sample;
|
||||
* 0x2: take bits 17~2 from the source sound sample;
|
||||
* . . . . . .
|
||||
* 0x10: take bits 31~16 from the source sound sample;
|
||||
*/
|
||||
uint32_t smpl_shift_bits : 5;
|
||||
uint32_t reserved : 19;
|
||||
} __attribute__((packed, aligned(4))) apu_dwsz_cfg_t;
|
||||
|
||||
/*0x31c*/
|
||||
typedef struct _apu_fft_cfg
|
||||
{
|
||||
uint32_t fft_shift_factor : 9;
|
||||
uint32_t reserved1 : 3;
|
||||
uint32_t fft_enable : 1;
|
||||
uint32_t reserved2 : 19;
|
||||
} __attribute__((packed, aligned(4))) apu_fft_cfg_t;
|
||||
|
||||
/*0x328*/
|
||||
typedef struct _apu_int_stat
|
||||
{
|
||||
/**
|
||||
* sound direction searching data ready interrupt event.
|
||||
* Writing '1' to clear this interrupt event.
|
||||
* 0x1: data is ready for sound direction detect;
|
||||
* 0x0: no event.
|
||||
*/
|
||||
uint32_t dir_search_data_rdy : 1;
|
||||
/**
|
||||
* voice output stream buffer data ready interrupt event.
|
||||
* When a block of 512 voice samples are collected, this interrupt event
|
||||
* is asserted. Writing '1' to clear this interrupt event. 0x1: voice
|
||||
* output stream buffer data is ready; 0x0: no event.
|
||||
*/
|
||||
uint32_t voc_buf_data_rdy : 1;
|
||||
uint32_t reserved : 30;
|
||||
} __attribute__((packed, aligned(4))) apu_int_stat_t;
|
||||
|
||||
/*0x32c*/
|
||||
typedef struct _apu_int_mask
|
||||
{
|
||||
/**
|
||||
* This is the interrupt mask to dir searching data ready interrupt.
|
||||
* 0x1: mask off this interrupt;
|
||||
* 0x0: enable this interrupt.
|
||||
*/
|
||||
uint32_t dir_data_rdy_msk : 1;
|
||||
/**
|
||||
* This is the interrupt mask to voice output stream buffer ready
|
||||
* interrupt. 0x1: mask off this interrupt; 0x0: enable this interrupt.
|
||||
*/
|
||||
uint32_t voc_buf_rdy_msk : 1;
|
||||
uint32_t reserved : 30;
|
||||
} __attribute__((packed, aligned(4))) apu_int_mask_t;
|
||||
|
||||
typedef struct _apu_reg
|
||||
{
|
||||
//0x200
|
||||
apu_ch_cfg_t bf_ch_cfg_reg;
|
||||
//0x204
|
||||
apu_ctl_t bf_ctl_reg;
|
||||
//0x208
|
||||
apu_dir_bidx_t bf_dir_bidx[16][2];
|
||||
//0x288
|
||||
apu_fir_coef_t bf_pre_fir0_coef[9];
|
||||
//0x2ac
|
||||
apu_fir_coef_t bf_post_fir0_coef[9];
|
||||
//0x2d0
|
||||
apu_fir_coef_t bf_pre_fir1_coef[9];
|
||||
//0x2f4
|
||||
apu_fir_coef_t bf_post_fir1_coef[9];
|
||||
//0x318
|
||||
apu_dwsz_cfg_t bf_dwsz_cfg_reg;
|
||||
//0x31c
|
||||
apu_fft_cfg_t bf_fft_cfg_reg;
|
||||
// 0x320
|
||||
/**
|
||||
* This is the read register for system DMA to read data stored in
|
||||
* sample out buffers (the sample out buffers are used for sound
|
||||
* direction detect). Each data contains two sound samples.
|
||||
*/
|
||||
volatile uint32_t sobuf_dma_rdata;
|
||||
// 0x324
|
||||
/**
|
||||
* This is the read register for system DMA to read data stored in voice
|
||||
* out buffers (the voice out buffers are used for voice recognition).
|
||||
* Each data contains two sound samples.
|
||||
*/
|
||||
volatile uint32_t vobuf_dma_rdata;
|
||||
/*0x328*/
|
||||
apu_int_stat_t bf_int_stat_reg;
|
||||
/*0x32c*/
|
||||
apu_int_mask_t bf_int_mask_reg;
|
||||
/*0x330*/
|
||||
uint32_t saturation_counter;
|
||||
/*0x334*/
|
||||
uint32_t saturation_limits;
|
||||
} __attribute__((packed, aligned(4))) apu_reg_t;
|
||||
|
||||
extern volatile apu_reg_t *const apu;
|
||||
|
||||
/**
|
||||
* @brief Voice strength average value right shift factor. When performing sound direction detect,
|
||||
* the average value of samples from different channels is required, this right shift factor
|
||||
* is used to perform division.
|
||||
*
|
||||
* @param[in] gain value of audio gain.
|
||||
* 0x0: no right shift;
|
||||
* 0x1: right shift by 1-bit;
|
||||
* . . . . . .
|
||||
* 0xF: right shift by 15-bit.
|
||||
*
|
||||
*/
|
||||
void apu_set_audio_gain(uint16_t gain);
|
||||
|
||||
/**
|
||||
* @brief Set sampling shift.
|
||||
*
|
||||
* @param[in] smpl_shift vlaue of sampling shift
|
||||
*
|
||||
*/
|
||||
void apu_set_smpl_shift(uint8_t smpl_shift);
|
||||
|
||||
/**
|
||||
* @brief Get sampling shift
|
||||
*
|
||||
* @return vlaue of sampling shift
|
||||
*/
|
||||
uint8_t apu_get_smpl_shift(void);
|
||||
|
||||
/**
|
||||
* @brief APU unit sound channel enable control bits. Bit 'x' corresponds to enable bit for sound
|
||||
* channel 'x' (x = 0, 1, 2, . . ., 7). APU sound channels are related with I2S host RX channels.
|
||||
* APU sound channel 0/1 correspond to the left/right channel of I2S RX0; APU channel 2/3 correspond
|
||||
* to left/right channels of I2S RX1; and things like that. Software write '1' to enable a sound
|
||||
* channel and hardware automatically clear the bit after the sample buffers used for direction
|
||||
* searching is filled full.
|
||||
*
|
||||
*
|
||||
* @param[in] channel_bit APU sound channel.0x1: writing
|
||||
* '1' to enable the corresponding APU sound channel.
|
||||
*
|
||||
*/
|
||||
void apu_set_channel_enabled(uint8_t channel_bit);
|
||||
|
||||
/**
|
||||
* @brief I2S host beam-forming direction sample ibuffer read index configure register
|
||||
*
|
||||
* @param[in] dir_num the direction of index
|
||||
* @param[in] dir_bidx
|
||||
*
|
||||
*/
|
||||
void apu_set_direction_delay(uint8_t dir_num, uint8_t *dir_bidx);
|
||||
|
||||
/**
|
||||
* @brief I2S host beam-forming direction sample ibuffer read index configure register
|
||||
*
|
||||
* @param[in] radius radius
|
||||
* @param[in] mic_num_a_circle the num of mic per circle
|
||||
* @param[in] center 0: no center mic, 1:have center mic
|
||||
*
|
||||
*/
|
||||
void apu_set_delay(float radius, uint8_t mic_num_a_circle, uint8_t center);
|
||||
|
||||
/**
|
||||
* @brief Set ffp shift factor
|
||||
*
|
||||
* @param[in] enable_flag enable fft
|
||||
* @param[in] shift_factor shift factor
|
||||
*
|
||||
*/
|
||||
void apu_set_fft_shift_factor(uint8_t enable_flag, uint16_t shift_factor);
|
||||
|
||||
/**
|
||||
* @brief Set down-sizing ratio used for voice direction searching and voice stream generation.
|
||||
*
|
||||
* @param[in] dir_dwn_siz down-sizing ratio used for voice direction searching
|
||||
* 0x0: no down-sizing
|
||||
* 0x1: 1/2 down sizing
|
||||
* 0x2: 1/3 down sizing
|
||||
* . . . . . .
|
||||
* 0xF: 1/16 down sizing
|
||||
* @param[in] voc_dwn_siz down-sizing ratio used for voice stream generation
|
||||
* 0x0: no down-sizing
|
||||
* 0x1: 1/2 down sizing
|
||||
* 0x2: 1/3 down sizing
|
||||
* . . . . . .
|
||||
* 0xF: 1/16 down sizing
|
||||
*/
|
||||
void apu_set_down_size(uint8_t dir_dwn_siz, uint8_t voc_dwn_siz);
|
||||
|
||||
/**
|
||||
* @brief Set direction and voice interrupt mask
|
||||
*
|
||||
* @param[in] dir_int_mask direction interrupt mask
|
||||
* @param[in] voc_int_mask voice interrupt mask
|
||||
*
|
||||
*/
|
||||
void apu_set_interrupt_mask(uint8_t dir_int_mask, uint8_t voc_int_mask);
|
||||
|
||||
/**
|
||||
* @brief Enable direction searching.
|
||||
*
|
||||
*/
|
||||
void apu_dir_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Reset direction searching.
|
||||
*
|
||||
*/
|
||||
void apu_dir_reset(void);
|
||||
|
||||
/**
|
||||
* @brief I2S host beam-forming Filter FIR16 Coefficient Register
|
||||
*
|
||||
* @param[in] fir_coef direction prev FIR
|
||||
*
|
||||
*/
|
||||
void apu_dir_set_prev_fir(uint16_t *fir_coef);
|
||||
|
||||
/**
|
||||
* @brief I2S host beam-forming Filter FIR16 Coefficient Register
|
||||
*
|
||||
* @param[in] fir_coef direction post FIR
|
||||
*
|
||||
*/
|
||||
void apu_dir_set_post_fir(uint16_t *fir_coef);
|
||||
|
||||
/**
|
||||
* @brief Set down-sizing ratio used for voice direction searching
|
||||
*
|
||||
* @param[in] dir_dwn_siz down-sizing ratio used for voice direction searching
|
||||
* 0x0: no down-sizing
|
||||
* 0x1: 1/2 down sizing
|
||||
* 0x2: 1/3 down sizing
|
||||
* . . . . . .
|
||||
* 0xF: 1/16 down sizing
|
||||
*/
|
||||
void apu_dir_set_down_size(uint8_t dir_dwn_size);
|
||||
|
||||
/**
|
||||
* @brief Set direction searching interrupt mask
|
||||
*
|
||||
* @param[in] dir_int_mask direction interrupt mask
|
||||
*
|
||||
*/
|
||||
void apu_dir_set_interrupt_mask(uint8_t dir_int_mask);
|
||||
|
||||
/**
|
||||
* @brief Clear direction interrupt
|
||||
*
|
||||
*/
|
||||
void apu_dir_clear_int_state(void);
|
||||
|
||||
/**
|
||||
* @brief Valid voice sample stream generation enable bit. After sound direction searching is done, software can
|
||||
* configure this bit to generate a stream of voice samples for voice recognition.
|
||||
*
|
||||
* @param[in] enable_flag 0x1: enable output of voice sample stream. 0x0: stop the voice samlpe stream output.
|
||||
*
|
||||
*/
|
||||
void apu_voc_enable(uint8_t enable_flag);
|
||||
|
||||
/**
|
||||
* @brief Reset voice sample
|
||||
*
|
||||
*/
|
||||
void apu_voc_reset(void);
|
||||
|
||||
/**
|
||||
* @brief Target direction select for valid voice output. When the source voice direaction searching
|
||||
* is done, software can use this field to select one from 16 sound directions for the following
|
||||
* voice recognition
|
||||
*
|
||||
* @param[in] direction 0x0: select sound direction 0;
|
||||
* 0x1: select sound direction 1;
|
||||
* . . . . . .
|
||||
* 0xF: select sound direction 15.
|
||||
*/
|
||||
void apu_voc_set_direction(en_bf_dir_t direction);
|
||||
|
||||
/**
|
||||
* @brief I2S host beam-forming Filter FIR16 Coefficient Register
|
||||
*
|
||||
* @param[in] fir_coef voice prev FIR
|
||||
*
|
||||
*/
|
||||
void apu_voc_set_prev_fir(uint16_t *fir_coef);
|
||||
|
||||
/**
|
||||
* @brief I2S host beam-forming Filter FIR16 Coefficient Register
|
||||
*
|
||||
* @param[in] fir_coef voice post FIR
|
||||
*
|
||||
*/
|
||||
void apu_voc_set_post_fir(uint16_t *fir_coef);
|
||||
|
||||
/**
|
||||
* @brief Set down-sizing ratio used for voice stream generation.
|
||||
*
|
||||
* @param[in] voc_dwn_siz down-sizing ratio used for voice stream generation
|
||||
* 0x0: no down-sizing
|
||||
* 0x1: 1/2 down sizing
|
||||
* 0x2: 1/3 down sizing
|
||||
* . . . . . .
|
||||
* 0xF: 1/16 down sizing
|
||||
*/
|
||||
void apu_voc_set_down_size(uint8_t voc_dwn_size);
|
||||
|
||||
/**
|
||||
* @brief Set voice stream generation interrupt mask
|
||||
*
|
||||
* @param[in] voc_int_mask voice interrupt mask
|
||||
*
|
||||
*/
|
||||
void apu_voc_set_interrupt_mask(uint8_t voc_int_mask);
|
||||
|
||||
/**
|
||||
* @brief Clear voice interrupt
|
||||
*
|
||||
*/
|
||||
void apu_voc_clear_int_state(void);
|
||||
|
||||
/**
|
||||
* @brief Reset saturation_counter
|
||||
*
|
||||
*/
|
||||
void apu_voc_reset_saturation_counter(void);
|
||||
|
||||
/**
|
||||
* @brief Get saturation counter
|
||||
*
|
||||
* @return vlaue of saturation counter.heigh 16 bit is counter, low 16 bit is total
|
||||
*/
|
||||
uint32_t apu_voc_get_saturation_counter(void);
|
||||
|
||||
/**
|
||||
* @brief set saturation limit
|
||||
*
|
||||
* @param[in] upper heigh 16 bit is counter
|
||||
* @param[in] bottom low 16 bit is total
|
||||
*
|
||||
*/
|
||||
void apu_voc_set_saturation_limit(uint16_t upper, uint16_t bottom);
|
||||
|
||||
/**
|
||||
* @brief Get saturation limit
|
||||
*
|
||||
* @return vlaue of saturation limit.heigh 16 bit is counter, low 16 bit is total
|
||||
*/
|
||||
uint32_t apu_voc_get_saturation_limit(void);
|
||||
|
||||
/**
|
||||
* @brief Print apu setting for debug
|
||||
*
|
||||
*/
|
||||
void apu_print_setting(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,254 @@
|
||||
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file atomic.h
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#ifndef _BSP_ATOMIC_H
|
||||
#define _BSP_ATOMIC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define SPINLOCK_INIT \
|
||||
{ \
|
||||
0 \
|
||||
}
|
||||
|
||||
#define CORELOCK_INIT \
|
||||
{ \
|
||||
.lock = SPINLOCK_INIT, \
|
||||
.count = 0, \
|
||||
.core = -1 \
|
||||
}
|
||||
|
||||
|
||||
/* Defination of memory barrier macro */
|
||||
#define mb() \
|
||||
{ \
|
||||
asm volatile("fence" :: \
|
||||
: "memory"); \
|
||||
}
|
||||
|
||||
#define atomic_set(ptr, val) (*(volatile typeof(*(ptr))*)(ptr) = val)
|
||||
#define atomic_read(ptr) (*(volatile typeof(*(ptr))*)(ptr))
|
||||
|
||||
#ifndef __riscv_atomic
|
||||
#error "atomic extension is required."
|
||||
#endif
|
||||
#define atomic_add(ptr, inc) __sync_fetch_and_add(ptr, inc)
|
||||
#define atomic_or(ptr, inc) __sync_fetch_and_or(ptr, inc)
|
||||
#define atomic_swap(ptr, swp) __sync_lock_test_and_set(ptr, swp)
|
||||
#define atomic_cas(ptr, cmp, swp) __sync_val_compare_and_swap(ptr, cmp, swp)
|
||||
|
||||
typedef struct _spinlock
|
||||
{
|
||||
int lock;
|
||||
} spinlock_t;
|
||||
|
||||
typedef struct _semaphore
|
||||
{
|
||||
spinlock_t lock;
|
||||
int count;
|
||||
int waiting;
|
||||
} semaphore_t;
|
||||
|
||||
|
||||
typedef struct _corelock
|
||||
{
|
||||
spinlock_t lock;
|
||||
int count;
|
||||
int core;
|
||||
} corelock_t;
|
||||
|
||||
static inline int spinlock_trylock(spinlock_t *lock)
|
||||
{
|
||||
int res = atomic_swap(&lock->lock, -1);
|
||||
/* Use memory barrier to keep coherency */
|
||||
mb();
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline void spinlock_lock(spinlock_t *lock)
|
||||
{
|
||||
while (spinlock_trylock(lock));
|
||||
}
|
||||
|
||||
static inline void spinlock_unlock(spinlock_t *lock)
|
||||
{
|
||||
/* Use memory barrier to keep coherency */
|
||||
mb();
|
||||
atomic_set(&lock->lock, 0);
|
||||
asm volatile ("nop");
|
||||
}
|
||||
|
||||
static inline void semaphore_signal(semaphore_t *semaphore, int i)
|
||||
{
|
||||
spinlock_lock(&(semaphore->lock));
|
||||
semaphore->count += i;
|
||||
spinlock_unlock(&(semaphore->lock));
|
||||
}
|
||||
|
||||
static inline void semaphore_wait(semaphore_t *semaphore, int i)
|
||||
{
|
||||
atomic_add(&(semaphore->waiting), 1);
|
||||
while (1)
|
||||
{
|
||||
spinlock_lock(&(semaphore->lock));
|
||||
if (semaphore->count >= i)
|
||||
{
|
||||
semaphore->count -= i;
|
||||
atomic_add(&(semaphore->waiting), -1);
|
||||
spinlock_unlock(&(semaphore->lock));
|
||||
break;
|
||||
}
|
||||
spinlock_unlock(&(semaphore->lock));
|
||||
}
|
||||
}
|
||||
|
||||
static inline int semaphore_count(semaphore_t *semaphore)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
spinlock_lock(&(semaphore->lock));
|
||||
res = semaphore->count;
|
||||
spinlock_unlock(&(semaphore->lock));
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int semaphore_waiting(semaphore_t *semaphore)
|
||||
{
|
||||
return atomic_read(&(semaphore->waiting));
|
||||
}
|
||||
|
||||
static inline int corelock_trylock(corelock_t *lock)
|
||||
{
|
||||
int res = 0;
|
||||
unsigned long core;
|
||||
|
||||
asm volatile("csrr %0, mhartid;"
|
||||
: "=r"(core));
|
||||
if(spinlock_trylock(&lock->lock))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lock->count == 0)
|
||||
{
|
||||
/* First time get lock */
|
||||
lock->count++;
|
||||
lock->core = core;
|
||||
res = 0;
|
||||
}
|
||||
else if (lock->core == core)
|
||||
{
|
||||
/* Same core get lock */
|
||||
lock->count++;
|
||||
res = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Different core get lock */
|
||||
res = -1;
|
||||
}
|
||||
spinlock_unlock(&lock->lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline void corelock_lock(corelock_t *lock)
|
||||
{
|
||||
unsigned long core;
|
||||
|
||||
asm volatile("csrr %0, mhartid;"
|
||||
: "=r"(core));
|
||||
spinlock_lock(&lock->lock);
|
||||
|
||||
if (lock->count == 0)
|
||||
{
|
||||
/* First time get lock */
|
||||
lock->count++;
|
||||
lock->core = core;
|
||||
}
|
||||
else if (lock->core == core)
|
||||
{
|
||||
/* Same core get lock */
|
||||
lock->count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Different core get lock */
|
||||
spinlock_unlock(&lock->lock);
|
||||
|
||||
do
|
||||
{
|
||||
while (atomic_read(&lock->count))
|
||||
;
|
||||
} while (corelock_trylock(lock));
|
||||
return;
|
||||
}
|
||||
spinlock_unlock(&lock->lock);
|
||||
}
|
||||
|
||||
static inline void corelock_unlock(corelock_t *lock)
|
||||
{
|
||||
unsigned long core;
|
||||
|
||||
asm volatile("csrr %0, mhartid;"
|
||||
: "=r"(core));
|
||||
spinlock_lock(&lock->lock);
|
||||
|
||||
if (lock->core == core)
|
||||
{
|
||||
/* Same core release lock */
|
||||
lock->count--;
|
||||
if (lock->count <= 0)
|
||||
{
|
||||
lock->core = -1;
|
||||
lock->count = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Different core release lock */
|
||||
spinlock_unlock(&lock->lock);
|
||||
|
||||
register unsigned long a7 asm("a7") = 93;
|
||||
register unsigned long a0 asm("a0") = 0;
|
||||
register unsigned long a1 asm("a1") = 0;
|
||||
register unsigned long a2 asm("a2") = 0;
|
||||
|
||||
asm volatile("scall"
|
||||
: "+r"(a0)
|
||||
: "r"(a1), "r"(a2), "r"(a7));
|
||||
}
|
||||
spinlock_unlock(&lock->lock);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BSP_ATOMIC_H */
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @file bsp.h
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#ifndef _KENDRYTE_BSP_H
|
||||
#define _KENDRYTE_BSP_H
|
||||
#include "atomic.h"
|
||||
#include "encoding.h"
|
||||
#endif
|
||||
@@ -0,0 +1,271 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file clint.c
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "encoding.h"
|
||||
#include "clint.h"
|
||||
#include "sysctl.h"
|
||||
|
||||
volatile clint_t* const clint = (volatile clint_t*)CLINT_BASE_ADDR;
|
||||
static clint_timer_instance_t clint_timer_instance[CLINT_NUM_CORES];
|
||||
static clint_ipi_instance_t clint_ipi_instance[CLINT_NUM_CORES];
|
||||
|
||||
uint64_t clint_get_time(void)
|
||||
{
|
||||
/* No difference on cores */
|
||||
return clint->mtime;
|
||||
}
|
||||
|
||||
int clint_timer_init(void)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Clear the Machine-Timer bit in MIE */
|
||||
clear_csr(mie, MIP_MTIP);
|
||||
/* Fill core's instance with original data */
|
||||
|
||||
/* clang-format off */
|
||||
clint_timer_instance[core_id] = (const clint_timer_instance_t)
|
||||
{
|
||||
.interval = 0,
|
||||
.cycles = 0,
|
||||
.single_shot = 0,
|
||||
.callback = NULL,
|
||||
.ctx = NULL,
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_timer_stop(void)
|
||||
{
|
||||
/* Clear the Machine-Timer bit in MIE */
|
||||
clear_csr(mie, MIP_MTIP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t clint_timer_get_freq(void)
|
||||
{
|
||||
/* The clock is divided by CLINT_CLOCK_DIV */
|
||||
return sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / CLINT_CLOCK_DIV;
|
||||
}
|
||||
|
||||
int clint_timer_start(uint64_t interval, int single_shot)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Set timer interval */
|
||||
if (clint_timer_set_interval(interval) != 0)
|
||||
return -1;
|
||||
/* Set timer single shot */
|
||||
if (clint_timer_set_single_shot(single_shot) != 0)
|
||||
return -1;
|
||||
/* Check settings to prevent interval is 0 */
|
||||
if (clint_timer_instance[core_id].interval == 0)
|
||||
return -1;
|
||||
/* Check settings to prevent cycles is 0 */
|
||||
if (clint_timer_instance[core_id].cycles == 0)
|
||||
return -1;
|
||||
/* Add cycle interval to mtimecmp */
|
||||
uint64_t now = clint->mtime;
|
||||
uint64_t then = now + clint_timer_instance[core_id].cycles;
|
||||
/* Set mtimecmp by core id */
|
||||
clint->mtimecmp[core_id] = then;
|
||||
/* Enable interrupts in general */
|
||||
set_csr(mstatus, MSTATUS_MIE);
|
||||
/* Enable the Machine-Timer bit in MIE */
|
||||
set_csr(mie, MIP_MTIP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t clint_timer_get_interval(void)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
return clint_timer_instance[core_id].interval;
|
||||
}
|
||||
|
||||
int clint_timer_set_interval(uint64_t interval)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Check parameter */
|
||||
if (interval == 0)
|
||||
return -1;
|
||||
|
||||
/* Assign user interval with Millisecond(ms) */
|
||||
clint_timer_instance[core_id].interval = interval;
|
||||
/* Convert interval to cycles */
|
||||
clint_timer_instance[core_id].cycles = interval * clint_timer_get_freq() / 1000ULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_timer_get_single_shot(void)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Get single shot mode by core id */
|
||||
return clint_timer_instance[core_id].single_shot;
|
||||
}
|
||||
|
||||
int clint_timer_set_single_shot(int single_shot)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Set single shot mode by core id */
|
||||
clint_timer_instance[core_id].single_shot = single_shot;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_timer_register(clint_timer_callback_t callback, void *ctx)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Set user callback function */
|
||||
clint_timer_instance[core_id].callback = callback;
|
||||
/* Assign user context */
|
||||
clint_timer_instance[core_id].ctx = ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_timer_unregister(void)
|
||||
{
|
||||
/* Just assign NULL to user callback function and context */
|
||||
return clint_timer_register(NULL, NULL);
|
||||
}
|
||||
|
||||
int clint_ipi_init(void)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Clear the Machine-Software bit in MIE */
|
||||
clear_csr(mie, MIP_MSIP);
|
||||
/* Fill core's instance with original data */
|
||||
/* clang-format off */
|
||||
clint_ipi_instance[core_id] = (const clint_ipi_instance_t){
|
||||
.callback = NULL,
|
||||
.ctx = NULL,
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_ipi_enable(void)
|
||||
{
|
||||
/* Enable interrupts in general */
|
||||
set_csr(mstatus, MSTATUS_MIE);
|
||||
/* Set the Machine-Software bit in MIE */
|
||||
set_csr(mie, MIP_MSIP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_ipi_disable(void)
|
||||
{
|
||||
/* Clear the Machine-Software bit in MIE */
|
||||
clear_csr(mie, MIP_MSIP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_ipi_send(size_t core_id)
|
||||
{
|
||||
if (core_id >= CLINT_NUM_CORES)
|
||||
return -1;
|
||||
clint->msip[core_id].msip = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_ipi_clear(size_t core_id)
|
||||
{
|
||||
if (core_id >= CLINT_NUM_CORES)
|
||||
return -1;
|
||||
if (clint->msip[core_id].msip)
|
||||
{
|
||||
clint->msip[core_id].msip = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_ipi_register(clint_ipi_callback_t callback, void *ctx)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Set user callback function */
|
||||
clint_ipi_instance[core_id].callback = callback;
|
||||
/* Assign user context */
|
||||
clint_ipi_instance[core_id].ctx = ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_ipi_unregister(void)
|
||||
{
|
||||
/* Just assign NULL to user callback function and context */
|
||||
return clint_ipi_register(NULL, NULL);
|
||||
}
|
||||
|
||||
uintptr_t handle_irq_m_timer(uintptr_t cause, uintptr_t epc)
|
||||
{
|
||||
/* Read core id */
|
||||
uint64_t core_id = current_coreid();
|
||||
uint64_t ie_flag = read_csr(mie);
|
||||
|
||||
clear_csr(mie, MIP_MTIP | MIP_MSIP);
|
||||
set_csr(mstatus, MSTATUS_MIE);
|
||||
if (clint_timer_instance[core_id].callback != NULL)
|
||||
clint_timer_instance[core_id].callback(
|
||||
clint_timer_instance[core_id].ctx);
|
||||
clear_csr(mstatus, MSTATUS_MIE);
|
||||
set_csr(mstatus, MSTATUS_MPIE | MSTATUS_MPP);
|
||||
write_csr(mie, ie_flag);
|
||||
/* If not single shot and cycle interval is not 0, repeat this timer */
|
||||
if (!clint_timer_instance[core_id].single_shot && clint_timer_instance[core_id].cycles != 0)
|
||||
{
|
||||
/* Set mtimecmp by core id */
|
||||
clint->mtimecmp[core_id] += clint_timer_instance[core_id].cycles;
|
||||
}
|
||||
else
|
||||
clear_csr(mie, MIP_MTIP);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t handle_irq_m_soft(uintptr_t cause, uintptr_t epc)
|
||||
{
|
||||
/* Read core id */
|
||||
uint64_t core_id = current_coreid();
|
||||
/* Clear the Machine-Software bit in MIE to prevent call again */
|
||||
clear_csr(mie, MIP_MSIP);
|
||||
set_csr(mstatus, MSTATUS_MIE);
|
||||
/* Clear ipi flag */
|
||||
clint_ipi_clear(core_id);
|
||||
if (clint_ipi_instance[core_id].callback != NULL)
|
||||
clint_ipi_instance[core_id].callback(clint_ipi_instance[core_id].ctx);
|
||||
clear_csr(mstatus, MSTATUS_MIE);
|
||||
set_csr(mstatus, MSTATUS_MPIE | MSTATUS_MPP);
|
||||
set_csr(mie, MIP_MSIP);
|
||||
return epc;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @brief The CLINT block holds memory-mapped control and status registers
|
||||
* associated with local interrupts for a Coreplex.
|
||||
*
|
||||
* @note CLINT RAM Layout
|
||||
*
|
||||
* | Address -| Description |
|
||||
* |------------|---------------------------------|
|
||||
* | 0x02000000 | msip for core 0 |
|
||||
* | 0x02000004 | msip for core 1 |
|
||||
* | ... | ... |
|
||||
* | 0x02003FF8 | msip for core 4094 |
|
||||
* | | |
|
||||
* | 0x02004000 | mtimecmp for core 0 |
|
||||
* | 0x02004008 | mtimecmp for core 1 |
|
||||
* | ... | ... |
|
||||
* | 0x0200BFF0 | mtimecmp For core 4094 |
|
||||
* | 0x0200BFF8 | mtime |
|
||||
* | | |
|
||||
* | 0x0200C000 | Reserved |
|
||||
* | ... | ... |
|
||||
* | 0x0200EFFC | Reserved |
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file clint.h
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#ifndef _DRIVER_CLINT_H
|
||||
#define _DRIVER_CLINT_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
/* Register address offsets */
|
||||
#define CLINT_MSIP (0x0000)
|
||||
#define CLINT_MSIP_SIZE (0x4)
|
||||
#define CLINT_MTIMECMP (0x4000)
|
||||
#define CLINT_MTIMECMP_SIZE (0x8)
|
||||
#define CLINT_MTIME (0xBFF8)
|
||||
#define CLINT_MTIME_SIZE (0x8)
|
||||
/* Max number of cores */
|
||||
#define CLINT_MAX_CORES (4095)
|
||||
/* Real number of cores */
|
||||
#define CLINT_NUM_CORES (2)
|
||||
/* Clock frequency division factor */
|
||||
#define CLINT_CLOCK_DIV (50)
|
||||
/* clang-format on */
|
||||
|
||||
/**
|
||||
* @brief MSIP Registers
|
||||
*
|
||||
* Machine-mode software interrupts are generated by writing to a
|
||||
* per-core memory-mapped control register. The msip registers are
|
||||
* 32-bit wide WARL registers, where the LSB is reflected in the
|
||||
* msip bit of the associated core’s mip register. Other bits in
|
||||
* the msip registers are hardwired to zero. The mapping supports
|
||||
* up to 4095 machine-mode cores.
|
||||
*/
|
||||
typedef struct _clint_msip
|
||||
{
|
||||
uint32_t msip : 1; /*!< Bit 0 is msip */
|
||||
uint32_t zero : 31; /*!< Bits [32:1] is 0 */
|
||||
} __attribute__((packed, aligned(4))) clint_msip_t;
|
||||
|
||||
/**
|
||||
* @brief Timer compare Registers Machine-mode timer interrupts are
|
||||
* generated by a real-time counter and a per-core comparator. The
|
||||
* mtime register is a 64-bit read-only register that contains the
|
||||
* current value of the real-time counter. Each mtimecmp register
|
||||
* holds its core’s time comparator. A timer interrupt is pending
|
||||
* whenever mtime is greater than or equal to the value in a
|
||||
* core’s mtimecmp register. The timer interrupt is reflected in
|
||||
* the mtip bit of the associated core’s mip register.
|
||||
*/
|
||||
typedef uint64_t clint_mtimecmp_t;
|
||||
|
||||
/**
|
||||
* @brief Timer Registers
|
||||
*
|
||||
* The mtime register has a 64-bit precision on all RV32, RV64,
|
||||
* and RV128 systems. Platforms provide a 64-bit memory-mapped
|
||||
* machine-mode timer compare register (mtimecmp), which causes a
|
||||
* timer interrupt to be posted when the mtime register contains a
|
||||
* value greater than or equal to the value in the mtimecmp
|
||||
* register. The interrupt remains posted until it is cleared by
|
||||
* writing the mtimecmp register. The interrupt will only be taken
|
||||
* if interrupts are enabled and the MTIE bit is set in the mie
|
||||
* register.
|
||||
*/
|
||||
typedef uint64_t clint_mtime_t;
|
||||
|
||||
/**
|
||||
* @brief CLINT object
|
||||
*
|
||||
* Coreplex-Local INTerrupts, which includes software interrupts,
|
||||
* local timer interrupts, and other interrupts routed directly to
|
||||
* a core.
|
||||
*/
|
||||
typedef struct _clint
|
||||
{
|
||||
/* 0x0000 to 0x3FF8, MSIP Registers */
|
||||
clint_msip_t msip[CLINT_MAX_CORES];
|
||||
/* Resverd space, do not use */
|
||||
uint32_t resv0;
|
||||
/* 0x4000 to 0xBFF0, Timer Compare Registers */
|
||||
clint_mtimecmp_t mtimecmp[CLINT_MAX_CORES];
|
||||
/* 0xBFF8, Time Register */
|
||||
clint_mtime_t mtime;
|
||||
} __attribute__((packed, aligned(4))) clint_t;
|
||||
|
||||
/**
|
||||
* @brief Clint object instanse
|
||||
*/
|
||||
extern volatile clint_t* const clint;
|
||||
|
||||
/**
|
||||
* @brief Definitions for the timer callbacks
|
||||
*/
|
||||
typedef int (*clint_timer_callback_t)(void *ctx);
|
||||
|
||||
/**
|
||||
* @brief Definitions for local interprocessor interrupt callbacks
|
||||
*/
|
||||
typedef int (*clint_ipi_callback_t)(void *ctx);
|
||||
|
||||
typedef struct _clint_timer_instance
|
||||
{
|
||||
uint64_t interval;
|
||||
uint64_t cycles;
|
||||
uint64_t single_shot;
|
||||
clint_timer_callback_t callback;
|
||||
void *ctx;
|
||||
} clint_timer_instance_t;
|
||||
|
||||
typedef struct _clint_ipi_instance
|
||||
{
|
||||
clint_ipi_callback_t callback;
|
||||
void *ctx;
|
||||
} clint_ipi_instance_t;
|
||||
|
||||
/**
|
||||
* @brief Get the time form CLINT timer register
|
||||
*
|
||||
* @note The CLINT must init to get right time
|
||||
*
|
||||
* @return 64bit Time
|
||||
*/
|
||||
uint64_t clint_get_time(void);
|
||||
|
||||
/**
|
||||
* @brief Init the CLINT timer
|
||||
*
|
||||
* @note MIP_MTIP will be clear after init. The MSTATUS_MIE must set by
|
||||
* user.
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_timer_init(void);
|
||||
|
||||
/**
|
||||
* @brief Stop the CLINT timer
|
||||
*
|
||||
* @note MIP_MTIP will be clear after stop
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_timer_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Start the CLINT timer
|
||||
*
|
||||
* @param[in] interval The interval with Millisecond(ms)
|
||||
* @param[in] single_shot Single shot or repeat
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_timer_start(uint64_t interval, int single_shot);
|
||||
|
||||
/**
|
||||
* @brief Get the interval of timer
|
||||
*
|
||||
* @return The interval with Millisecond(ms)
|
||||
*/
|
||||
uint64_t clint_timer_get_interval(void);
|
||||
|
||||
/**
|
||||
* @brief Set the interval with Millisecond(ms)
|
||||
*
|
||||
* @param[in] interval The interval with Millisecond(ms)
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_timer_set_interval(uint64_t interval);
|
||||
|
||||
/**
|
||||
* @brief Get whether the timer is a single shot timer
|
||||
*
|
||||
* @return result
|
||||
* - 0 It is a repeat timer
|
||||
* - 1 It is a single shot timer
|
||||
*/
|
||||
int clint_timer_get_single_shot(void);
|
||||
|
||||
/**
|
||||
* @brief Set the timer working as a single shot timer or repeat timer
|
||||
*
|
||||
* @param[in] single_shot Single shot or repeat
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_timer_set_single_shot(int single_shot);
|
||||
|
||||
/**
|
||||
* @brief Set user callback function when timer is timeout
|
||||
*
|
||||
* @param[in] callback The callback function
|
||||
* @param[in] ctx The context
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_timer_register(clint_timer_callback_t callback, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief Deregister user callback function
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_timer_unregister(void);
|
||||
|
||||
/**
|
||||
* @brief Initialize local interprocessor interrupt
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_ipi_init(void);
|
||||
|
||||
/**
|
||||
* @brief Enable local interprocessor interrupt
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_ipi_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Disable local interprocessor interrupt
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_ipi_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Send local interprocessor interrupt to core by core id
|
||||
*
|
||||
* @param[in] core_id The core identifier
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_ipi_send(size_t core_id);
|
||||
|
||||
/**
|
||||
* @brief Clear local interprocessor interrupt
|
||||
*
|
||||
* @param[in] core_id The core identifier
|
||||
*
|
||||
* @return result
|
||||
* - 1 An IPI was pending
|
||||
* - 0 Non IPI was pending
|
||||
* - -1 Fail
|
||||
*/
|
||||
int clint_ipi_clear(size_t core_id);
|
||||
|
||||
/**
|
||||
* @brief Set user callback function when interprocessor interrupt
|
||||
*
|
||||
* @param[in] callback The callback function
|
||||
* @param[in] ctx The context
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_ipi_register(clint_ipi_callback_t callback, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief Deregister user callback function
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_ipi_unregister(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_CLINT_H */
|
||||
|
||||
@@ -0,0 +1,808 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file damc.c
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include "dmac.h"
|
||||
#include "sysctl.h"
|
||||
#include "fpioa.h"
|
||||
#include "utils.h"
|
||||
#include "plic.h"
|
||||
#include "stdlib.h"
|
||||
#include <nuttx/arch.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
volatile dmac_t *const dmac = (dmac_t *)DMAC_BASE_ADDR;
|
||||
|
||||
typedef struct _dmac_context
|
||||
{
|
||||
dmac_channel_number_t dmac_channel;
|
||||
plic_irq_callback_t callback;
|
||||
void *ctx;
|
||||
} dmac_context_t;
|
||||
|
||||
dmac_context_t dmac_context[6];
|
||||
|
||||
static int is_memory(uintptr_t address)
|
||||
{
|
||||
enum {
|
||||
mem_len = 6 * 1024 * 1024,
|
||||
mem_no_cache_len = 8 * 1024 * 1024,
|
||||
};
|
||||
return ((address >= 0x80000000) && (address < 0x80000000 + mem_len)) || ((address >= 0x40000000) && (address < 0x40000000 + mem_no_cache_len)) || (address == 0x50450040);
|
||||
}
|
||||
|
||||
uint64_t dmac_read_id(void)
|
||||
{
|
||||
return dmac->id;
|
||||
}
|
||||
|
||||
uint64_t dmac_read_version(void)
|
||||
{
|
||||
return dmac->compver;
|
||||
}
|
||||
|
||||
uint64_t dmac_read_channel_id(dmac_channel_number_t channel_num)
|
||||
{
|
||||
return dmac->channel[channel_num].axi_id;
|
||||
}
|
||||
|
||||
static void dmac_enable(void)
|
||||
{
|
||||
dmac_cfg_u_t dmac_cfg;
|
||||
|
||||
dmac_cfg.data = readq(&dmac->cfg);
|
||||
dmac_cfg.cfg.dmac_en = 1;
|
||||
dmac_cfg.cfg.int_en = 1;
|
||||
writeq(dmac_cfg.data, &dmac->cfg);
|
||||
}
|
||||
|
||||
void dmac_disable(void)
|
||||
{
|
||||
dmac_cfg_u_t dmac_cfg;
|
||||
|
||||
dmac_cfg.data = readq(&dmac->cfg);
|
||||
dmac_cfg.cfg.dmac_en = 0;
|
||||
dmac_cfg.cfg.int_en = 0;
|
||||
writeq(dmac_cfg.data, &dmac->cfg);
|
||||
}
|
||||
|
||||
void src_transaction_complete_int_enable(dmac_channel_number_t channel_num)
|
||||
{
|
||||
dmac_ch_intstatus_enable_u_t ch_intstat;
|
||||
|
||||
ch_intstat.data = readq(&dmac->channel[channel_num].intstatus_en);
|
||||
ch_intstat.ch_intstatus_enable.enable_src_transcomp_intstat = 1;
|
||||
|
||||
writeq(ch_intstat.data, &dmac->channel[channel_num].intstatus_en);
|
||||
}
|
||||
|
||||
void dmac_channel_enable(dmac_channel_number_t channel_num)
|
||||
{
|
||||
dmac_chen_u_t chen;
|
||||
|
||||
chen.data = readq(&dmac->chen);
|
||||
|
||||
switch (channel_num) {
|
||||
case DMAC_CHANNEL0:
|
||||
chen.dmac_chen.ch1_en = 1;
|
||||
chen.dmac_chen.ch1_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL1:
|
||||
chen.dmac_chen.ch2_en = 1;
|
||||
chen.dmac_chen.ch2_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL2:
|
||||
chen.dmac_chen.ch3_en = 1;
|
||||
chen.dmac_chen.ch3_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL3:
|
||||
chen.dmac_chen.ch4_en = 1;
|
||||
chen.dmac_chen.ch4_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL4:
|
||||
chen.dmac_chen.ch5_en = 1;
|
||||
chen.dmac_chen.ch5_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL5:
|
||||
chen.dmac_chen.ch6_en = 1;
|
||||
chen.dmac_chen.ch6_en_we = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
writeq(chen.data, &dmac->chen);
|
||||
}
|
||||
|
||||
void dmac_channel_disable(dmac_channel_number_t channel_num)
|
||||
{
|
||||
dmac_chen_u_t chen;
|
||||
|
||||
chen.data = readq(&dmac->chen);
|
||||
|
||||
switch (channel_num)
|
||||
{
|
||||
case DMAC_CHANNEL0:
|
||||
chen.dmac_chen.ch1_en = 0;
|
||||
chen.dmac_chen.ch1_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL1:
|
||||
chen.dmac_chen.ch2_en = 0;
|
||||
chen.dmac_chen.ch2_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL2:
|
||||
chen.dmac_chen.ch3_en = 0;
|
||||
chen.dmac_chen.ch3_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL3:
|
||||
chen.dmac_chen.ch4_en = 0;
|
||||
chen.dmac_chen.ch4_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL4:
|
||||
chen.dmac_chen.ch5_en = 0;
|
||||
chen.dmac_chen.ch5_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL5:
|
||||
chen.dmac_chen.ch6_en = 0;
|
||||
chen.dmac_chen.ch6_en_we = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
writeq(chen.data, &dmac->chen);
|
||||
}
|
||||
|
||||
int32_t dmac_check_channel_busy(dmac_channel_number_t channel_num)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
dmac_chen_u_t chen_u;
|
||||
|
||||
chen_u.data = readq(&dmac->chen);
|
||||
switch (channel_num) {
|
||||
case DMAC_CHANNEL0:
|
||||
if (chen_u.dmac_chen.ch1_en == 1)
|
||||
ret = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL1:
|
||||
if (chen_u.dmac_chen.ch2_en == 1)
|
||||
ret = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL2:
|
||||
if (chen_u.dmac_chen.ch3_en == 1)
|
||||
ret = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL3:
|
||||
if (chen_u.dmac_chen.ch4_en == 1)
|
||||
ret = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL4:
|
||||
if (chen_u.dmac_chen.ch5_en == 1)
|
||||
ret = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL5:
|
||||
if (chen_u.dmac_chen.ch6_en == 1)
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
writeq(chen_u.data, &dmac->chen);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t dmac_set_list_master_select(dmac_channel_number_t channel_num,
|
||||
dmac_src_dst_select_t sd_sel, dmac_master_number_t mst_num)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
uint64_t tmp = 0;
|
||||
dmac_ch_ctl_u_t ctl;
|
||||
|
||||
ctl.data = readq(&dmac->channel[channel_num].ctl);
|
||||
ret = dmac_check_channel_busy(channel_num);
|
||||
if (ret == 0) {
|
||||
if (sd_sel == DMAC_SRC || sd_sel == DMAC_SRC_DST)
|
||||
ctl.ch_ctl.sms = mst_num;
|
||||
|
||||
if (sd_sel == DMAC_DST || sd_sel == DMAC_SRC_DST)
|
||||
ctl.ch_ctl.dms = mst_num;
|
||||
tmp |= *(uint64_t *)&dmac->channel[channel_num].ctl;
|
||||
writeq(ctl.data, &dmac->channel[channel_num].ctl);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dmac_enable_common_interrupt_status(void)
|
||||
{
|
||||
dmac_commonreg_intstatus_enable_u_t intstatus;
|
||||
|
||||
intstatus.data = readq(&dmac->com_intstatus_en);
|
||||
intstatus.intstatus_enable.enable_slvif_dec_err_intstat = 1;
|
||||
intstatus.intstatus_enable.enable_slvif_wr2ro_err_intstat = 1;
|
||||
intstatus.intstatus_enable.enable_slvif_rd2wo_err_intstat = 1;
|
||||
intstatus.intstatus_enable.enable_slvif_wronhold_err_intstat = 1;
|
||||
intstatus.intstatus_enable.enable_slvif_undefinedreg_dec_err_intstat = 1;
|
||||
|
||||
writeq(intstatus.data, &dmac->com_intstatus_en);
|
||||
}
|
||||
|
||||
void dmac_enable_common_interrupt_signal(void)
|
||||
{
|
||||
dmac_commonreg_intsignal_enable_u_t intsignal;
|
||||
|
||||
intsignal.data = readq(&dmac->com_intsignal_en);
|
||||
intsignal.intsignal_enable.enable_slvif_dec_err_intsignal = 1;
|
||||
intsignal.intsignal_enable.enable_slvif_wr2ro_err_intsignal = 1;
|
||||
intsignal.intsignal_enable.enable_slvif_rd2wo_err_intsignal = 1;
|
||||
intsignal.intsignal_enable.enable_slvif_wronhold_err_intsignal = 1;
|
||||
intsignal.intsignal_enable.enable_slvif_undefinedreg_dec_err_intsignal = 1;
|
||||
|
||||
writeq(intsignal.data, &dmac->com_intsignal_en);
|
||||
}
|
||||
|
||||
static void dmac_enable_channel_interrupt(dmac_channel_number_t channel_num)
|
||||
{
|
||||
writeq(0xffffffff, &dmac->channel[channel_num].intclear);
|
||||
writeq(0x2, &dmac->channel[channel_num].intstatus_en);
|
||||
}
|
||||
|
||||
void dmac_disable_channel_interrupt(dmac_channel_number_t channel_num)
|
||||
{
|
||||
writeq(0, &dmac->channel[channel_num].intstatus_en);
|
||||
}
|
||||
|
||||
void dmac_chanel_interrupt_clear(dmac_channel_number_t channel_num)
|
||||
{
|
||||
writeq(0xffffffff, &dmac->channel[channel_num].intclear);
|
||||
}
|
||||
|
||||
int dmac_set_channel_config(dmac_channel_number_t channel_num,
|
||||
dmac_channel_config_t *cfg_param)
|
||||
{
|
||||
dmac_ch_ctl_u_t ctl;
|
||||
dmac_ch_cfg_u_t cfg;
|
||||
dmac_ch_llp_u_t ch_llp;
|
||||
|
||||
if (cfg_param->ctl_sms > DMAC_MASTER2)
|
||||
return -1;
|
||||
if (cfg_param->ctl_dms > DMAC_MASTER2)
|
||||
return -1;
|
||||
if (cfg_param->ctl_src_msize > DMAC_MSIZE_256)
|
||||
return -1;
|
||||
if (cfg_param->ctl_drc_msize > DMAC_MSIZE_256)
|
||||
return -1;
|
||||
|
||||
/**
|
||||
* cfg register must configure before ts_block and
|
||||
* sar dar register
|
||||
*/
|
||||
cfg.data = readq(&dmac->channel[channel_num].cfg);
|
||||
|
||||
cfg.ch_cfg.hs_sel_src = cfg_param->cfg_hs_sel_src;
|
||||
cfg.ch_cfg.hs_sel_dst = cfg_param->cfg_hs_sel_dst;
|
||||
cfg.ch_cfg.src_hwhs_pol = cfg_param->cfg_src_hs_pol;
|
||||
cfg.ch_cfg.dst_hwhs_pol = cfg_param->cfg_dst_hs_pol;
|
||||
cfg.ch_cfg.src_per = cfg_param->cfg_src_per;
|
||||
cfg.ch_cfg.dst_per = cfg_param->cfg_dst_per;
|
||||
cfg.ch_cfg.ch_prior = cfg_param->cfg_ch_prior;
|
||||
cfg.ch_cfg.tt_fc = cfg_param->ctl_tt_fc;
|
||||
|
||||
cfg.ch_cfg.src_multblk_type = cfg_param->cfg_src_multblk_type;
|
||||
cfg.ch_cfg.dst_multblk_type = cfg_param->cfg_dst_multblk_type;
|
||||
|
||||
writeq(cfg.data, &dmac->channel[channel_num].cfg);
|
||||
|
||||
ctl.data = readq(&dmac->channel[channel_num].ctl);
|
||||
ctl.ch_ctl.sms = cfg_param->ctl_sms;
|
||||
ctl.ch_ctl.dms = cfg_param->ctl_dms;
|
||||
/* master select */
|
||||
ctl.ch_ctl.sinc = cfg_param->ctl_sinc;
|
||||
ctl.ch_ctl.dinc = cfg_param->ctl_dinc;
|
||||
/* address incrememt */
|
||||
ctl.ch_ctl.src_tr_width = cfg_param->ctl_src_tr_width;
|
||||
ctl.ch_ctl.dst_tr_width = cfg_param->ctl_dst_tr_width;
|
||||
/* transfer width */
|
||||
ctl.ch_ctl.src_msize = cfg_param->ctl_src_msize;
|
||||
ctl.ch_ctl.dst_msize = cfg_param->ctl_drc_msize;
|
||||
/* Burst transaction length */
|
||||
ctl.ch_ctl.ioc_blktfr = cfg_param->ctl_ioc_blktfr;
|
||||
/* interrupt on completion of block transfer */
|
||||
/* 0x1 enable BLOCK_TFR_DONE_IntStat field */
|
||||
|
||||
writeq(cfg_param->ctl_block_ts, &dmac->channel[channel_num].block_ts);
|
||||
/* the number of (blcok_ts +1) data of width SRC_TR_WIDTF to be */
|
||||
/* transferred in a dma block transfer */
|
||||
|
||||
dmac->channel[channel_num].sar = cfg_param->sar;
|
||||
dmac->channel[channel_num].dar = cfg_param->dar;
|
||||
|
||||
ch_llp.data = readq(&dmac->channel[channel_num].llp);
|
||||
ch_llp.llp.loc = cfg_param->llp_loc;
|
||||
ch_llp.llp.lms = cfg_param->llp_lms;
|
||||
writeq(ch_llp.data, &dmac->channel[channel_num].llp);
|
||||
writeq(ctl.data, &dmac->channel[channel_num].ctl);
|
||||
readq(&dmac->channel[channel_num].swhssrc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dmac_set_channel_param(dmac_channel_number_t channel_num,
|
||||
const void *src, void *dest, dmac_address_increment_t src_inc, dmac_address_increment_t dest_inc,
|
||||
dmac_burst_trans_length_t dmac_burst_size,
|
||||
dmac_transfer_width_t dmac_trans_width,
|
||||
uint32_t blockSize)
|
||||
{
|
||||
dmac_ch_ctl_u_t ctl;
|
||||
dmac_ch_cfg_u_t cfg_u;
|
||||
|
||||
int mem_type_src = is_memory((uintptr_t)src), mem_type_dest = is_memory((uintptr_t)dest);
|
||||
dmac_transfer_flow_t flow_control;
|
||||
if (mem_type_src == 0 && mem_type_dest == 0)
|
||||
{
|
||||
flow_control = DMAC_PRF2PRF_DMA;
|
||||
}else if (mem_type_src == 1 && mem_type_dest == 0)
|
||||
flow_control = DMAC_MEM2PRF_DMA;
|
||||
else if (mem_type_src == 0 && mem_type_dest == 1)
|
||||
flow_control = DMAC_PRF2MEM_DMA;
|
||||
else
|
||||
flow_control = DMAC_MEM2MEM_DMA;
|
||||
|
||||
/**
|
||||
* cfg register must configure before ts_block and
|
||||
* sar dar register
|
||||
*/
|
||||
cfg_u.data = readq(&dmac->channel[channel_num].cfg);
|
||||
|
||||
cfg_u.ch_cfg.tt_fc = flow_control;
|
||||
cfg_u.ch_cfg.hs_sel_src = mem_type_src ? DMAC_HS_SOFTWARE : DMAC_HS_HARDWARE;
|
||||
cfg_u.ch_cfg.hs_sel_dst = mem_type_dest ? DMAC_HS_SOFTWARE : DMAC_HS_HARDWARE;
|
||||
cfg_u.ch_cfg.src_per = channel_num;
|
||||
cfg_u.ch_cfg.dst_per = channel_num;
|
||||
cfg_u.ch_cfg.src_multblk_type = 0;
|
||||
cfg_u.ch_cfg.dst_multblk_type = 0;
|
||||
|
||||
writeq(cfg_u.data, &dmac->channel[channel_num].cfg);
|
||||
|
||||
dmac->channel[channel_num].sar = (uint64_t)src;
|
||||
dmac->channel[channel_num].dar = (uint64_t)dest;
|
||||
|
||||
ctl.data = readq(&dmac->channel[channel_num].ctl);
|
||||
ctl.ch_ctl.sms = DMAC_MASTER1;
|
||||
ctl.ch_ctl.dms = DMAC_MASTER2;
|
||||
/* master select */
|
||||
ctl.ch_ctl.sinc = src_inc;
|
||||
ctl.ch_ctl.dinc = dest_inc;
|
||||
/* address incrememt */
|
||||
ctl.ch_ctl.src_tr_width = dmac_trans_width;
|
||||
ctl.ch_ctl.dst_tr_width = dmac_trans_width;
|
||||
/* transfer width */
|
||||
ctl.ch_ctl.src_msize = dmac_burst_size;
|
||||
ctl.ch_ctl.dst_msize = dmac_burst_size;
|
||||
|
||||
writeq(ctl.data, &dmac->channel[channel_num].ctl);
|
||||
|
||||
writeq(blockSize - 1, &dmac->channel[channel_num].block_ts);
|
||||
/*the number of (blcok_ts +1) data of width SRC_TR_WIDTF to be */
|
||||
/* transferred in a dma block transfer */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dmac_get_channel_config(dmac_channel_number_t channel_num,
|
||||
dmac_channel_config_t *cfg_param)
|
||||
{
|
||||
dmac_ch_ctl_u_t ctl;
|
||||
dmac_ch_cfg_u_t cfg;
|
||||
dmac_ch_llp_u_t ch_llp;
|
||||
|
||||
if (cfg_param == 0)
|
||||
return -1;
|
||||
if (channel_num < DMAC_CHANNEL0 ||
|
||||
channel_num > DMAC_CHANNEL3)
|
||||
return -1;
|
||||
|
||||
ctl.data = readq(&dmac->channel[channel_num].ctl);
|
||||
|
||||
cfg_param->ctl_sms = ctl.ch_ctl.sms;
|
||||
cfg_param->ctl_dms = ctl.ch_ctl.dms;
|
||||
cfg_param->ctl_sinc = ctl.ch_ctl.sinc;
|
||||
cfg_param->ctl_dinc = ctl.ch_ctl.dinc;
|
||||
cfg_param->ctl_src_tr_width = ctl.ch_ctl.src_tr_width;
|
||||
cfg_param->ctl_dst_tr_width = ctl.ch_ctl.dst_tr_width;
|
||||
cfg_param->ctl_src_msize = ctl.ch_ctl.src_msize;
|
||||
cfg_param->ctl_drc_msize = ctl.ch_ctl.dst_msize;
|
||||
cfg_param->ctl_ioc_blktfr = ctl.ch_ctl.ioc_blktfr;
|
||||
|
||||
cfg.data = readq(&dmac->channel[channel_num].cfg);
|
||||
cfg_param->cfg_hs_sel_src = cfg.ch_cfg.hs_sel_src;
|
||||
cfg_param->cfg_hs_sel_dst = cfg.ch_cfg.hs_sel_dst;
|
||||
cfg_param->cfg_src_hs_pol = cfg.ch_cfg.src_hwhs_pol;
|
||||
cfg_param->cfg_dst_hs_pol = cfg.ch_cfg.dst_hwhs_pol;
|
||||
cfg_param->cfg_src_per = cfg.ch_cfg.src_per;
|
||||
cfg_param->cfg_dst_per = cfg.ch_cfg.dst_per;
|
||||
cfg_param->cfg_ch_prior = cfg.ch_cfg.ch_prior;
|
||||
cfg_param->cfg_src_multblk_type = cfg.ch_cfg.src_multblk_type;
|
||||
cfg_param->cfg_dst_multblk_type = cfg.ch_cfg.dst_multblk_type;
|
||||
|
||||
cfg_param->sar = dmac->channel[channel_num].sar;
|
||||
cfg_param->dar = dmac->channel[channel_num].dar;
|
||||
|
||||
ch_llp.data = readq(&dmac->channel[channel_num].llp);
|
||||
cfg_param->llp_loc = ch_llp.llp.loc;
|
||||
cfg_param->llp_lms = ch_llp.llp.lms;
|
||||
|
||||
cfg_param->ctl_block_ts = readq(&dmac->channel[channel_num].block_ts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dmac_set_address(dmac_channel_number_t channel_num, uint64_t src_addr,
|
||||
uint64_t dst_addr)
|
||||
{
|
||||
writeq(src_addr, &dmac->channel[channel_num].sar);
|
||||
writeq(dst_addr, &dmac->channel[channel_num].dar);
|
||||
}
|
||||
|
||||
void dmac_set_block_ts(dmac_channel_number_t channel_num,
|
||||
uint32_t block_size)
|
||||
{
|
||||
uint32_t block_ts;
|
||||
|
||||
block_ts = block_size & 0x3fffff;
|
||||
writeq(block_ts, &dmac->channel[channel_num].block_ts);
|
||||
}
|
||||
|
||||
void dmac_source_control(dmac_channel_number_t channel_num,
|
||||
dmac_master_number_t master_select,
|
||||
dmac_address_increment_t address_mode,
|
||||
dmac_transfer_width_t tr_width,
|
||||
dmac_burst_trans_length_t burst_length)
|
||||
{
|
||||
dmac_ch_ctl_u_t ctl_u;
|
||||
|
||||
ctl_u.data = readq(&dmac->channel[channel_num].ctl);
|
||||
ctl_u.ch_ctl.sms = master_select;
|
||||
ctl_u.ch_ctl.sinc = address_mode;
|
||||
ctl_u.ch_ctl.src_tr_width = tr_width;
|
||||
ctl_u.ch_ctl.src_msize = burst_length;
|
||||
|
||||
writeq(ctl_u.data, &dmac->channel[channel_num].ctl);
|
||||
}
|
||||
|
||||
void dmac_master_control(dmac_channel_number_t channel_num,
|
||||
dmac_master_number_t master_select,
|
||||
dmac_address_increment_t address_mode,
|
||||
dmac_transfer_width_t tr_width,
|
||||
dmac_burst_trans_length_t burst_length)
|
||||
{
|
||||
dmac_ch_ctl_u_t ctl_u;
|
||||
|
||||
ctl_u.data = readq(&dmac->channel[channel_num].ctl);
|
||||
ctl_u.ch_ctl.dms = master_select;
|
||||
ctl_u.ch_ctl.dinc = address_mode;
|
||||
ctl_u.ch_ctl.dst_tr_width = tr_width;
|
||||
ctl_u.ch_ctl.dst_msize = burst_length;
|
||||
|
||||
writeq(ctl_u.data, &dmac->channel[channel_num].ctl);
|
||||
}
|
||||
|
||||
void dmac_set_source_transfer_control(dmac_channel_number_t channel_num,
|
||||
dmac_multiblk_transfer_type_t transfer_type,
|
||||
dmac_sw_hw_hs_select_t handshak_select)
|
||||
{
|
||||
dmac_ch_cfg_u_t cfg_u;
|
||||
|
||||
cfg_u.data = readq(&dmac->channel[channel_num].cfg);
|
||||
cfg_u.ch_cfg.src_multblk_type = transfer_type;
|
||||
cfg_u.ch_cfg.hs_sel_src = handshak_select;
|
||||
|
||||
writeq(cfg_u.data, &dmac->channel[channel_num].cfg);
|
||||
}
|
||||
|
||||
void dmac_set_destination_transfer_control(dmac_channel_number_t channel_num,
|
||||
dmac_multiblk_transfer_type_t transfer_type,
|
||||
dmac_sw_hw_hs_select_t handshak_select)
|
||||
{
|
||||
dmac_ch_cfg_u_t cfg_u;
|
||||
|
||||
cfg_u.data = readq(&dmac->channel[channel_num].cfg);
|
||||
cfg_u.ch_cfg.dst_multblk_type = transfer_type;
|
||||
cfg_u.ch_cfg.hs_sel_dst = handshak_select;
|
||||
|
||||
writeq(cfg_u.data, &dmac->channel[channel_num].cfg);
|
||||
}
|
||||
|
||||
void dmac_set_flow_control(dmac_channel_number_t channel_num,
|
||||
dmac_transfer_flow_t flow_control)
|
||||
{
|
||||
dmac_ch_cfg_u_t cfg_u;
|
||||
|
||||
cfg_u.data = readq(&dmac->channel[channel_num].cfg);
|
||||
cfg_u.ch_cfg.tt_fc = flow_control;
|
||||
|
||||
writeq(cfg_u.data, &dmac->channel[channel_num].cfg);
|
||||
}
|
||||
|
||||
void dmac_set_linked_list_addr_point(dmac_channel_number_t channel_num,
|
||||
uint64_t *addr)
|
||||
{
|
||||
dmac_ch_llp_u_t llp_u;
|
||||
|
||||
llp_u.data = readq(&dmac->channel[channel_num].llp);
|
||||
/* Cast pointer to uint64_t */
|
||||
llp_u.llp.loc = (uint64_t)addr;
|
||||
writeq(llp_u.data, &dmac->channel[channel_num].llp);
|
||||
}
|
||||
|
||||
void dmac_init(void)
|
||||
{
|
||||
uint64_t tmp;
|
||||
dmac_commonreg_intclear_u_t intclear;
|
||||
dmac_cfg_u_t dmac_cfg;
|
||||
dmac_reset_u_t dmac_reset;
|
||||
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_DMA);
|
||||
|
||||
dmac_reset.data = readq(&dmac->reset);
|
||||
dmac_reset.reset.rst = 1;
|
||||
writeq(dmac_reset.data, &dmac->reset);
|
||||
while (dmac_reset.reset.rst)
|
||||
dmac_reset.data = readq(&dmac->reset);
|
||||
|
||||
/*reset dmac */
|
||||
|
||||
intclear.data = readq(&dmac->com_intclear);
|
||||
intclear.com_intclear.cear_slvif_dec_err_intstat = 1;
|
||||
intclear.com_intclear.clear_slvif_wr2ro_err_intstat = 1;
|
||||
intclear.com_intclear.clear_slvif_rd2wo_err_intstat = 1;
|
||||
intclear.com_intclear.clear_slvif_wronhold_err_intstat = 1;
|
||||
intclear.com_intclear.clear_slvif_undefinedreg_dec_err_intstat = 1;
|
||||
writeq(intclear.data, &dmac->com_intclear);
|
||||
/* clear common register interrupt */
|
||||
|
||||
dmac_cfg.data = readq(&dmac->cfg);
|
||||
dmac_cfg.cfg.dmac_en = 0;
|
||||
dmac_cfg.cfg.int_en = 0;
|
||||
writeq(dmac_cfg.data, &dmac->cfg);
|
||||
/* disable dmac and disable interrupt */
|
||||
|
||||
while (readq(&dmac->cfg))
|
||||
;
|
||||
tmp = readq(&dmac->chen);
|
||||
tmp &= ~0xf;
|
||||
writeq(tmp, &dmac->chen);
|
||||
/* disable all channel before configure */
|
||||
dmac_enable();
|
||||
}
|
||||
|
||||
static void list_add(struct list_head_t *new, struct list_head_t *prev,
|
||||
struct list_head_t *next)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
}
|
||||
|
||||
void list_add_tail(struct list_head_t *new, struct list_head_t *head)
|
||||
{
|
||||
list_add(new, head->prev, head);
|
||||
}
|
||||
|
||||
void INIT_LIST_HEAD(struct list_head_t *list)
|
||||
{
|
||||
list->next = list;
|
||||
list->prev = list;
|
||||
}
|
||||
|
||||
void dmac_link_list_item(dmac_channel_number_t channel_num,
|
||||
uint8_t LLI_row_num, int8_t LLI_last_row,
|
||||
dmac_lli_item_t *lli_item,
|
||||
dmac_channel_config_t *cfg_param)
|
||||
{
|
||||
dmac_ch_ctl_u_t ctl;
|
||||
dmac_ch_llp_u_t llp_u;
|
||||
|
||||
lli_item[LLI_row_num].sar = cfg_param->sar;
|
||||
lli_item[LLI_row_num].dar = cfg_param->dar;
|
||||
|
||||
ctl.data = readq(&dmac->channel[channel_num].ctl);
|
||||
ctl.ch_ctl.sms = cfg_param->ctl_sms;
|
||||
ctl.ch_ctl.dms = cfg_param->ctl_dms;
|
||||
ctl.ch_ctl.sinc = cfg_param->ctl_sinc;
|
||||
ctl.ch_ctl.dinc = cfg_param->ctl_dinc;
|
||||
ctl.ch_ctl.src_tr_width = cfg_param->ctl_src_tr_width;
|
||||
ctl.ch_ctl.dst_tr_width = cfg_param->ctl_dst_tr_width;
|
||||
ctl.ch_ctl.src_msize = cfg_param->ctl_src_msize;
|
||||
ctl.ch_ctl.dst_msize = cfg_param->ctl_drc_msize;
|
||||
ctl.ch_ctl.src_stat_en = cfg_param->ctl_src_stat_en;
|
||||
ctl.ch_ctl.dst_stat_en = cfg_param->ctl_dst_stat_en;
|
||||
|
||||
if (LLI_last_row != LAST_ROW) {
|
||||
ctl.ch_ctl.shadowreg_or_lli_valid = 1;
|
||||
ctl.ch_ctl.shadowreg_or_lli_last = 0;
|
||||
} else {
|
||||
ctl.ch_ctl.shadowreg_or_lli_valid = 1;
|
||||
ctl.ch_ctl.shadowreg_or_lli_last = 1;
|
||||
}
|
||||
|
||||
lli_item[LLI_row_num].ctl = ctl.data;
|
||||
|
||||
lli_item[LLI_row_num].ch_block_ts = cfg_param->ctl_block_ts;
|
||||
lli_item[LLI_row_num].sstat = 0;
|
||||
lli_item[LLI_row_num].dstat = 0;
|
||||
|
||||
llp_u.data = readq(&dmac->channel[channel_num].llp);
|
||||
|
||||
if (LLI_last_row != LAST_ROW)
|
||||
llp_u.llp.loc = ((uint64_t)&lli_item[LLI_row_num + 1]) >> 6;
|
||||
else
|
||||
llp_u.llp.loc = 0;
|
||||
|
||||
lli_item[LLI_row_num].llp = llp_u.data;
|
||||
}
|
||||
|
||||
void dmac_update_shandow_register(dmac_channel_number_t channel_num,
|
||||
int8_t last_block, dmac_channel_config_t *cfg_param)
|
||||
{
|
||||
dmac_ch_ctl_u_t ctl_u;
|
||||
|
||||
do {
|
||||
ctl_u.data = readq(&dmac->channel[channel_num].ctl);
|
||||
} while (ctl_u.ch_ctl.shadowreg_or_lli_valid);
|
||||
|
||||
writeq(cfg_param->sar, &dmac->channel[channel_num].sar);
|
||||
writeq(cfg_param->dar, &dmac->channel[channel_num].dar);
|
||||
writeq(cfg_param->ctl_block_ts, &dmac->channel[channel_num].block_ts);
|
||||
|
||||
ctl_u.ch_ctl.sms = cfg_param->ctl_sms;
|
||||
ctl_u.ch_ctl.dms = cfg_param->ctl_dms;
|
||||
ctl_u.ch_ctl.sinc = cfg_param->ctl_sinc;
|
||||
ctl_u.ch_ctl.dinc = cfg_param->ctl_dinc;
|
||||
ctl_u.ch_ctl.src_tr_width = cfg_param->ctl_src_tr_width;
|
||||
ctl_u.ch_ctl.dst_tr_width = cfg_param->ctl_dst_tr_width;
|
||||
ctl_u.ch_ctl.src_msize = cfg_param->ctl_src_msize;
|
||||
ctl_u.ch_ctl.dst_msize = cfg_param->ctl_drc_msize;
|
||||
ctl_u.ch_ctl.src_stat_en = cfg_param->ctl_src_stat_en;
|
||||
ctl_u.ch_ctl.dst_stat_en = cfg_param->ctl_dst_stat_en;
|
||||
if (last_block != LAST_ROW)
|
||||
{
|
||||
ctl_u.ch_ctl.shadowreg_or_lli_valid = 1;
|
||||
ctl_u.ch_ctl.shadowreg_or_lli_last = 0;
|
||||
} else {
|
||||
ctl_u.ch_ctl.shadowreg_or_lli_valid = 1;
|
||||
ctl_u.ch_ctl.shadowreg_or_lli_last = 1;
|
||||
}
|
||||
|
||||
writeq(ctl_u.data, &dmac->channel[channel_num].ctl);
|
||||
writeq(0, &dmac->channel[channel_num].blk_tfr);
|
||||
}
|
||||
|
||||
void dmac_set_shadow_invalid_flag(dmac_channel_number_t channel_num)
|
||||
{
|
||||
dmac_ch_ctl_u_t ctl_u;
|
||||
|
||||
ctl_u.data = readq(&dmac->channel[channel_num].ctl);
|
||||
ctl_u.ch_ctl.shadowreg_or_lli_valid = 1;
|
||||
ctl_u.ch_ctl.shadowreg_or_lli_last = 0;
|
||||
writeq(ctl_u.data, &dmac->channel[channel_num].ctl);
|
||||
}
|
||||
|
||||
void dmac_set_single_mode(dmac_channel_number_t channel_num,
|
||||
const void *src, void *dest, dmac_address_increment_t src_inc,
|
||||
dmac_address_increment_t dest_inc,
|
||||
dmac_burst_trans_length_t dmac_burst_size,
|
||||
dmac_transfer_width_t dmac_trans_width,
|
||||
size_t block_size) {
|
||||
dmac_chanel_interrupt_clear(channel_num);
|
||||
dmac_channel_disable(channel_num);
|
||||
dmac_wait_idle(channel_num);
|
||||
dmac_set_channel_param(channel_num, src, dest, src_inc, dest_inc,
|
||||
dmac_burst_size, dmac_trans_width, block_size);
|
||||
dmac_enable();
|
||||
dmac_channel_enable(channel_num);
|
||||
}
|
||||
|
||||
int dmac_is_done(dmac_channel_number_t channel_num)
|
||||
{
|
||||
if(readq(&dmac->channel[channel_num].intstatus) & 0x2)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dmac_wait_done(dmac_channel_number_t channel_num)
|
||||
{
|
||||
dmac_wait_idle(channel_num);
|
||||
}
|
||||
|
||||
int dmac_is_idle(dmac_channel_number_t channel_num)
|
||||
{
|
||||
dmac_chen_u_t chen;
|
||||
chen.data = readq(&dmac->chen);
|
||||
if((chen.data >> channel_num) & 0x1UL)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
void dmac_wait_idle(dmac_channel_number_t channel_num)
|
||||
{
|
||||
while(!dmac_is_idle(channel_num));
|
||||
dmac_chanel_interrupt_clear(channel_num); /* clear interrupt */
|
||||
}
|
||||
|
||||
void dmac_set_src_dest_length(dmac_channel_number_t channel_num, const void *src, void *dest, size_t len)
|
||||
{
|
||||
if(src != NULL)
|
||||
dmac->channel[channel_num].sar = (uint64_t)src;
|
||||
if(dest != NULL)
|
||||
dmac->channel[channel_num].dar = (uint64_t)dest;
|
||||
if(len > 0)
|
||||
dmac_set_block_ts(channel_num, len - 1);
|
||||
dmac_channel_enable(channel_num);
|
||||
}
|
||||
|
||||
static int dmac_irq_callback(int irq, void *ctx, void *arg)
|
||||
{
|
||||
dmac_context_t *v_dmac_context = (dmac_context_t *)(ctx);
|
||||
dmac_channel_number_t v_dmac_channel = v_dmac_context->dmac_channel;
|
||||
dmac_chanel_interrupt_clear(v_dmac_channel);
|
||||
if(v_dmac_context->callback != NULL)
|
||||
v_dmac_context->callback(v_dmac_context->ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dmac_irq_register(dmac_channel_number_t channel_num , plic_irq_callback_t dmac_callback, void *ctx, uint32_t priority)
|
||||
{
|
||||
int ret;
|
||||
dmac_context[channel_num].dmac_channel = channel_num;
|
||||
dmac_context[channel_num].callback = dmac_callback;
|
||||
dmac_context[channel_num].ctx = ctx;
|
||||
dmac_enable_channel_interrupt(channel_num);
|
||||
plic_set_priority(IRQN_DMA0_INTERRUPT + channel_num, priority);
|
||||
ret = irq_attach(IRQN_DMA0_INTERRUPT + channel_num, dmac_irq_callback, &dmac_context[channel_num]);
|
||||
if (ret == OK)
|
||||
{
|
||||
up_enable_irq(IRQN_DMA0_INTERRUPT + channel_num);
|
||||
}
|
||||
}
|
||||
|
||||
void __attribute__((weak, alias("dmac_irq_register"))) dmac_set_irq(dmac_channel_number_t channel_num , plic_irq_callback_t dmac_callback, void *ctx, uint32_t priority);
|
||||
|
||||
void dmac_irq_unregister(dmac_channel_number_t channel_num)
|
||||
{
|
||||
dmac_context[channel_num].callback = NULL;
|
||||
dmac_context[channel_num].ctx = NULL;
|
||||
up_disable_irq(IRQN_DMA0_INTERRUPT + channel_num);
|
||||
irq_detach(IRQN_DMA0_INTERRUPT + channel_num);
|
||||
}
|
||||
|
||||
void __attribute__((weak, alias("dmac_irq_unregister"))) dmac_free_irq(dmac_channel_number_t channel_num);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,79 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file fft.c
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
#include "dmac.h"
|
||||
#include "utils.h"
|
||||
#include "sysctl.h"
|
||||
#include "fft.h"
|
||||
|
||||
static volatile fft_t *const fft = (volatile fft_t *)FFT_BASE_ADDR;
|
||||
|
||||
static void fft_init(uint8_t point, uint8_t mode, uint16_t shift, uint8_t is_dma, uint8_t input_mode, uint8_t data_mode)
|
||||
{
|
||||
fft->fft_ctrl.fft_point = point;
|
||||
fft->fft_ctrl.fft_mode = mode;
|
||||
fft->fft_ctrl.fft_shift = shift;
|
||||
fft->fft_ctrl.dma_send = is_dma;
|
||||
fft->fft_ctrl.fft_enable = 1;
|
||||
fft->fft_ctrl.fft_input_mode = input_mode;
|
||||
fft->fft_ctrl.fft_data_mode = data_mode;
|
||||
}
|
||||
|
||||
void fft_complex_uint16_dma(dmac_channel_number_t dma_send_channel_num, dmac_channel_number_t dma_receive_channel_num,
|
||||
uint16_t shift, fft_direction_t direction, const uint64_t *input, size_t point_num, uint64_t *output)
|
||||
{
|
||||
fft_point_t point = FFT_512;
|
||||
switch(point_num)
|
||||
{
|
||||
case 512:
|
||||
point = FFT_512;
|
||||
break;
|
||||
case 256:
|
||||
point = FFT_256;
|
||||
break;
|
||||
case 128:
|
||||
point = FFT_128;
|
||||
break;
|
||||
case 64:
|
||||
point = FFT_64;
|
||||
break;
|
||||
default:
|
||||
ASSERT(!"fft point error");
|
||||
break;
|
||||
}
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_FFT);
|
||||
sysctl_reset(SYSCTL_RESET_FFT);
|
||||
fft_init(point, direction, shift, 1, 0, 0);
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_FFT_RX_REQ);
|
||||
sysctl_dma_select(dma_send_channel_num, SYSCTL_DMA_SELECT_FFT_TX_REQ);
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&fft->fft_output_fifo), output, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_64, point_num>>1);
|
||||
dmac_set_single_mode(dma_send_channel_num, input, (void *)(&fft->fft_input_fifo), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_64, point_num>>1);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file fft.h
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#ifndef _DRIVER_FFT_H
|
||||
#define _DRIVER_FFT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _complex_hard
|
||||
{
|
||||
int16_t real;
|
||||
int16_t imag;
|
||||
} complex_hard_t;
|
||||
|
||||
typedef struct _fft_data
|
||||
{
|
||||
int16_t I1;
|
||||
int16_t R1;
|
||||
int16_t I2;
|
||||
int16_t R2;
|
||||
} fft_data_t;
|
||||
|
||||
typedef enum _fft_point
|
||||
{
|
||||
FFT_512,
|
||||
FFT_256,
|
||||
FFT_128,
|
||||
FFT_64,
|
||||
} fft_point_t;
|
||||
|
||||
typedef enum _fft_direction
|
||||
{
|
||||
FFT_DIR_BACKWARD,
|
||||
FFT_DIR_FORWARD,
|
||||
FFT_DIR_MAX,
|
||||
} fft_direction_t;
|
||||
|
||||
/**
|
||||
* @brief FFT algorithm accelerator register
|
||||
*
|
||||
* @note FFT algorithm accelerator register table
|
||||
*
|
||||
* | Offset | Name | Description |
|
||||
* |-----------|----------------|-------------------------------------|
|
||||
* | 0x00 | fft_input_fifo | input data fifo |
|
||||
* | 0x08 | fft_ctrl | fft ctrl reg |
|
||||
* | 0x10 | fifo_ctrl | fifo ctrl |
|
||||
* | 0x18 | intr_mask | interrupt mask |
|
||||
* | 0x20 | intr_clear | interrupt clear |
|
||||
* | 0x28 | fft_status | fft status reg |
|
||||
* | 0x30 | fft_status_raw | fft_status_raw |
|
||||
* | 0x38 | fft_output_fifo| fft_output_fifo |
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief The calculation data is input through this register
|
||||
*
|
||||
* No. 0 Register (0x00)
|
||||
*/
|
||||
typedef struct _fft_input_fifo
|
||||
{
|
||||
uint64_t fft_input_fifo : 64;
|
||||
} __attribute__((packed, aligned(8))) fft_input_fifo_t;
|
||||
|
||||
/**
|
||||
* @brief fft ctrl reg
|
||||
*
|
||||
* No. 1 Register (0x08)
|
||||
*/
|
||||
typedef struct _fft_fft_ctrl
|
||||
{
|
||||
/**
|
||||
*FFT calculation data length:
|
||||
*b'000:512 point; b'001:256 point; b'010:128 point; b'011:64 point;
|
||||
*/
|
||||
uint64_t fft_point : 3;
|
||||
/* FFT mode: b'0:FFT b'1:IFFT */
|
||||
uint64_t fft_mode : 1;
|
||||
/* Corresponding to the nine layer butterfly shift operation, 0x0: does not shift; 0x1: shift 1st layer. ...*/
|
||||
uint64_t fft_shift : 9;
|
||||
/* FFT enable: b'0:disable b'1:enable */
|
||||
uint64_t fft_enable : 1;
|
||||
/* FFT DMA enable: b'0:disable b'1:enable */
|
||||
uint64_t dma_send : 1;
|
||||
/**
|
||||
*Input data arrangement: b'00:RIRI; b'01:only real part exist, RRRR;
|
||||
*b'10:First input the real part and then input the imaginary part.
|
||||
*/
|
||||
uint64_t fft_input_mode : 2;
|
||||
/* Effective width of input data. b'0:64bit effective; b'1:32bit effective */
|
||||
uint64_t fft_data_mode : 1;
|
||||
uint64_t reserved : 46;
|
||||
} __attribute__((packed, aligned(8))) fft_fft_ctrl_t;
|
||||
|
||||
/**
|
||||
* @brief fifo ctrl
|
||||
*
|
||||
* No. 2 Register (0x10)
|
||||
*/
|
||||
typedef struct _fft_fifo_ctrl
|
||||
{
|
||||
/* Response memory initialization flag.b'1:initialization */
|
||||
uint64_t resp_fifo_flush_n : 1;
|
||||
/* Command memory initialization flag.b'1:initialization */
|
||||
uint64_t cmd_fifo_flush_n : 1;
|
||||
/* Output interface memory initialization flag.b'1:initialization */
|
||||
uint64_t gs_fifo_flush_n : 1;
|
||||
uint64_t reserved : 61;
|
||||
} __attribute__((packed, aligned(8))) fft_fifo_ctrl_t;
|
||||
|
||||
/**
|
||||
* @brief interrupt mask
|
||||
*
|
||||
* No. 3 Register (0x18)
|
||||
*/
|
||||
typedef struct _fft_intr_mask
|
||||
{
|
||||
/**
|
||||
*FFT return status set.
|
||||
*b'0:FFT returns to the state after completion.
|
||||
*b'1:FFT does not return to the state after completion
|
||||
*/
|
||||
uint64_t fft_done_mask : 1;
|
||||
uint64_t reserved : 63;
|
||||
} __attribute__((packed, aligned(8))) fft_intr_mask_t;
|
||||
|
||||
/**
|
||||
* @brief interrupt clear
|
||||
*
|
||||
* No. 4 Register (0x20)
|
||||
*/
|
||||
typedef struct _fft_intr_clear
|
||||
{
|
||||
/* The interrupt state clears. b'1:clear current interrupt request */
|
||||
uint64_t fft_done_clear : 1;
|
||||
uint64_t reserved1 : 63;
|
||||
} __attribute__((packed, aligned(8))) fft_intr_clear_t;
|
||||
|
||||
/**
|
||||
* @brief fft status reg
|
||||
*
|
||||
* No. 5 Register (0x28)
|
||||
*/
|
||||
typedef struct _fft_status
|
||||
{
|
||||
/* FFT calculation state.b'0:not completed; b'1:completed */
|
||||
uint64_t fft_done_status : 1;
|
||||
uint64_t reserved1 : 63;
|
||||
} __attribute__((packed, aligned(8))) fft_status_t;
|
||||
|
||||
/**
|
||||
* @brief fft status raw
|
||||
*
|
||||
* No. 6 Register (0x30)
|
||||
*/
|
||||
typedef struct _fft_status_raw
|
||||
{
|
||||
/* FFT calculation state. b'1:done */
|
||||
uint64_t fft_done_status_raw : 1;
|
||||
/* FFT calculation state. b'1:working */
|
||||
uint64_t fft_work_status_raw : 1;
|
||||
uint64_t reserved : 62;
|
||||
} __attribute__((packed, aligned(8))) fft_status_raw_t;
|
||||
|
||||
/**
|
||||
* @brief Output of FFT calculation data through this register
|
||||
*
|
||||
* No. 7 Register (0x38)
|
||||
*/
|
||||
typedef struct _fft_output_fifo
|
||||
{
|
||||
uint64_t fft_output_fifo : 64;
|
||||
} __attribute__((packed, aligned(8))) fft_output_fifo_t;
|
||||
|
||||
/**
|
||||
* @brief Fast Fourier transform (FFT) algorithm accelerator object
|
||||
*
|
||||
* A fast Fourier transform (FFT) algorithm computes the discrete
|
||||
* Fourier transform (DFT) of a sequence, or its inverse (IFFT).
|
||||
* Fourier analysis converts a signal from its original domain
|
||||
* (often time or space) to a representation in the frequency
|
||||
* domain and vice versa. An FFT rapidly computes such
|
||||
* transformations by factorizing the DFT matrix into a product of
|
||||
* sparse (mostly zero) factors.
|
||||
*/
|
||||
typedef struct _fft
|
||||
{
|
||||
/* No. 0 (0x00): input data fifo */
|
||||
fft_input_fifo_t fft_input_fifo;
|
||||
/* No. 1 (0x08): fft ctrl reg */
|
||||
fft_fft_ctrl_t fft_ctrl;
|
||||
/* No. 2 (0x10): fifo ctrl */
|
||||
fft_fifo_ctrl_t fifo_ctrl;
|
||||
/* No. 3 (0x18): interrupt mask */
|
||||
fft_intr_mask_t intr_mask;
|
||||
/* No. 4 (0x20): interrupt clear */
|
||||
fft_intr_clear_t intr_clear;
|
||||
/* No. 5 (0x28): fft status reg */
|
||||
fft_status_t fft_status;
|
||||
/* No. 6 (0x30): fft_status_raw */
|
||||
fft_status_raw_t fft_status_raw;
|
||||
/* No. 7 (0x38): fft_output_fifo */
|
||||
fft_output_fifo_t fft_output_fifo;
|
||||
} __attribute__((packed, aligned(8))) fft_t;
|
||||
|
||||
/**
|
||||
* @brief Do 16bit quantized complex FFT by DMA
|
||||
*
|
||||
* @param[in] dma_send_channel_num Dmac send channel number.
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] shift The shifts selection in 9 stage
|
||||
* @param[in] direction The direction
|
||||
* @param[in] input The input data
|
||||
* @param[in] point The FFT points count
|
||||
* @param[out] output The output data
|
||||
*/
|
||||
void fft_complex_uint16_dma(dmac_channel_number_t dma_send_channel_num,
|
||||
dmac_channel_number_t dma_receive_channel_num,
|
||||
uint16_t shift,
|
||||
fft_direction_t direction,
|
||||
const uint64_t *input,
|
||||
size_t point_num,
|
||||
uint64_t *output);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_FFT_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,91 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file gpio.c
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "gpio.h"
|
||||
#include "utils.h"
|
||||
#include "fpioa.h"
|
||||
#include "sysctl.h"
|
||||
#define GPIO_MAX_PINNO 8
|
||||
|
||||
volatile gpio_t* const gpio = (volatile gpio_t*)GPIO_BASE_ADDR;
|
||||
|
||||
int gpio_init(void)
|
||||
{
|
||||
return sysctl_clock_enable(SYSCTL_CLOCK_GPIO);
|
||||
}
|
||||
|
||||
void gpio_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode)
|
||||
{
|
||||
ASSERT(pin < GPIO_MAX_PINNO);
|
||||
int io_number = fpioa_get_io_by_function(FUNC_GPIO0 + pin);
|
||||
ASSERT(io_number >= 0);
|
||||
|
||||
fpioa_pull_t pull;
|
||||
uint32_t dir;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case GPIO_DM_INPUT:
|
||||
pull = FPIOA_PULL_NONE;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_INPUT_PULL_DOWN:
|
||||
pull = FPIOA_PULL_DOWN;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_INPUT_PULL_UP:
|
||||
pull = FPIOA_PULL_UP;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_OUTPUT:
|
||||
pull = FPIOA_PULL_DOWN;
|
||||
dir = 1;
|
||||
break;
|
||||
default:
|
||||
ASSERT(!"GPIO drive mode is not supported.");
|
||||
break;
|
||||
}
|
||||
|
||||
fpioa_set_io_pull(io_number, pull);
|
||||
set_gpio_bit(gpio->direction.u32, pin, dir);
|
||||
}
|
||||
|
||||
gpio_pin_value_t gpio_get_pin(uint8_t pin)
|
||||
{
|
||||
ASSERT(pin < GPIO_MAX_PINNO);
|
||||
uint32_t dir = get_gpio_bit(gpio->direction.u32, pin);
|
||||
volatile uint32_t *reg = dir ? gpio->data_output.u32 : gpio->data_input.u32;
|
||||
return get_gpio_bit(reg, pin);
|
||||
}
|
||||
|
||||
void gpio_set_pin(uint8_t pin, gpio_pin_value_t value)
|
||||
{
|
||||
ASSERT(pin < GPIO_MAX_PINNO);
|
||||
uint32_t dir = get_gpio_bit(gpio->direction.u32, pin);
|
||||
volatile uint32_t *reg = dir ? gpio->data_output.u32 : gpio->data_input.u32;
|
||||
ASSERT(dir == 1);
|
||||
set_gpio_bit(reg, pin, value);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file gpio.h
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#ifndef _DRIVER_GPIO_H
|
||||
#define _DRIVER_GPIO_H
|
||||
|
||||
#include "platform.h"
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
#include "gpio_common.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Structure for accessing GPIO registers by individual bit
|
||||
*/
|
||||
typedef struct _gpio_bits
|
||||
{
|
||||
uint32_t b0 : 1;
|
||||
uint32_t b1 : 1;
|
||||
uint32_t b2 : 1;
|
||||
uint32_t b3 : 1;
|
||||
uint32_t b4 : 1;
|
||||
uint32_t b5 : 1;
|
||||
uint32_t b6 : 1;
|
||||
uint32_t b7 : 1;
|
||||
uint32_t b8 : 1;
|
||||
uint32_t b9 : 1;
|
||||
uint32_t b10 : 1;
|
||||
uint32_t b11 : 1;
|
||||
uint32_t b12 : 1;
|
||||
uint32_t b13 : 1;
|
||||
uint32_t b14 : 1;
|
||||
uint32_t b15 : 1;
|
||||
uint32_t b16 : 1;
|
||||
uint32_t b17 : 1;
|
||||
uint32_t b18 : 1;
|
||||
uint32_t b19 : 1;
|
||||
uint32_t b20 : 1;
|
||||
uint32_t b21 : 1;
|
||||
uint32_t b22 : 1;
|
||||
uint32_t b23 : 1;
|
||||
uint32_t b24 : 1;
|
||||
uint32_t b25 : 1;
|
||||
uint32_t b26 : 1;
|
||||
uint32_t b27 : 1;
|
||||
uint32_t b28 : 1;
|
||||
uint32_t b29 : 1;
|
||||
uint32_t b30 : 1;
|
||||
uint32_t b31 : 1;
|
||||
} __attribute__((packed, aligned(4))) gpio_bits_t;
|
||||
|
||||
/**
|
||||
* @brief Structure of templates for accessing GPIO registers
|
||||
*/
|
||||
typedef union _gpio_access_tp
|
||||
{
|
||||
/* 32x1 bit mode */
|
||||
uint32_t u32[1];
|
||||
/* 16x2 bit mode */
|
||||
uint16_t u16[2];
|
||||
/* 8x4 bit mode */
|
||||
uint8_t u8[4];
|
||||
/* 1 bit mode */
|
||||
gpio_bits_t bits;
|
||||
} __attribute__((packed, aligned(4))) gpio_access_tp_t;
|
||||
|
||||
/**
|
||||
* @brief The GPIO address map
|
||||
*/
|
||||
typedef struct _gpio
|
||||
{
|
||||
/* Offset 0x00: Data (output) registers */
|
||||
gpio_access_tp_t data_output;
|
||||
/* Offset 0x04: Data direction registers */
|
||||
gpio_access_tp_t direction;
|
||||
/* Offset 0x08: Data source registers */
|
||||
gpio_access_tp_t source;
|
||||
/* Offset 0x10 - 0x2f: Unused registers, 9x4 bytes */
|
||||
uint32_t unused_0[9];
|
||||
/* Offset 0x30: Interrupt enable/disable registers */
|
||||
gpio_access_tp_t interrupt_enable;
|
||||
/* Offset 0x34: Interrupt mask registers */
|
||||
gpio_access_tp_t interrupt_mask;
|
||||
/* Offset 0x38: Interrupt level registers */
|
||||
gpio_access_tp_t interrupt_level;
|
||||
/* Offset 0x3c: Interrupt polarity registers */
|
||||
gpio_access_tp_t interrupt_polarity;
|
||||
/* Offset 0x40: Interrupt status registers */
|
||||
gpio_access_tp_t interrupt_status;
|
||||
/* Offset 0x44: Raw interrupt status registers */
|
||||
gpio_access_tp_t interrupt_status_raw;
|
||||
/* Offset 0x48: Interrupt debounce registers */
|
||||
gpio_access_tp_t interrupt_debounce;
|
||||
/* Offset 0x4c: Registers for clearing interrupts */
|
||||
gpio_access_tp_t interrupt_clear;
|
||||
/* Offset 0x50: External port (data input) registers */
|
||||
gpio_access_tp_t data_input;
|
||||
/* Offset 0x54 - 0x5f: Unused registers, 3x4 bytes */
|
||||
uint32_t unused_1[3];
|
||||
/* Offset 0x60: Sync level registers */
|
||||
gpio_access_tp_t sync_level;
|
||||
/* Offset 0x64: ID code */
|
||||
gpio_access_tp_t id_code;
|
||||
/* Offset 0x68: Interrupt both edge type */
|
||||
gpio_access_tp_t interrupt_bothedge;
|
||||
|
||||
} __attribute__((packed, aligned(4))) gpio_t;
|
||||
|
||||
/**
|
||||
* @brief Bus GPIO object instance
|
||||
*/
|
||||
extern volatile gpio_t *const gpio;
|
||||
|
||||
/**
|
||||
* @brief Gpio initialize
|
||||
*
|
||||
* @return Result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int gpio_init(void);
|
||||
|
||||
/**
|
||||
* @brief Set Gpio drive mode
|
||||
*
|
||||
* @param[in] pin Gpio pin
|
||||
* @param[in] mode Gpio pin drive mode
|
||||
*/
|
||||
void gpio_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Get Gpio pin value
|
||||
*
|
||||
* @param[in] pin Gpio pin
|
||||
* @return Pin value
|
||||
*
|
||||
* - GPIO_PV_Low Gpio pin low
|
||||
* - GPIO_PV_High Gpio pin high
|
||||
*/
|
||||
gpio_pin_value_t gpio_get_pin(uint8_t pin);
|
||||
|
||||
/**
|
||||
* @brief Set Gpio pin value
|
||||
*
|
||||
* @param[in] pin Gpio pin
|
||||
* @param[in] value Gpio pin value
|
||||
*/
|
||||
void gpio_set_pin(uint8_t pin, gpio_pin_value_t value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_GPIO_H */
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file gpio_common.h
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#ifndef _GPIO_COMMON_H
|
||||
#define _GPIO_COMMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum _gpio_drive_mode
|
||||
{
|
||||
GPIO_DM_INPUT,
|
||||
GPIO_DM_INPUT_PULL_DOWN,
|
||||
GPIO_DM_INPUT_PULL_UP,
|
||||
GPIO_DM_OUTPUT,
|
||||
} gpio_drive_mode_t;
|
||||
|
||||
typedef enum _gpio_pin_edge
|
||||
{
|
||||
GPIO_PE_NONE,
|
||||
GPIO_PE_FALLING,
|
||||
GPIO_PE_RISING,
|
||||
GPIO_PE_BOTH,
|
||||
GPIO_PE_LOW,
|
||||
GPIO_PE_HIGH = 8,
|
||||
} gpio_pin_edge_t;
|
||||
|
||||
typedef enum _gpio_pin_value
|
||||
{
|
||||
GPIO_PV_LOW,
|
||||
GPIO_PV_HIGH
|
||||
} gpio_pin_value_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _GPIO_COMMON_H */
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file gpiohs.c
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "fpioa.h"
|
||||
#include "gpiohs.h"
|
||||
#include "sysctl.h"
|
||||
#include "utils.h"
|
||||
#include <nuttx/arch.h>
|
||||
#include <arch/irq.h>
|
||||
#define GPIOHS_MAX_PINNO 32
|
||||
|
||||
volatile gpiohs_t *const gpiohs = (volatile gpiohs_t *)GPIOHS_BASE_ADDR;
|
||||
|
||||
typedef struct _gpiohs_pin_instance
|
||||
{
|
||||
size_t pin;
|
||||
gpio_pin_edge_t edge;
|
||||
void (*callback)(void);
|
||||
plic_irq_callback_t gpiohs_callback;
|
||||
void *context;
|
||||
} gpiohs_pin_instance_t;
|
||||
|
||||
static gpiohs_pin_instance_t pin_instance[32];
|
||||
|
||||
void gpiohs_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode)
|
||||
{
|
||||
ASSERT(pin < GPIOHS_MAX_PINNO);
|
||||
int io_number = fpioa_get_io_by_function(FUNC_GPIOHS0 + pin);
|
||||
ASSERT(io_number >= 0);
|
||||
|
||||
fpioa_pull_t pull;
|
||||
uint32_t dir;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case GPIO_DM_INPUT:
|
||||
pull = FPIOA_PULL_NONE;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_INPUT_PULL_DOWN:
|
||||
pull = FPIOA_PULL_DOWN;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_INPUT_PULL_UP:
|
||||
pull = FPIOA_PULL_UP;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_OUTPUT:
|
||||
pull = FPIOA_PULL_DOWN;
|
||||
dir = 1;
|
||||
break;
|
||||
default:
|
||||
ASSERT(!"GPIO drive mode is not supported.");
|
||||
break;
|
||||
}
|
||||
|
||||
fpioa_set_io_pull(io_number, pull);
|
||||
volatile uint32_t *reg = dir ? gpiohs->output_en.u32 : gpiohs->input_en.u32;
|
||||
volatile uint32_t *reg_d = !dir ? gpiohs->output_en.u32 : gpiohs->input_en.u32;
|
||||
set_gpio_bit(reg_d, pin, 0);
|
||||
set_gpio_bit(reg, pin, 1);
|
||||
}
|
||||
|
||||
gpio_pin_value_t gpiohs_get_pin(uint8_t pin)
|
||||
{
|
||||
ASSERT(pin < GPIOHS_MAX_PINNO);
|
||||
return get_gpio_bit(gpiohs->input_val.u32, pin);
|
||||
}
|
||||
|
||||
void gpiohs_set_pin(uint8_t pin, gpio_pin_value_t value)
|
||||
{
|
||||
ASSERT(pin < GPIOHS_MAX_PINNO);
|
||||
set_gpio_bit(gpiohs->output_val.u32, pin, value);
|
||||
}
|
||||
|
||||
void gpiohs_set_pin_edge(uint8_t pin, gpio_pin_edge_t edge)
|
||||
{
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->rise_ip.u32, pin, 1);
|
||||
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->fall_ip.u32, pin, 1);
|
||||
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->low_ip.u32, pin, 1);
|
||||
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->high_ip.u32, pin, 1);
|
||||
|
||||
if(edge & GPIO_PE_FALLING)
|
||||
{
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 1);
|
||||
} else
|
||||
{
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 0);
|
||||
}
|
||||
|
||||
if(edge & GPIO_PE_RISING)
|
||||
{
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 1);
|
||||
} else
|
||||
{
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 0);
|
||||
}
|
||||
|
||||
if(edge & GPIO_PE_LOW)
|
||||
{
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 1);
|
||||
} else
|
||||
{
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 0);
|
||||
}
|
||||
|
||||
if(edge & GPIO_PE_HIGH)
|
||||
{
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 1);
|
||||
} else
|
||||
{
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 0);
|
||||
}
|
||||
|
||||
pin_instance[pin].edge = edge;
|
||||
}
|
||||
|
||||
int gpiohs_pin_onchange_isr(int irq, void *userdata, void *arg)
|
||||
{
|
||||
gpiohs_pin_instance_t *ctx = (gpiohs_pin_instance_t *)userdata;
|
||||
size_t pin = ctx->pin;
|
||||
|
||||
if(ctx->edge & GPIO_PE_FALLING)
|
||||
{
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->fall_ip.u32, pin, 1);
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 1);
|
||||
}
|
||||
|
||||
if(ctx->edge & GPIO_PE_RISING)
|
||||
{
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->rise_ip.u32, pin, 1);
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 1);
|
||||
}
|
||||
|
||||
if(ctx->edge & GPIO_PE_LOW)
|
||||
{
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->low_ip.u32, pin, 1);
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 1);
|
||||
}
|
||||
|
||||
if(ctx->edge & GPIO_PE_HIGH)
|
||||
{
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->high_ip.u32, pin, 1);
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 1);
|
||||
}
|
||||
|
||||
if(ctx->callback)
|
||||
ctx->callback();
|
||||
if(ctx->gpiohs_callback)
|
||||
ctx->gpiohs_callback(ctx->context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gpiohs_set_irq(uint8_t pin, uint32_t priority, void (*func)(void))
|
||||
{
|
||||
|
||||
int ret;
|
||||
pin_instance[pin].pin = pin;
|
||||
pin_instance[pin].callback = func;
|
||||
|
||||
plic_set_priority(IRQN_GPIOHS0_INTERRUPT + pin, priority);
|
||||
ret = irq_attach(IRQN_GPIOHS0_INTERRUPT + pin, gpiohs_pin_onchange_isr, &(pin_instance[pin]));
|
||||
if (ret == OK)
|
||||
{
|
||||
up_enable_irq(IRQN_GPIOHS0_INTERRUPT + pin);
|
||||
}
|
||||
}
|
||||
|
||||
void gpiohs_irq_register(uint8_t pin, uint32_t priority, plic_irq_callback_t callback, void *ctx)
|
||||
{
|
||||
int ret;
|
||||
pin_instance[pin].pin = pin;
|
||||
pin_instance[pin].gpiohs_callback = callback;
|
||||
pin_instance[pin].context = ctx;
|
||||
|
||||
plic_set_priority(IRQN_GPIOHS0_INTERRUPT + pin, priority);
|
||||
ret = irq_attach(IRQN_GPIOHS0_INTERRUPT + pin, gpiohs_pin_onchange_isr, &(pin_instance[pin]));
|
||||
if (ret == OK)
|
||||
{
|
||||
up_enable_irq(IRQN_GPIOHS0_INTERRUPT + pin);
|
||||
}
|
||||
}
|
||||
|
||||
void gpiohs_irq_unregister(uint8_t pin)
|
||||
{
|
||||
pin_instance[pin] = (gpiohs_pin_instance_t){
|
||||
.callback = NULL,
|
||||
.gpiohs_callback = NULL,
|
||||
.context = NULL,
|
||||
};
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 0);
|
||||
up_disable_irq(IRQN_GPIOHS0_INTERRUPT + pin);
|
||||
irq_detach(IRQN_GPIOHS0_INTERRUPT + pin);
|
||||
}
|
||||
|
||||
void gpiohs_irq_disable(size_t pin)
|
||||
{
|
||||
plic_irq_disable(IRQN_GPIOHS0_INTERRUPT + pin);
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file gpiohs.h
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#ifndef _DRIVER_GPIOHS_H
|
||||
#define _DRIVER_GPIOHS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "gpio_common.h"
|
||||
#include "platform.h"
|
||||
#include "plic.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
/* Register address offsets */
|
||||
#define GPIOHS_INPUT_VAL (0x00)
|
||||
#define GPIOHS_INPUT_EN (0x04)
|
||||
#define GPIOHS_OUTPUT_EN (0x08)
|
||||
#define GPIOHS_OUTPUT_VAL (0x0C)
|
||||
#define GPIOHS_PULLUP_EN (0x10)
|
||||
#define GPIOHS_DRIVE (0x14)
|
||||
#define GPIOHS_RISE_IE (0x18)
|
||||
#define GPIOHS_RISE_IP (0x1C)
|
||||
#define GPIOHS_FALL_IE (0x20)
|
||||
#define GPIOHS_FALL_IP (0x24)
|
||||
#define GPIOHS_HIGH_IE (0x28)
|
||||
#define GPIOHS_HIGH_IP (0x2C)
|
||||
#define GPIOHS_LOW_IE (0x30)
|
||||
#define GPIOHS_LOW_IP (0x34)
|
||||
#define GPIOHS_IOF_EN (0x38)
|
||||
#define GPIOHS_IOF_SEL (0x3C)
|
||||
#define GPIOHS_OUTPUT_XOR (0x40)
|
||||
/* clang-format on */
|
||||
|
||||
/**
|
||||
* @brief GPIO bits raw object
|
||||
*/
|
||||
typedef struct _gpiohs_raw
|
||||
{
|
||||
/* Address offset 0x00 */
|
||||
uint32_t input_val;
|
||||
/* Address offset 0x04 */
|
||||
uint32_t input_en;
|
||||
/* Address offset 0x08 */
|
||||
uint32_t output_en;
|
||||
/* Address offset 0x0c */
|
||||
uint32_t output_val;
|
||||
/* Address offset 0x10 */
|
||||
uint32_t pullup_en;
|
||||
/* Address offset 0x14 */
|
||||
uint32_t drive;
|
||||
/* Address offset 0x18 */
|
||||
uint32_t rise_ie;
|
||||
/* Address offset 0x1c */
|
||||
uint32_t rise_ip;
|
||||
/* Address offset 0x20 */
|
||||
uint32_t fall_ie;
|
||||
/* Address offset 0x24 */
|
||||
uint32_t fall_ip;
|
||||
/* Address offset 0x28 */
|
||||
uint32_t high_ie;
|
||||
/* Address offset 0x2c */
|
||||
uint32_t high_ip;
|
||||
/* Address offset 0x30 */
|
||||
uint32_t low_ie;
|
||||
/* Address offset 0x34 */
|
||||
uint32_t low_ip;
|
||||
/* Address offset 0x38 */
|
||||
uint32_t iof_en;
|
||||
/* Address offset 0x3c */
|
||||
uint32_t iof_sel;
|
||||
/* Address offset 0x40 */
|
||||
uint32_t output_xor;
|
||||
} __attribute__((packed, aligned(4))) gpiohs_raw_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO bits object
|
||||
*/
|
||||
typedef struct _gpiohs_bits
|
||||
{
|
||||
uint32_t b0 : 1;
|
||||
uint32_t b1 : 1;
|
||||
uint32_t b2 : 1;
|
||||
uint32_t b3 : 1;
|
||||
uint32_t b4 : 1;
|
||||
uint32_t b5 : 1;
|
||||
uint32_t b6 : 1;
|
||||
uint32_t b7 : 1;
|
||||
uint32_t b8 : 1;
|
||||
uint32_t b9 : 1;
|
||||
uint32_t b10 : 1;
|
||||
uint32_t b11 : 1;
|
||||
uint32_t b12 : 1;
|
||||
uint32_t b13 : 1;
|
||||
uint32_t b14 : 1;
|
||||
uint32_t b15 : 1;
|
||||
uint32_t b16 : 1;
|
||||
uint32_t b17 : 1;
|
||||
uint32_t b18 : 1;
|
||||
uint32_t b19 : 1;
|
||||
uint32_t b20 : 1;
|
||||
uint32_t b21 : 1;
|
||||
uint32_t b22 : 1;
|
||||
uint32_t b23 : 1;
|
||||
uint32_t b24 : 1;
|
||||
uint32_t b25 : 1;
|
||||
uint32_t b26 : 1;
|
||||
uint32_t b27 : 1;
|
||||
uint32_t b28 : 1;
|
||||
uint32_t b29 : 1;
|
||||
uint32_t b30 : 1;
|
||||
uint32_t b31 : 1;
|
||||
} __attribute__((packed, aligned(4))) gpiohs_bits_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO bits multi access union
|
||||
*/
|
||||
typedef union _gpiohs_u32
|
||||
{
|
||||
/* 32x1 bit mode */
|
||||
uint32_t u32[1];
|
||||
/* 16x2 bit mode */
|
||||
uint16_t u16[2];
|
||||
/* 8x4 bit mode */
|
||||
uint8_t u8[4];
|
||||
/* 1 bit mode */
|
||||
gpiohs_bits_t bits;
|
||||
} __attribute__((packed, aligned(4))) gpiohs_u32_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO object
|
||||
*
|
||||
* The GPIO controller is a peripheral device mapped in the
|
||||
* internal memory map, discoverable in the Configuration String.
|
||||
* It is responsible for low-level configuration of the actual
|
||||
* GPIO pads on the device (direction, pull up-enable, and drive
|
||||
* value), as well as selecting between various sources of the
|
||||
* controls for these signals. The GPIO controller allows seperate
|
||||
* configuration of each of N GPIO bits.
|
||||
*
|
||||
* Once the interrupt is pending, it will remain set until a 1 is
|
||||
* written to the *_ip register at that bit.
|
||||
*/
|
||||
|
||||
typedef struct _gpiohs
|
||||
{
|
||||
/* Address offset 0x00, Input Values */
|
||||
gpiohs_u32_t input_val;
|
||||
/* Address offset 0x04, Input enable */
|
||||
gpiohs_u32_t input_en;
|
||||
/* Address offset 0x08, Output enable */
|
||||
gpiohs_u32_t output_en;
|
||||
/* Address offset 0x0c, Onput Values */
|
||||
gpiohs_u32_t output_val;
|
||||
/* Address offset 0x10, Internal Pull-Ups enable */
|
||||
gpiohs_u32_t pullup_en;
|
||||
/* Address offset 0x14, Drive Strength */
|
||||
gpiohs_u32_t drive;
|
||||
/* Address offset 0x18, Rise interrupt enable */
|
||||
gpiohs_u32_t rise_ie;
|
||||
/* Address offset 0x1c, Rise interrupt pending */
|
||||
gpiohs_u32_t rise_ip;
|
||||
/* Address offset 0x20, Fall interrupt enable */
|
||||
gpiohs_u32_t fall_ie;
|
||||
/* Address offset 0x24, Fall interrupt pending */
|
||||
gpiohs_u32_t fall_ip;
|
||||
/* Address offset 0x28, High interrupt enable */
|
||||
gpiohs_u32_t high_ie;
|
||||
/* Address offset 0x2c, High interrupt pending */
|
||||
gpiohs_u32_t high_ip;
|
||||
/* Address offset 0x30, Low interrupt enable */
|
||||
gpiohs_u32_t low_ie;
|
||||
/* Address offset 0x34, Low interrupt pending */
|
||||
gpiohs_u32_t low_ip;
|
||||
/* Address offset 0x38, HW I/O Function enable */
|
||||
gpiohs_u32_t iof_en;
|
||||
/* Address offset 0x3c, HW I/O Function select */
|
||||
gpiohs_u32_t iof_sel;
|
||||
/* Address offset 0x40, Output XOR (invert) */
|
||||
gpiohs_u32_t output_xor;
|
||||
} __attribute__((packed, aligned(4))) gpiohs_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO High-speed object instanse
|
||||
*/
|
||||
extern volatile gpiohs_t *const gpiohs;
|
||||
|
||||
/**
|
||||
* @brief Set Gpiohs drive mode
|
||||
*
|
||||
* @param[in] pin Gpiohs pin
|
||||
* @param[in] mode Gpiohs pin drive mode
|
||||
*/
|
||||
void gpiohs_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Get Gpiohs pin value
|
||||
*
|
||||
* @param[in] pin Gpiohs pin
|
||||
* @return Pin value
|
||||
*
|
||||
* - GPIO_PV_Low Gpiohs pin low
|
||||
* - GPIO_PV_High Gpiohs pin high
|
||||
*/
|
||||
gpio_pin_value_t gpiohs_get_pin(uint8_t pin);
|
||||
|
||||
/**
|
||||
* @brief Set Gpiohs pin value
|
||||
*
|
||||
* @param[in] pin Gpiohs pin
|
||||
* @param[in] value Gpiohs pin value
|
||||
*/
|
||||
void gpiohs_set_pin(uint8_t pin, gpio_pin_value_t value);
|
||||
|
||||
/**
|
||||
* @brief Set Gpiohs pin edge for interrupt
|
||||
*
|
||||
* @param[in] pin Gpiohs pin
|
||||
* @param[in] edge Gpiohs pin edge type
|
||||
*/
|
||||
void gpiohs_set_pin_edge(uint8_t pin, gpio_pin_edge_t edge);
|
||||
|
||||
/**
|
||||
* @brief Set Gpiohs pin interrupt
|
||||
*
|
||||
* @param[in] pin Gpiohs pin
|
||||
* @param[in] priority Gpiohs pin interrupt priority
|
||||
* @param[in] func Gpiohs pin interrupt service routine
|
||||
*/
|
||||
void gpiohs_set_irq(uint8_t pin, uint32_t priority, void (*func)(void));
|
||||
|
||||
/**
|
||||
* @brief Set Gpiohs pin interrupt
|
||||
*
|
||||
* @param[in] pin Gpiohs pin
|
||||
* @param[in] priority Gpiohs pin interrupt priority
|
||||
* @param[in] callback Gpiohs pin interrupt service routine
|
||||
* @param[in] ctx Gpiohs interrupt param
|
||||
*/
|
||||
void gpiohs_irq_register(uint8_t pin, uint32_t priority, plic_irq_callback_t callback, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief Unregister Gpiohs pin interrupt
|
||||
*
|
||||
* @param[in] pin Gpiohs pin
|
||||
*/
|
||||
void gpiohs_irq_unregister(uint8_t pin);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_GPIOHS_H */
|
||||
@@ -0,0 +1,719 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file i2s.c
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include "i2s.h"
|
||||
#include "sysctl.h"
|
||||
#include "stdlib.h"
|
||||
#include "utils.h"
|
||||
|
||||
volatile i2s_t *const i2s[3] =
|
||||
{
|
||||
(volatile i2s_t *)I2S0_BASE_ADDR,
|
||||
(volatile i2s_t *)I2S1_BASE_ADDR,
|
||||
(volatile i2s_t *)I2S2_BASE_ADDR
|
||||
};
|
||||
|
||||
typedef struct _i2s_instance
|
||||
{
|
||||
i2s_device_number_t i2s_num;
|
||||
i2s_transfer_mode_t transfer_mode;
|
||||
dmac_channel_number_t dmac_channel;
|
||||
plic_instance_t i2s_int_instance;
|
||||
} i2s_instance_t;
|
||||
|
||||
static i2s_instance_t g_i2s_send_instance[3];
|
||||
static i2s_instance_t g_i2s_recv_instance[3];
|
||||
|
||||
static int i2s_recv_channel_enable(i2s_device_number_t device_num,
|
||||
i2s_channel_num_t channel_num, uint32_t enable)
|
||||
{
|
||||
rer_t u_rer;
|
||||
|
||||
if (channel_num < I2S_CHANNEL_0 || channel_num > I2S_CHANNEL_3)
|
||||
return -1;
|
||||
u_rer.reg_data = readl(&i2s[device_num]->channel[channel_num].rer);
|
||||
u_rer.rer.rxchenx = enable;
|
||||
writel(u_rer.reg_data, &i2s[device_num]->channel[channel_num].rer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2s_transmit_channel_enable(i2s_device_number_t device_num,
|
||||
i2s_channel_num_t channel_num, uint32_t enable)
|
||||
{
|
||||
ter_t u_ter;
|
||||
|
||||
if (channel_num < I2S_CHANNEL_0 || channel_num > I2S_CHANNEL_3)
|
||||
return -1;
|
||||
|
||||
u_ter.reg_data = readl(&i2s[device_num]->channel[channel_num].ter);
|
||||
u_ter.ter.txchenx = enable;
|
||||
writel(u_ter.reg_data, &i2s[device_num]->channel[channel_num].ter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void i2s_receive_enable(i2s_device_number_t device_num, i2s_channel_num_t channel_num)
|
||||
{
|
||||
irer_t u_irer;
|
||||
|
||||
u_irer.reg_data = readl(&i2s[device_num]->irer);
|
||||
u_irer.irer.rxen = 1;
|
||||
writel(u_irer.reg_data, &i2s[device_num]->irer);
|
||||
/* Receiver block enable */
|
||||
|
||||
i2s_recv_channel_enable(device_num, channel_num, 1);
|
||||
/* Receive channel enable */
|
||||
}
|
||||
|
||||
static void i2s_transimit_enable(i2s_device_number_t device_num, i2s_channel_num_t channel_num)
|
||||
{
|
||||
iter_t u_iter;
|
||||
|
||||
u_iter.reg_data = readl(&i2s[device_num]->iter);
|
||||
u_iter.iter.txen = 1;
|
||||
writel(u_iter.reg_data, &i2s[device_num]->iter);
|
||||
/* Transmitter block enable */
|
||||
|
||||
i2s_transmit_channel_enable(device_num, channel_num, 1);
|
||||
/* Transmit channel enable */
|
||||
}
|
||||
|
||||
static void i2s_set_enable(i2s_device_number_t device_num, uint32_t enable)
|
||||
{
|
||||
ier_t u_ier;
|
||||
|
||||
u_ier.reg_data = readl(&i2s[device_num]->ier);
|
||||
u_ier.ier.ien = enable;
|
||||
writel(u_ier.reg_data, &i2s[device_num]->ier);
|
||||
}
|
||||
|
||||
static void i2s_disable_block(i2s_device_number_t device_num, i2s_transmit_t rxtx_mode)
|
||||
{
|
||||
irer_t u_irer;
|
||||
iter_t u_iter;
|
||||
|
||||
if (rxtx_mode == I2S_RECEIVER)
|
||||
{
|
||||
u_irer.reg_data = readl(&i2s[device_num]->irer);
|
||||
u_irer.irer.rxen = 0;
|
||||
writel(u_irer.reg_data, &i2s[device_num]->irer);
|
||||
/* Receiver block disable */
|
||||
}
|
||||
else
|
||||
{
|
||||
u_iter.reg_data = readl(&i2s[device_num]->iter);
|
||||
u_iter.iter.txen = 0;
|
||||
writel(u_iter.reg_data, &i2s[device_num]->iter);
|
||||
/* Transmitter block disable */
|
||||
}
|
||||
}
|
||||
|
||||
static int i2s_set_rx_word_length(i2s_device_number_t device_num,
|
||||
i2s_word_length_t word_length,
|
||||
i2s_channel_num_t channel_num)
|
||||
{
|
||||
rcr_tcr_t u_rcr;
|
||||
|
||||
if (word_length > RESOLUTION_32_BIT || word_length < IGNORE_WORD_LENGTH)
|
||||
return -1;
|
||||
if (channel_num < I2S_CHANNEL_0 || channel_num > I2S_CHANNEL_3)
|
||||
return -1;
|
||||
|
||||
u_rcr.reg_data = readl(&i2s[device_num]->channel[channel_num].rcr);
|
||||
u_rcr.rcr_tcr.wlen = word_length;
|
||||
writel(u_rcr.reg_data, &i2s[device_num]->channel[channel_num].rcr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2s_set_tx_word_length(i2s_device_number_t device_num,
|
||||
i2s_word_length_t word_length,
|
||||
i2s_channel_num_t channel_num)
|
||||
{
|
||||
rcr_tcr_t u_tcr;
|
||||
|
||||
if (word_length > RESOLUTION_32_BIT || word_length < IGNORE_WORD_LENGTH)
|
||||
return -1;
|
||||
if (channel_num < I2S_CHANNEL_0 || channel_num > I2S_CHANNEL_3)
|
||||
return -1;
|
||||
|
||||
u_tcr.reg_data = readl(&i2s[device_num]->channel[channel_num].tcr);
|
||||
u_tcr.rcr_tcr.wlen = word_length;
|
||||
writel(u_tcr.reg_data, &i2s[device_num]->channel[channel_num].tcr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void i2s_master_configure(i2s_device_number_t device_num,
|
||||
i2s_word_select_cycles_t word_select_size,
|
||||
i2s_sclk_gating_cycles_t gating_cycles,
|
||||
i2s_work_mode_t word_mode)
|
||||
{
|
||||
ASSERT(!(word_select_size < SCLK_CYCLES_16 ||
|
||||
word_select_size > SCLK_CYCLES_32));
|
||||
ASSERT(!(gating_cycles < NO_CLOCK_GATING ||
|
||||
gating_cycles > CLOCK_CYCLES_24));
|
||||
|
||||
ccr_t u_ccr;
|
||||
cer_t u_cer;
|
||||
|
||||
u_ccr.reg_data = readl(&i2s[device_num]->ccr);
|
||||
u_ccr.ccr.clk_word_size = word_select_size;
|
||||
u_ccr.ccr.clk_gate = gating_cycles;
|
||||
u_ccr.ccr.align_mode = word_mode;
|
||||
writel(u_ccr.reg_data, &i2s[device_num]->ccr);
|
||||
|
||||
u_cer.reg_data = readl(&i2s[device_num]->cer);
|
||||
u_cer.cer.clken = 1;
|
||||
writel(u_cer.reg_data, &i2s[device_num]->cer);
|
||||
/* Clock generation enable */
|
||||
|
||||
}
|
||||
|
||||
static int i2s_set_rx_threshold(i2s_device_number_t device_num,
|
||||
i2s_fifo_threshold_t threshold,
|
||||
i2s_channel_num_t channel_num)
|
||||
{
|
||||
rfcr_t u_rfcr;
|
||||
|
||||
if (threshold < TRIGGER_LEVEL_1 || threshold > TRIGGER_LEVEL_16)
|
||||
return -1;
|
||||
if (channel_num < I2S_CHANNEL_0 || channel_num > I2S_CHANNEL_3)
|
||||
return -1;
|
||||
|
||||
u_rfcr.reg_data = readl(&i2s[device_num]->channel[channel_num].rfcr);
|
||||
u_rfcr.rfcr.rxchdt = threshold;
|
||||
writel(u_rfcr.reg_data, &i2s[device_num]->channel[channel_num].rfcr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2s_set_tx_threshold(i2s_device_number_t device_num,
|
||||
i2s_fifo_threshold_t threshold,
|
||||
i2s_channel_num_t channel_num)
|
||||
{
|
||||
tfcr_t u_tfcr;
|
||||
|
||||
if (threshold < TRIGGER_LEVEL_1 || threshold > TRIGGER_LEVEL_16)
|
||||
return -1;
|
||||
if (channel_num < I2S_CHANNEL_0 || channel_num > I2S_CHANNEL_3)
|
||||
return -1;
|
||||
|
||||
u_tfcr.reg_data = readl(&i2s[device_num]->channel[channel_num].tfcr);
|
||||
u_tfcr.tfcr.txchet = threshold;
|
||||
writel(u_tfcr.reg_data, &i2s[device_num]->channel[channel_num].tfcr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2s_set_mask_interrupt(i2s_device_number_t device_num,
|
||||
i2s_channel_num_t channel_num,
|
||||
uint32_t rx_available_int, uint32_t rx_overrun_int,
|
||||
uint32_t tx_empty_int, uint32_t tx_overrun_int)
|
||||
{
|
||||
imr_t u_imr;
|
||||
|
||||
if (channel_num < I2S_CHANNEL_0 || channel_num > I2S_CHANNEL_3)
|
||||
return -1;
|
||||
u_imr.reg_data = readl(&i2s[device_num]->channel[channel_num].imr);
|
||||
|
||||
if (rx_available_int == 1)
|
||||
u_imr.imr.rxdam = 1;
|
||||
else
|
||||
u_imr.imr.rxdam = 0;
|
||||
if (rx_overrun_int == 1)
|
||||
u_imr.imr.rxfom = 1;
|
||||
else
|
||||
u_imr.imr.rxfom = 0;
|
||||
|
||||
if (tx_empty_int == 1)
|
||||
u_imr.imr.txfem = 1;
|
||||
else
|
||||
u_imr.imr.txfem = 0;
|
||||
if (tx_overrun_int == 1)
|
||||
u_imr.imr.txfom = 1;
|
||||
else
|
||||
u_imr.imr.txfom = 0;
|
||||
writel(u_imr.reg_data, &i2s[device_num]->channel[channel_num].imr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2s_transmit_dma_enable(i2s_device_number_t device_num, uint32_t enable)
|
||||
{
|
||||
ccr_t u_ccr;
|
||||
|
||||
if (device_num >= I2S_DEVICE_MAX)
|
||||
return -1;
|
||||
|
||||
u_ccr.reg_data = readl(&i2s[device_num]->ccr);
|
||||
u_ccr.ccr.dma_tx_en = enable;
|
||||
writel(u_ccr.reg_data, &i2s[device_num]->ccr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2s_receive_dma_enable(i2s_device_number_t device_num, uint32_t enable)
|
||||
{
|
||||
ccr_t u_ccr;
|
||||
|
||||
if (device_num >= I2S_DEVICE_MAX)
|
||||
return -1;
|
||||
|
||||
u_ccr.reg_data = readl(&i2s[device_num]->ccr);
|
||||
u_ccr.ccr.dma_rx_en = enable;
|
||||
writel(u_ccr.reg_data, &i2s[device_num]->ccr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2s_set_dma_divide_16(i2s_device_number_t device_num, uint32_t enable)
|
||||
{
|
||||
ccr_t u_ccr;
|
||||
|
||||
if (device_num >= I2S_DEVICE_MAX)
|
||||
return -1;
|
||||
|
||||
u_ccr.reg_data = readl(&i2s[device_num]->ccr);
|
||||
u_ccr.ccr.dma_divide_16 = enable;
|
||||
writel(u_ccr.reg_data, &i2s[device_num]->ccr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2s_get_dma_divide_16(i2s_device_number_t device_num)
|
||||
{
|
||||
if (device_num >= I2S_DEVICE_MAX)
|
||||
return -1;
|
||||
ccr_t u_ccr;
|
||||
u_ccr.reg_data = readl(&i2s[device_num]->ccr);
|
||||
return u_ccr.ccr.dma_divide_16;
|
||||
}
|
||||
|
||||
int i2s_receive_data(i2s_device_number_t device_num, i2s_channel_num_t channel_num, uint64_t *buf, size_t buf_len)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
isr_t u_isr;
|
||||
|
||||
readl(&i2s[device_num]->channel[channel_num].ror);
|
||||
/*clear over run*/
|
||||
|
||||
for (i = 0; i < buf_len;)
|
||||
{
|
||||
u_isr.reg_data = readl(&i2s[device_num]->channel[channel_num].isr);
|
||||
if (u_isr.isr.rxda == 1)
|
||||
{
|
||||
buf[i] = readl(&i2s[device_num]->channel[channel_num].left_rxtx);
|
||||
buf[i] <<= 32;
|
||||
buf[i++] |= readl(&i2s[device_num]->channel[channel_num].right_rxtx);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i2s_receive_data_dma(i2s_device_number_t device_num, uint32_t *buf,
|
||||
size_t buf_len, dmac_channel_number_t channel_num)
|
||||
{
|
||||
dmac_wait_idle(channel_num);
|
||||
sysctl_dma_select((sysctl_dma_channel_t)channel_num, SYSCTL_DMA_SELECT_I2S0_RX_REQ + device_num * 2);
|
||||
dmac_set_single_mode(channel_num, (void *)(&i2s[device_num]->rxdma), buf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, buf_len);
|
||||
}
|
||||
|
||||
int i2s_rx_to_tx(i2s_device_number_t device_src_num, i2s_device_number_t device_dest_num,
|
||||
size_t buf_len, dmac_channel_number_t channel_num)
|
||||
{
|
||||
static uint8_t dmac_recv_flag[6] = {0,0,0,0,0,0};
|
||||
if(dmac_recv_flag[channel_num])
|
||||
dmac_wait_done(channel_num);
|
||||
else
|
||||
dmac_recv_flag[channel_num] = 1;
|
||||
sysctl_dma_select((sysctl_dma_channel_t)channel_num, SYSCTL_DMA_SELECT_I2S0_RX_REQ + device_src_num * 2);
|
||||
dmac_set_single_mode(channel_num, (void *)(&i2s[device_src_num]->rxdma), (void *)(&i2s[device_dest_num]->txdma), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE,
|
||||
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, buf_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2s_send_data(i2s_device_number_t device_num, i2s_channel_num_t channel_num, const uint8_t *pcm, size_t buf_len,
|
||||
size_t single_length)
|
||||
{
|
||||
isr_t u_isr;
|
||||
uint32_t left_buffer = 0;
|
||||
uint32_t right_buffer = 0;
|
||||
uint32_t i = 0;
|
||||
uint32_t j = 0;
|
||||
if (channel_num < I2S_CHANNEL_0 || channel_num > I2S_CHANNEL_3)
|
||||
return -1;
|
||||
|
||||
buf_len = buf_len / (single_length / 8) / 2; /* sample num */
|
||||
readl(&i2s[device_num]->channel[channel_num].tor);
|
||||
/* read clear overrun flag */
|
||||
|
||||
for (j = 0; j < buf_len;)
|
||||
{
|
||||
u_isr.reg_data = readl(&i2s[device_num]->channel[channel_num].isr);
|
||||
if (u_isr.isr.txfe == 1)
|
||||
{
|
||||
switch(single_length)
|
||||
{
|
||||
case 16:
|
||||
left_buffer = ((uint16_t *)pcm)[i++];
|
||||
right_buffer = ((uint16_t *)pcm)[i++];
|
||||
break;
|
||||
case 24:
|
||||
left_buffer = 0;
|
||||
left_buffer |= pcm[i++];
|
||||
left_buffer |= pcm[i++] << 8;
|
||||
left_buffer |= pcm[i++] << 16;
|
||||
right_buffer = 0;
|
||||
right_buffer |= pcm[i++];
|
||||
right_buffer |= pcm[i++] << 8;
|
||||
right_buffer |= pcm[i++] << 16;
|
||||
break;
|
||||
case 32:
|
||||
left_buffer = ((uint32_t *)pcm)[i++];
|
||||
right_buffer = ((uint32_t *)pcm)[i++];
|
||||
break;
|
||||
default:
|
||||
left_buffer = pcm[i++];
|
||||
right_buffer = pcm[i++];
|
||||
break;
|
||||
}
|
||||
writel(left_buffer, &i2s[device_num]->channel[channel_num].left_rxtx);
|
||||
writel(right_buffer, &i2s[device_num]->channel[channel_num].right_rxtx);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i2s_send_data_dma(i2s_device_number_t device_num, const void *buf, size_t buf_len, dmac_channel_number_t channel_num)
|
||||
{
|
||||
|
||||
dmac_wait_idle(channel_num);
|
||||
sysctl_dma_select((sysctl_dma_channel_t)channel_num, SYSCTL_DMA_SELECT_I2S0_TX_REQ + device_num * 2);
|
||||
dmac_set_single_mode(channel_num, buf, (void *)(&i2s[device_num]->txdma), DMAC_ADDR_INCREMENT,
|
||||
DMAC_ADDR_NOCHANGE, DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, buf_len);
|
||||
}
|
||||
|
||||
static void i2s_parse_voice(i2s_device_number_t device_num, uint32_t *buf, const uint8_t *pcm, size_t length, size_t bits_per_sample,
|
||||
uint8_t track_num, size_t *send_len)
|
||||
{
|
||||
uint32_t i,j=0;
|
||||
*send_len = length * 2;
|
||||
switch(bits_per_sample)
|
||||
{
|
||||
case 16:
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
buf[2*i] = ((uint16_t *)pcm)[i];
|
||||
buf[2*i+1] = 0;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
buf[2*i] = 0;
|
||||
buf[2*i] |= pcm[j++];
|
||||
buf[2*i] |= pcm[j++] << 8;
|
||||
buf[2*i] |= pcm[j++] << 16;
|
||||
buf[2*i+1] = 0;
|
||||
if(track_num == 2)
|
||||
{
|
||||
buf[2*i+1] |= pcm[j++];
|
||||
buf[2*i+1] |= pcm[j++] << 8;
|
||||
buf[2*i+1] |= pcm[j++] << 16;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
default:
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
buf[2*i] = ((uint32_t *)pcm)[i];
|
||||
buf[2*i+1] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void i2s_play(i2s_device_number_t device_num, dmac_channel_number_t channel_num,
|
||||
const uint8_t *buf, size_t buf_len, size_t frame, size_t bits_per_sample, uint8_t track_num)
|
||||
{
|
||||
const uint8_t *trans_buf;
|
||||
uint32_t i;
|
||||
size_t sample_cnt = buf_len / ( bits_per_sample / 8 ) / track_num;
|
||||
size_t frame_cnt = sample_cnt / frame;
|
||||
size_t frame_remain = sample_cnt % frame;
|
||||
i2s_set_dma_divide_16(device_num, 0);
|
||||
|
||||
if (bits_per_sample == 16 && track_num == 2)
|
||||
{
|
||||
i2s_set_dma_divide_16(device_num, 1);
|
||||
for (i = 0; i < frame_cnt; i++)
|
||||
{
|
||||
trans_buf = buf + i * frame * (bits_per_sample / 8) * track_num;
|
||||
i2s_send_data_dma(device_num,trans_buf, frame, channel_num);
|
||||
}
|
||||
if(frame_remain)
|
||||
{
|
||||
trans_buf = buf + frame_cnt * frame * (bits_per_sample / 8) * track_num;
|
||||
i2s_send_data_dma(device_num, trans_buf, frame_remain, channel_num);
|
||||
}
|
||||
}
|
||||
else if (bits_per_sample == 32 && track_num == 2)
|
||||
{
|
||||
for (i = 0; i < frame_cnt; i++)
|
||||
{
|
||||
trans_buf = buf + i * frame * (bits_per_sample / 8) * track_num;
|
||||
i2s_send_data_dma(device_num,trans_buf, frame * 2, channel_num);
|
||||
}
|
||||
if(frame_remain)
|
||||
{
|
||||
trans_buf = buf + frame_cnt * frame * (bits_per_sample / 8) * track_num;
|
||||
i2s_send_data_dma(device_num, trans_buf, frame_remain * 2, channel_num);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t *buff[2];
|
||||
buff[0] = malloc(frame * 2 * sizeof(uint32_t) * 2);
|
||||
buff[1] = buff[0] + frame * 2;
|
||||
uint8_t flag = 0;
|
||||
size_t send_len = 0;
|
||||
for (i = 0; i < frame_cnt; i++)
|
||||
{
|
||||
trans_buf = buf + i * frame * (bits_per_sample / 8) * track_num;
|
||||
i2s_parse_voice(device_num, buff[flag], trans_buf, frame, bits_per_sample, track_num, &send_len);
|
||||
i2s_send_data_dma(device_num,buff[flag], send_len, channel_num);
|
||||
flag = !flag;
|
||||
}
|
||||
if (frame_remain)
|
||||
{
|
||||
trans_buf = buf + frame_cnt * frame * (bits_per_sample / 8) * track_num;
|
||||
i2s_parse_voice(device_num, buff[flag], trans_buf, frame_remain, bits_per_sample, track_num, &send_len);
|
||||
i2s_send_data_dma(device_num, trans_buf, send_len, channel_num);
|
||||
}
|
||||
free(buff[0]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void i2s_set_sign_expand_en(i2s_device_number_t device_num, uint32_t enable)
|
||||
{
|
||||
ccr_t u_ccr;
|
||||
u_ccr.reg_data = readl(&i2s[device_num]->ccr);
|
||||
u_ccr.ccr.sign_expand_en = enable;
|
||||
writel(u_ccr.reg_data, &i2s[device_num]->ccr);
|
||||
}
|
||||
|
||||
void i2s_rx_channel_config(i2s_device_number_t device_num,
|
||||
i2s_channel_num_t channel_num,
|
||||
i2s_word_length_t word_length,
|
||||
i2s_word_select_cycles_t word_select_size,
|
||||
i2s_fifo_threshold_t trigger_level,
|
||||
i2s_work_mode_t word_mode)
|
||||
{
|
||||
i2s_recv_channel_enable(device_num, channel_num, 0);
|
||||
/* Receive channel disable */
|
||||
|
||||
writel(0, &i2s[device_num]->channel[channel_num].ter);
|
||||
/* disable tx */
|
||||
|
||||
writel(1, &i2s[device_num]->channel[channel_num].rff);
|
||||
/* flash individual fifo */
|
||||
|
||||
writel(1, &i2s[device_num]->rxffr);
|
||||
/* flush tx fifo*/
|
||||
|
||||
i2s_set_rx_word_length(device_num, word_length, channel_num);
|
||||
/* Word buf_len is RESOLUTION_32_BIT */
|
||||
|
||||
i2s_master_configure(device_num,
|
||||
word_select_size, NO_CLOCK_GATING, word_mode);
|
||||
/* word select size is 32 bits,no clock gating */
|
||||
|
||||
i2s_set_rx_threshold(device_num, trigger_level, channel_num);
|
||||
/* Interrupt trigger when FIFO level is 8 */
|
||||
|
||||
readl(&i2s[device_num]->channel[channel_num].ror);
|
||||
readl(&i2s[device_num]->channel[channel_num].tor);
|
||||
|
||||
i2s_recv_channel_enable(device_num, channel_num, 1);
|
||||
}
|
||||
|
||||
void i2s_tx_channel_config(i2s_device_number_t device_num,
|
||||
i2s_channel_num_t channel_num,
|
||||
i2s_word_length_t word_length,
|
||||
i2s_word_select_cycles_t word_select_size,
|
||||
i2s_fifo_threshold_t trigger_level,
|
||||
i2s_work_mode_t word_mode)
|
||||
{
|
||||
writel(0, &i2s[device_num]->channel[channel_num].rer);
|
||||
/* disable rx */
|
||||
|
||||
i2s_transmit_channel_enable(device_num, channel_num, 0);
|
||||
/* Transmit channel disable */
|
||||
|
||||
writel(1, &i2s[device_num]->txffr);
|
||||
/* flush tx fifo */
|
||||
writel(1, &i2s[device_num]->channel[channel_num].tff);
|
||||
/* flush individual fifo */
|
||||
|
||||
i2s_set_tx_word_length(device_num, word_length, channel_num);
|
||||
/* Word buf_len is RESOLUTION_16_BIT */
|
||||
|
||||
i2s_master_configure(device_num, word_select_size, NO_CLOCK_GATING, word_mode);
|
||||
/* word select size is 16 bits,gating after 16 bit */
|
||||
|
||||
i2s_set_tx_threshold(device_num, trigger_level, channel_num);
|
||||
/* Interrupt trigger when FIFO level is 8 */
|
||||
|
||||
i2s_transmit_channel_enable(device_num, channel_num, 1);
|
||||
}
|
||||
|
||||
void i2s_init(i2s_device_number_t device_num, i2s_transmit_t rxtx_mode, uint32_t channel_mask)
|
||||
{
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_I2S0 + device_num);
|
||||
sysctl_reset(SYSCTL_RESET_I2S0 + device_num);
|
||||
sysctl_clock_set_threshold(SYSCTL_THRESHOLD_I2S0 + device_num, 7);
|
||||
/*96k:5,44k:12,24k:23,22k:25 16k:35 sampling*/
|
||||
/*sample rate*32bit*2 =75MHz/((N+1)*2) */
|
||||
i2s_set_enable(device_num, 1);
|
||||
i2s_disable_block(device_num, I2S_TRANSMITTER);
|
||||
i2s_disable_block(device_num, I2S_RECEIVER);
|
||||
|
||||
if (rxtx_mode == I2S_TRANSMITTER)
|
||||
{
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
if ((channel_mask & 0x3) == 0x3)
|
||||
{
|
||||
i2s_set_mask_interrupt(device_num, I2S_CHANNEL_0 + i, 1, 1, 1, 1);
|
||||
i2s_transimit_enable(device_num, I2S_CHANNEL_0 + i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i2s_transmit_channel_enable(device_num, I2S_CHANNEL_0 + i, 0);
|
||||
}
|
||||
channel_mask >>= 2;
|
||||
}
|
||||
i2s_transmit_dma_enable(device_num, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
if ((channel_mask & 0x3) == 0x3)
|
||||
{
|
||||
i2s_set_mask_interrupt(device_num, I2S_CHANNEL_0 + i, 1, 1, 1, 1);
|
||||
i2s_receive_enable(device_num, I2S_CHANNEL_0 + i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i2s_recv_channel_enable(device_num, I2S_CHANNEL_0 + i, 0);
|
||||
}
|
||||
channel_mask >>= 2;
|
||||
}
|
||||
/* Set expand_en when receive */
|
||||
i2s_set_sign_expand_en(device_num, 1);
|
||||
i2s_receive_dma_enable(device_num, 1);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t i2s_set_sample_rate(i2s_device_number_t device_num, uint32_t sample_rate)
|
||||
{
|
||||
ccr_t u_ccr;
|
||||
uint32_t pll2_clock = 0;
|
||||
pll2_clock = sysctl_pll_get_freq(SYSCTL_PLL2);
|
||||
|
||||
u_ccr.reg_data = readl(&i2s[device_num]->ccr);
|
||||
/* 0x0 for 16sclk cycles, 0x1 for 24 sclk cycles 0x2 for 32 sclk */
|
||||
uint32_t v_clk_word_size = (u_ccr.ccr.clk_word_size + 2) * 8;
|
||||
uint32_t threshold = round(pll2_clock / (sample_rate * 2.0 * v_clk_word_size * 2.0) - 1);
|
||||
sysctl_clock_set_threshold(SYSCTL_THRESHOLD_I2S0 + device_num, threshold);
|
||||
return sysctl_clock_get_freq(SYSCTL_CLOCK_I2S0 + device_num);
|
||||
}
|
||||
|
||||
int i2s_dmac_irq(void *ctx)
|
||||
{
|
||||
i2s_instance_t *v_instance = (i2s_instance_t *)ctx;
|
||||
dmac_irq_unregister(v_instance->dmac_channel);
|
||||
if(v_instance->i2s_int_instance.callback)
|
||||
{
|
||||
v_instance->i2s_int_instance.callback(v_instance->i2s_int_instance.ctx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i2s_handle_data_dma(i2s_device_number_t device_num, i2s_data_t data, plic_interrupt_t *cb)
|
||||
{
|
||||
ASSERT(device_num < I2S_DEVICE_MAX);
|
||||
if(data.transfer_mode == I2S_SEND)
|
||||
{
|
||||
ASSERT(data.tx_buf && data.tx_len);
|
||||
if(!data.nowait_dma_idle)
|
||||
{
|
||||
dmac_wait_idle(data.tx_channel);
|
||||
}
|
||||
if(cb)
|
||||
{
|
||||
g_i2s_send_instance[device_num].i2s_int_instance.callback = cb->callback;
|
||||
g_i2s_send_instance[device_num].i2s_int_instance.ctx = cb->ctx;
|
||||
g_i2s_send_instance[device_num].dmac_channel = data.tx_channel;
|
||||
g_i2s_send_instance[device_num].transfer_mode = I2S_SEND;
|
||||
dmac_irq_register(data.tx_channel, i2s_dmac_irq, &g_i2s_send_instance[device_num], cb->priority);
|
||||
}
|
||||
sysctl_dma_select((sysctl_dma_channel_t)data.tx_channel, SYSCTL_DMA_SELECT_I2S0_TX_REQ + device_num * 2);
|
||||
dmac_set_single_mode(data.tx_channel, data.tx_buf, (void *)(&i2s[device_num]->txdma), DMAC_ADDR_INCREMENT,
|
||||
DMAC_ADDR_NOCHANGE, DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, data.tx_len);
|
||||
if(!cb && data.wait_dma_done)
|
||||
{
|
||||
dmac_wait_done(data.tx_channel);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(data.rx_buf && data.rx_len);
|
||||
if(!data.nowait_dma_idle)
|
||||
{
|
||||
dmac_wait_idle(data.rx_channel);
|
||||
}
|
||||
if(cb)
|
||||
{
|
||||
g_i2s_recv_instance[device_num].i2s_int_instance.callback = cb->callback;
|
||||
g_i2s_recv_instance[device_num].i2s_int_instance.ctx = cb->ctx;
|
||||
g_i2s_recv_instance[device_num].dmac_channel = data.rx_channel;
|
||||
g_i2s_recv_instance[device_num].transfer_mode = I2S_RECEIVE;
|
||||
dmac_irq_register(data.rx_channel, i2s_dmac_irq, &g_i2s_recv_instance[device_num], cb->priority);
|
||||
}
|
||||
sysctl_dma_select((sysctl_dma_channel_t)data.rx_channel, SYSCTL_DMA_SELECT_I2S0_RX_REQ + device_num * 2);
|
||||
dmac_set_single_mode(data.rx_channel, (void *)(&i2s[device_num]->rxdma), data.rx_buf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, data.rx_len);
|
||||
if(!cb && data.wait_dma_done)
|
||||
{
|
||||
dmac_wait_done(data.rx_channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,793 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file i2s.h
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#ifndef _DRIVER_I2S_H
|
||||
#define _DRIVER_I2S_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "platform.h"
|
||||
#include "io.h"
|
||||
#include "dmac.h"
|
||||
#include "bsp.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define I2S0_IN_D0 90
|
||||
#define I2S0_SCLK 88
|
||||
#define I2S0_WS 89
|
||||
|
||||
typedef enum _i2s_device_number
|
||||
{
|
||||
I2S_DEVICE_0 = 0,
|
||||
I2S_DEVICE_1 = 1,
|
||||
I2S_DEVICE_2 = 2,
|
||||
I2S_DEVICE_MAX
|
||||
} i2s_device_number_t;
|
||||
|
||||
typedef enum _i2s_channel_num
|
||||
{
|
||||
I2S_CHANNEL_0 = 0,
|
||||
I2S_CHANNEL_1 = 1,
|
||||
I2S_CHANNEL_2 = 2,
|
||||
I2S_CHANNEL_3 = 3
|
||||
} i2s_channel_num_t;
|
||||
|
||||
typedef enum _i2s_transmit
|
||||
{
|
||||
I2S_TRANSMITTER = 0,
|
||||
I2S_RECEIVER = 1
|
||||
} i2s_transmit_t;
|
||||
|
||||
typedef enum _i2s_work_mode
|
||||
{
|
||||
STANDARD_MODE = 1,
|
||||
RIGHT_JUSTIFYING_MODE = 2,
|
||||
LEFT_JUSTIFYING_MODE = 4
|
||||
} i2s_work_mode_t;
|
||||
|
||||
typedef enum _sclk_gating_cycles
|
||||
{
|
||||
/* Clock gating is diable */
|
||||
NO_CLOCK_GATING = 0x0,
|
||||
/* Gating after 12 sclk cycles */
|
||||
CLOCK_CYCLES_12 = 0x1,
|
||||
/* Gating after 16 sclk cycles */
|
||||
CLOCK_CYCLES_16 = 0x2,
|
||||
/* Gating after 20 sclk cycles */
|
||||
CLOCK_CYCLES_20 = 0x3,
|
||||
/* Gating after 24 sclk cycles */
|
||||
CLOCK_CYCLES_24 = 0x4
|
||||
} i2s_sclk_gating_cycles_t;
|
||||
|
||||
typedef enum _word_select_cycles
|
||||
{
|
||||
/* 16 sclk cycles */
|
||||
SCLK_CYCLES_16 = 0x0,
|
||||
/* 24 sclk cycles */
|
||||
SCLK_CYCLES_24 = 0x1,
|
||||
/* 32 sclk cycles */
|
||||
SCLK_CYCLES_32 = 0x2
|
||||
} i2s_word_select_cycles_t;
|
||||
|
||||
typedef enum _word_length
|
||||
{
|
||||
/* Ignore the word length */
|
||||
IGNORE_WORD_LENGTH = 0x0,
|
||||
/* 12-bit data resolution of the receiver */
|
||||
RESOLUTION_12_BIT = 0x1,
|
||||
/* 16-bit data resolution of the receiver */
|
||||
RESOLUTION_16_BIT = 0x2,
|
||||
/* 20-bit data resolution of the receiver */
|
||||
RESOLUTION_20_BIT = 0x3,
|
||||
/* 24-bit data resolution of the receiver */
|
||||
RESOLUTION_24_BIT = 0x4,
|
||||
/* 32-bit data resolution of the receiver */
|
||||
RESOLUTION_32_BIT = 0x5
|
||||
} i2s_word_length_t;
|
||||
|
||||
typedef enum _fifo_threshold
|
||||
{
|
||||
/* Interrupt trigger when FIFO level is 1 */
|
||||
TRIGGER_LEVEL_1 = 0x0,
|
||||
/* Interrupt trigger when FIFO level is 2 */
|
||||
TRIGGER_LEVEL_2 = 0x1,
|
||||
/* Interrupt trigger when FIFO level is 3 */
|
||||
TRIGGER_LEVEL_3 = 0x2,
|
||||
/* Interrupt trigger when FIFO level is 4 */
|
||||
TRIGGER_LEVEL_4 = 0x3,
|
||||
/* Interrupt trigger when FIFO level is 5 */
|
||||
TRIGGER_LEVEL_5 = 0x4,
|
||||
/* Interrupt trigger when FIFO level is 6 */
|
||||
TRIGGER_LEVEL_6 = 0x5,
|
||||
/* Interrupt trigger when FIFO level is 7 */
|
||||
TRIGGER_LEVEL_7 = 0x6,
|
||||
/* Interrupt trigger when FIFO level is 8 */
|
||||
TRIGGER_LEVEL_8 = 0x7,
|
||||
/* Interrupt trigger when FIFO level is 9 */
|
||||
TRIGGER_LEVEL_9 = 0x8,
|
||||
/* Interrupt trigger when FIFO level is 10 */
|
||||
TRIGGER_LEVEL_10 = 0x9,
|
||||
/* Interrupt trigger when FIFO level is 11 */
|
||||
TRIGGER_LEVEL_11 = 0xa,
|
||||
/* Interrupt trigger when FIFO level is 12 */
|
||||
TRIGGER_LEVEL_12 = 0xb,
|
||||
/* Interrupt trigger when FIFO level is 13 */
|
||||
TRIGGER_LEVEL_13 = 0xc,
|
||||
/* Interrupt trigger when FIFO level is 14 */
|
||||
TRIGGER_LEVEL_14 = 0xd,
|
||||
/* Interrupt trigger when FIFO level is 15 */
|
||||
TRIGGER_LEVEL_15 = 0xe,
|
||||
/* Interrupt trigger when FIFO level is 16 */
|
||||
TRIGGER_LEVEL_16 = 0xf
|
||||
} i2s_fifo_threshold_t;
|
||||
|
||||
|
||||
typedef struct _i2s_ier
|
||||
{
|
||||
/* Bit 0 is ien, 0 for disable i2s and 1 for enable i2s */
|
||||
uint32_t ien : 1;
|
||||
/* Bits [31:1] is reserved */
|
||||
uint32_t resv : 31;
|
||||
} __attribute__((packed, aligned(4))) i2s_ier_t;
|
||||
|
||||
typedef union _ier_u
|
||||
{
|
||||
i2s_ier_t ier;
|
||||
uint32_t reg_data;
|
||||
} ier_t;
|
||||
|
||||
typedef struct _i2s_irer
|
||||
{
|
||||
/* Bit 0 is receiver block enable,
|
||||
* 0 for receiver disable
|
||||
* 1 for receiver enable
|
||||
*/
|
||||
uint32_t rxen : 1;
|
||||
/* Bits [31:1] is reserved */
|
||||
uint32_t resv : 31;
|
||||
} __attribute__((packed, aligned(4))) i2s_irer_t;
|
||||
|
||||
typedef union _irer_u
|
||||
{
|
||||
i2s_irer_t irer;
|
||||
uint32_t reg_data;
|
||||
} irer_t;
|
||||
|
||||
typedef struct _i2s_iter
|
||||
{
|
||||
uint32_t txen : 1;
|
||||
/* Bit 0 is transmitter block enable,
|
||||
* 0 for transmitter disable
|
||||
* 1 for transmitter enable
|
||||
*/
|
||||
uint32_t resv : 31;
|
||||
/* Bits [31:1] is reserved */
|
||||
} __attribute__((packed, aligned(4))) i2s_iter_t;
|
||||
|
||||
typedef union _iter_u
|
||||
{
|
||||
i2s_iter_t iter;
|
||||
uint32_t reg_data;
|
||||
} iter_t;
|
||||
|
||||
typedef struct _i2s_cer
|
||||
{
|
||||
uint32_t clken : 1;
|
||||
/* Bit 0 is clock generation enable/disable,
|
||||
* 0 for clock generation disable,
|
||||
* 1 for clock generation enable
|
||||
*/
|
||||
uint32_t resv : 31;
|
||||
/* Bits [31:1] is reserved */
|
||||
} __attribute__((packed, aligned(4))) i2s_cer_t;
|
||||
|
||||
typedef union _cer_u
|
||||
{
|
||||
i2s_cer_t cer;
|
||||
uint32_t reg_data;
|
||||
} cer_t;
|
||||
|
||||
typedef struct _i2s_ccr
|
||||
{
|
||||
/* Bits [2:0] is used to program the gating of sclk,
|
||||
* 0x0 for clock gating is diable,
|
||||
* 0x1 for gating after 12 sclk cycles
|
||||
* 0x2 for gating after 16 sclk cycles
|
||||
* 0x3 for gating after 20 sclk cycles
|
||||
* 0x4 for gating after 24 sclk cycles
|
||||
*/
|
||||
uint32_t clk_gate : 3;
|
||||
/* Bits [4:3] used program the number of sclk cycles for which the
|
||||
* word select line stayd in the left aligned or right aligned mode.
|
||||
* 0x0 for 16sclk cycles, 0x1 for 24 sclk cycles 0x2 for 32 sclk
|
||||
* cycles
|
||||
*/
|
||||
uint32_t clk_word_size : 2;
|
||||
/* Bit[5:7] is alignment mode setting.
|
||||
* 0x1 for standard i2s format
|
||||
* 0x2 for right aligned format
|
||||
* 0x4 for left aligned format
|
||||
*/
|
||||
uint32_t align_mode : 3;
|
||||
/* Bit[8] is DMA transmit enable control */
|
||||
uint32_t dma_tx_en : 1;
|
||||
/* Bit[9] is DMA receive enable control */
|
||||
uint32_t dma_rx_en : 1;
|
||||
uint32_t dma_divide_16 : 1;
|
||||
/* Bit[10] split 32bit data to two 16 bit data and filled in left
|
||||
* and right channel. Used with dma_tx_en or dma_rx_en
|
||||
*/
|
||||
uint32_t sign_expand_en : 1;
|
||||
uint32_t resv : 20;
|
||||
/* Bits [31:11] is reseved */
|
||||
} __attribute__((packed, aligned(4))) i2s_ccr_t;
|
||||
|
||||
typedef union _ccr_u
|
||||
{
|
||||
i2s_ccr_t ccr;
|
||||
uint32_t reg_data;
|
||||
} ccr_t;
|
||||
|
||||
typedef struct _i2s_rxffr
|
||||
{
|
||||
uint32_t rxffr : 1;
|
||||
/* Bit 0 is receiver FIFO reset,
|
||||
* 0 for does not flush RX FIFO, 1 for flush RX FIFO
|
||||
*/
|
||||
uint32_t resv : 31;
|
||||
/* Bits [31:1] is reserved */
|
||||
} __attribute__((packed, aligned(4))) i2s_rxffr_t;
|
||||
|
||||
typedef union _rxffr_u
|
||||
{
|
||||
i2s_rxffr_t rxffr;
|
||||
uint32_t reg_data;
|
||||
} rxffr_t;
|
||||
|
||||
typedef struct _i2s_lrbrthr
|
||||
{
|
||||
uint32_t fifo : 16;
|
||||
/* Bits [15:0] if used data receive or transmit */
|
||||
uint32_t resv : 16;
|
||||
} i2s_lrbrthr_t;
|
||||
|
||||
typedef union _lrbthr_u
|
||||
{
|
||||
i2s_lrbrthr_t buffer;
|
||||
uint32_t reg_data;
|
||||
} lrbthr_t;
|
||||
|
||||
typedef struct _i2s_rthr
|
||||
{
|
||||
/* Bits [15:0] is right stereo data transmitted serially
|
||||
* from transmit channel input
|
||||
*/
|
||||
uint32_t rthrx : 16;
|
||||
/* Bits [31:16] is reserved */
|
||||
uint32_t resv : 16;
|
||||
} __attribute__((packed, aligned(4))) i2s_rthr_t;
|
||||
|
||||
typedef union _rthr_u
|
||||
{
|
||||
i2s_rthr_t rthr;
|
||||
uint32_t reg_data;
|
||||
} rthr_t;
|
||||
|
||||
typedef struct _i2s_rer
|
||||
{
|
||||
/* Bit 0 is receive channel enable/disable, 0 for receive channel disable,
|
||||
*1 for receive channel enable
|
||||
*/
|
||||
uint32_t rxchenx : 1;
|
||||
/* Bits [31:1] is reseved */
|
||||
uint32_t resv : 31;
|
||||
} __attribute__((packed, aligned(4))) i2s_rer_t;
|
||||
|
||||
typedef union _rer_u
|
||||
{
|
||||
i2s_rer_t rer;
|
||||
uint32_t reg_data;
|
||||
} rer_t;
|
||||
|
||||
typedef struct _i2s_ter
|
||||
{
|
||||
/* Bit 0 is transmit channel enable/disable, 0 for transmit channel disable,
|
||||
* 1 for transmit channel enable
|
||||
*/
|
||||
uint32_t txchenx : 1;
|
||||
/* Bits [31:1] is reseved */
|
||||
uint32_t resv : 31;
|
||||
} __attribute__((packed, aligned(4))) i2s_ter_t;
|
||||
|
||||
typedef union _ter_u
|
||||
{
|
||||
i2s_ter_t ter;
|
||||
uint32_t reg_data;
|
||||
} ter_t;
|
||||
|
||||
typedef struct _i2s_rcr_tcr
|
||||
{
|
||||
/* Bits [2:0] is used to program desired data resolution of
|
||||
* receiver/transmitter,
|
||||
* 0x0 for ignore the word length
|
||||
* 0x1 for 12-bit data resolution of the receiver/transmitter,
|
||||
* 0x2 for 16-bit data resolution of the receiver/transmitter,
|
||||
* 0x3 for 20-bit data resolution of the receiver/transmitter,
|
||||
* 0x4 for 24-bit data resolution of the receiver/transmitter,
|
||||
* 0x5 for 32-bit data resolution of the receiver/transmitter
|
||||
*/
|
||||
uint32_t wlen : 3;
|
||||
/* Bits [31:3] is reseved */
|
||||
uint32_t resv : 29;
|
||||
} __attribute__((packed, aligned(4))) i2s_rcr_tcr_t;
|
||||
|
||||
typedef union _rcr_tcr_u {
|
||||
i2s_rcr_tcr_t rcr_tcr;
|
||||
uint32_t reg_data;
|
||||
} rcr_tcr_t;
|
||||
|
||||
typedef struct _i2s_isr
|
||||
{
|
||||
/* Bit 0 is status of receiver data avaliable interrupt
|
||||
* 0x0 for RX FIFO trigger level not reached
|
||||
* 0x1 for RX FIFO trigger level is reached
|
||||
*/
|
||||
uint32_t rxda : 1;
|
||||
/* Bit 1 is status of data overrun interrupt for rx channel
|
||||
* 0x0 for RX FIFO write valid
|
||||
* 0x1 for RX FIFO write overrun
|
||||
*/
|
||||
uint32_t rxfo : 1;
|
||||
/* Bits [3:2] is reserved */
|
||||
uint32_t resv1 : 2;
|
||||
/* Bit 4 is status of transmit empty triger interrupt
|
||||
* 0x0 for TX FIFO triiger level is reach
|
||||
* 0x1 for TX FIFO trigger level is not reached
|
||||
*/
|
||||
uint32_t txfe : 1;
|
||||
/* BIt 5 is status of data overrun interrupt for the TX channel
|
||||
* 0x0 for TX FIFO write valid
|
||||
* 0x1 for TX FIFO write overrun
|
||||
*/
|
||||
uint32_t txfo : 1;
|
||||
/* BIts [31:6] is reserved */
|
||||
uint32_t resv2 : 26;
|
||||
} __attribute__((packed, aligned(4))) i2s_isr_t;
|
||||
|
||||
typedef union _isr_u
|
||||
{
|
||||
i2s_isr_t isr;
|
||||
uint32_t reg_data;
|
||||
} isr_t;
|
||||
|
||||
typedef struct _i2s_imr
|
||||
{
|
||||
/* Bit 0 is mask RX FIFO data available interrupt
|
||||
* 0x0 for unmask RX FIFO data available interrupt
|
||||
* 0x1 for mask RX FIFO data available interrupt
|
||||
*/
|
||||
uint32_t rxdam : 1;
|
||||
/* Bit 1 is mask RX FIFO overrun interrupt
|
||||
* 0x0 for unmask RX FIFO overrun interrupt
|
||||
* 0x1 for mask RX FIFO overrun interrupt
|
||||
*/
|
||||
uint32_t rxfom : 1;
|
||||
/* Bits [3:2] is reserved */
|
||||
uint32_t resv1 : 2;
|
||||
/* Bit 4 is mask TX FIFO empty interrupt,
|
||||
* 0x0 for unmask TX FIFO empty interrupt,
|
||||
* 0x1 for mask TX FIFO empty interrupt
|
||||
*/
|
||||
uint32_t txfem : 1;
|
||||
/* BIt 5 is mask TX FIFO overrun interrupt
|
||||
* 0x0 for mask TX FIFO overrun interrupt
|
||||
* 0x1 for unmash TX FIFO overrun interrupt
|
||||
*/
|
||||
uint32_t txfom : 1;
|
||||
/* Bits [31:6] is reserved */
|
||||
uint32_t resv2 : 26;
|
||||
} __attribute__((packed, aligned(4))) i2s_imr_t;
|
||||
|
||||
typedef union _imr_u
|
||||
{
|
||||
i2s_imr_t imr;
|
||||
uint32_t reg_data;
|
||||
} imr_t;
|
||||
|
||||
typedef struct _i2s_ror
|
||||
{
|
||||
/* Bit 0 is read this bit to clear RX FIFO data overrun interrupt
|
||||
* 0x0 for RX FIFO write valid,
|
||||
*0x1 for RX FIFO write overrun
|
||||
*/
|
||||
uint32_t rxcho : 1;
|
||||
/* Bits [31:1] is reserved */
|
||||
uint32_t resv : 31;
|
||||
} __attribute__((packed, aligned(4))) i2s_ror_t;
|
||||
|
||||
typedef union _ror_u
|
||||
{
|
||||
i2s_ror_t ror;
|
||||
uint32_t reg_data;
|
||||
} ror_t;
|
||||
|
||||
typedef struct _i2s_tor
|
||||
{
|
||||
/* Bit 0 is read this bit to clear TX FIFO data overrun interrupt
|
||||
* 0x0 for TX FIFO write valid,
|
||||
*0x1 for TX FIFO write overrun
|
||||
*/
|
||||
uint32_t txcho : 1;
|
||||
/* Bits [31:1] is reserved */
|
||||
uint32_t resv : 31;
|
||||
} __attribute__((packed, aligned(4))) i2s_tor_t;
|
||||
|
||||
typedef union _tor_u
|
||||
{
|
||||
i2s_tor_t tor;
|
||||
uint32_t reg_data;
|
||||
} tor_t;
|
||||
|
||||
typedef struct _i2s_rfcr
|
||||
{
|
||||
/* Bits [3:0] is used program the trigger level in the RX FIFO at
|
||||
* which the receiver data available interrupt generate,
|
||||
* 0x0 for interrupt trigger when FIFO level is 1,
|
||||
* 0x2 for interrupt trigger when FIFO level is 2,
|
||||
* 0x3 for interrupt trigger when FIFO level is 4,
|
||||
* 0x4 for interrupt trigger when FIFO level is 5,
|
||||
* 0x5 for interrupt trigger when FIFO level is 6,
|
||||
* 0x6 for interrupt trigger when FIFO level is 7,
|
||||
* 0x7 for interrupt trigger when FIFO level is 8,
|
||||
* 0x8 for interrupt trigger when FIFO level is 9,
|
||||
* 0x9 for interrupt trigger when FIFO level is 10,
|
||||
* 0xa for interrupt trigger when FIFO level is 11,
|
||||
* 0xb for interrupt trigger when FIFO level is 12,
|
||||
* 0xc for interrupt trigger when FIFO level is 13,
|
||||
* 0xd for interrupt trigger when FIFO level is 14,
|
||||
* 0xe for interrupt trigger when FIFO level is 15,
|
||||
* 0xf for interrupt trigger when FIFO level is 16
|
||||
*/
|
||||
uint32_t rxchdt : 4;
|
||||
/* Bits [31:4] is reserved */
|
||||
uint32_t rsvd_rfcrx : 28;
|
||||
} __attribute__((packed, aligned(4))) i2s_rfcr_t;
|
||||
|
||||
typedef union _rfcr_u
|
||||
{
|
||||
i2s_rfcr_t rfcr;
|
||||
uint32_t reg_data;
|
||||
} rfcr_t;
|
||||
|
||||
typedef struct _i2s_tfcr
|
||||
{
|
||||
/* Bits [3:0] is used program the trigger level in the TX FIFO at
|
||||
* which the receiver data available interrupt generate,
|
||||
* 0x0 for interrupt trigger when FIFO level is 1,
|
||||
* 0x2 for interrupt trigger when FIFO level is 2,
|
||||
* 0x3 for interrupt trigger when FIFO level is 4,
|
||||
* 0x4 for interrupt trigger when FIFO level is 5,
|
||||
* 0x5 for interrupt trigger when FIFO level is 6,
|
||||
* 0x6 for interrupt trigger when FIFO level is 7,
|
||||
* 0x7 for interrupt trigger when FIFO level is 8,
|
||||
* 0x8 for interrupt trigger when FIFO level is 9,
|
||||
* 0x9 for interrupt trigger when FIFO level is 10,
|
||||
* 0xa for interrupt trigger when FIFO level is 11,
|
||||
* 0xb for interrupt trigger when FIFO level is 12,
|
||||
* 0xc for interrupt trigger when FIFO level is 13,
|
||||
* 0xd for interrupt trigger when FIFO level is 14,
|
||||
* 0xe for interrupt trigger when FIFO level is 15,
|
||||
* 0xf for interrupt trigger when FIFO level is 16
|
||||
*/
|
||||
uint32_t txchet : 4;
|
||||
/* Bits [31:4] is reserved */
|
||||
uint32_t rsvd_tfcrx : 28;
|
||||
} __attribute__((packed, aligned(4))) i2s_tfcr_t;
|
||||
|
||||
typedef union _tfcr_u
|
||||
{
|
||||
i2s_tfcr_t tfcr;
|
||||
uint32_t reg_data;
|
||||
} tfcr_t;
|
||||
|
||||
typedef struct _i2s_rff
|
||||
{
|
||||
/* Bit 0 is receiver channel FIFO reset,
|
||||
* 0x0 for does not flush an individual RX FIFO,
|
||||
* 0x1 for flush an indiviadual RX FIFO
|
||||
*/
|
||||
uint32_t rxchfr : 1;
|
||||
/*< Bits [31:1] is reserved ,write only */
|
||||
uint32_t rsvd_rffx : 31;
|
||||
} __attribute__((packed, aligned(4))) i2s_rff_t;
|
||||
|
||||
typedef union _rff_u
|
||||
{
|
||||
i2s_rff_t rff;
|
||||
uint32_t reg_data;
|
||||
} rff_t;
|
||||
|
||||
typedef struct _i2s_tff
|
||||
{
|
||||
/* Bit 0 is transmit channel FIFO reset,
|
||||
* 0x0 for does not flush an individual TX FIFO,
|
||||
* 0x1 for flush an indiviadual TX FIFO
|
||||
*/
|
||||
uint32_t rtxchfr : 1;
|
||||
/*< Bits [31:1] is reserved ,write only */
|
||||
uint32_t rsvd_rffx : 31;
|
||||
} __attribute__((packed, aligned(4))) i2s_tff_t;
|
||||
|
||||
typedef union tff_u
|
||||
{
|
||||
i2s_tff_t tff;
|
||||
uint32_t reg_data;
|
||||
} tff_t;
|
||||
|
||||
typedef struct _i2s_channel
|
||||
{
|
||||
/* Left Receive or Left Transmit Register (0x20) */
|
||||
volatile uint32_t left_rxtx;
|
||||
/* Right Receive or Right Transmit Register (0x24) */
|
||||
volatile uint32_t right_rxtx;
|
||||
/* Receive Enable Register (0x28) */
|
||||
volatile uint32_t rer;
|
||||
/* Transmit Enable Register (0x2c) */
|
||||
volatile uint32_t ter;
|
||||
/* Receive Configuration Register (0x30) */
|
||||
volatile uint32_t rcr;
|
||||
/* Transmit Configuration Register (0x34) */
|
||||
volatile uint32_t tcr;
|
||||
/* Interrupt Status Register (0x38) */
|
||||
volatile uint32_t isr;
|
||||
/* Interrupt Mask Register (0x3c) */
|
||||
volatile uint32_t imr;
|
||||
/* Receive Overrun Register (0x40) */
|
||||
volatile uint32_t ror;
|
||||
/* Transmit Overrun Register (0x44) */
|
||||
volatile uint32_t tor;
|
||||
/* Receive FIFO Configuration Register (0x48) */
|
||||
volatile uint32_t rfcr;
|
||||
/* Transmit FIFO Configuration Register (0x4c) */
|
||||
volatile uint32_t tfcr;
|
||||
/* Receive FIFO Flush Register (0x50) */
|
||||
volatile uint32_t rff;
|
||||
/* Transmit FIFO Flush Register (0x54) */
|
||||
volatile uint32_t tff;
|
||||
/* reserved (0x58-0x5c) */
|
||||
volatile uint32_t reserved1[2];
|
||||
} __attribute__((packed, aligned(4))) i2s_channel_t;
|
||||
|
||||
/****is* i2s.api/dw_i2s_portmap
|
||||
* NAME
|
||||
* i2s_t
|
||||
* DESCRIPTION
|
||||
* This is the structure used for accessing the i2s register
|
||||
* portmap.
|
||||
* EXAMPLE
|
||||
* struct i2s_t *portmap;
|
||||
* portmap = (struct dw_i2s_portmap *) DW_APB_I2S_BASE;
|
||||
* SOURCE
|
||||
*/
|
||||
typedef struct _i2s
|
||||
{
|
||||
/* I2S Enable Register (0x00) */
|
||||
volatile uint32_t ier;
|
||||
/* I2S Receiver Block Enable Register (0x04) */
|
||||
volatile uint32_t irer;
|
||||
/* I2S Transmitter Block Enable Register (0x08) */
|
||||
volatile uint32_t iter;
|
||||
/* Clock Enable Register (0x0c) */
|
||||
volatile uint32_t cer;
|
||||
/* Clock Configuration Register (0x10) */
|
||||
volatile uint32_t ccr;
|
||||
/* Receiver Block FIFO Reset Register (0x04) */
|
||||
volatile uint32_t rxffr;
|
||||
/* Transmitter Block FIFO Reset Register (0x18) */
|
||||
volatile uint32_t txffr;
|
||||
/* reserved (0x1c) */
|
||||
volatile uint32_t reserved1;
|
||||
volatile i2s_channel_t channel[4];
|
||||
/* reserved (0x118-0x1bc) */
|
||||
volatile uint32_t reserved2[40];
|
||||
/* Receiver Block DMA Register (0x1c0) */
|
||||
volatile uint32_t rxdma;
|
||||
/* Reset Receiver Block DMA Register (0x1c4) */
|
||||
volatile uint32_t rrxdma;
|
||||
/* Transmitter Block DMA Register (0x1c8) */
|
||||
volatile uint32_t txdma;
|
||||
/* Reset Transmitter Block DMA Register (0x1cc) */
|
||||
volatile uint32_t rtxdma;
|
||||
/* reserved (0x1d0-0x1ec) */
|
||||
volatile uint32_t reserved3[8];
|
||||
/* Component Parameter Register 2 (0x1f0) */
|
||||
volatile uint32_t i2s_comp_param_2;
|
||||
/* Component Parameter Register 1 (0x1f4) */
|
||||
volatile uint32_t i2s_comp_param_1;
|
||||
/* I2S Component Version Register (0x1f8) */
|
||||
volatile uint32_t i2s_comp_version_1;
|
||||
/* I2S Component Type Register (0x1fc) */
|
||||
volatile uint32_t i2s_comp_type;
|
||||
} __attribute__((packed, aligned(4))) i2s_t;
|
||||
|
||||
typedef enum _i2s_transfer_mode
|
||||
{
|
||||
I2S_SEND,
|
||||
I2S_RECEIVE,
|
||||
} i2s_transfer_mode_t;
|
||||
|
||||
typedef struct _i2s_data_t
|
||||
{
|
||||
dmac_channel_number_t tx_channel;
|
||||
dmac_channel_number_t rx_channel;
|
||||
uint32_t *tx_buf;
|
||||
size_t tx_len;
|
||||
uint32_t *rx_buf;
|
||||
size_t rx_len;
|
||||
i2s_transfer_mode_t transfer_mode;
|
||||
bool nowait_dma_idle;
|
||||
bool wait_dma_done;
|
||||
} i2s_data_t;
|
||||
|
||||
/**
|
||||
* @brief I2S object instance
|
||||
*/
|
||||
extern volatile i2s_t *const i2s[3];
|
||||
|
||||
/**
|
||||
* @brief I2s init
|
||||
*
|
||||
* @param[in] device_num The device number
|
||||
* @param[in] rxtx_mode I2s work mode
|
||||
* @param[in] channel_mask Channel mask to which channel work
|
||||
*
|
||||
*/
|
||||
void i2s_init(i2s_device_number_t device_num, i2s_transmit_t rxtx_mode, uint32_t channel_mask);
|
||||
|
||||
/**
|
||||
* @brief Read pcm data from dma
|
||||
*
|
||||
* @param[in] device_num which of device
|
||||
* @param[in] buf save read data
|
||||
* @param[in] buf_len the length to read form i2s
|
||||
* @param[in] channel_num The dma channel number
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void i2s_receive_data_dma(i2s_device_number_t device_num, uint32_t *buf, size_t buf_len,
|
||||
dmac_channel_number_t channel_num);
|
||||
|
||||
/**
|
||||
* @brief Write pcm data to channel_num channel by dma, first wait dmac done
|
||||
*
|
||||
* @param[in] device_num which of device
|
||||
* @param[in] pcm Send data
|
||||
* @param[in] buf_len Send data length
|
||||
* @param[in] channel_num dmac channel
|
||||
*
|
||||
*/
|
||||
void i2s_send_data_dma(i2s_device_number_t device_num, const void *buf, size_t buf_len, dmac_channel_number_t channel_num);
|
||||
|
||||
/**
|
||||
* @brief I2S receive channel configure
|
||||
*
|
||||
* @param[in] device_num The device number
|
||||
* @param[in] channel_num The channel number
|
||||
* @param[in] word_length The word length
|
||||
* @param[in] word_select_size The word select size
|
||||
* @param[in] trigger_level The trigger level
|
||||
*/
|
||||
void i2s_rx_channel_config(i2s_device_number_t device_num,
|
||||
i2s_channel_num_t channel_num,
|
||||
i2s_word_length_t word_length,
|
||||
i2s_word_select_cycles_t word_select_size,
|
||||
i2s_fifo_threshold_t trigger_level,
|
||||
i2s_work_mode_t word_mode);
|
||||
|
||||
/**
|
||||
* @brief I2S transmit channel enable
|
||||
*
|
||||
* @param[in] device_num The device number
|
||||
* @param[in] channel_num The channel number
|
||||
* @param[in] word_length The word length
|
||||
* @param[in] word_select_size The word select size
|
||||
* @param[in] trigger_level The trigger level
|
||||
*/
|
||||
void i2s_tx_channel_config(i2s_device_number_t device_num,
|
||||
i2s_channel_num_t channel_num,
|
||||
i2s_word_length_t word_length,
|
||||
i2s_word_select_cycles_t word_select_size,
|
||||
i2s_fifo_threshold_t trigger_level,
|
||||
i2s_work_mode_t word_mode);
|
||||
|
||||
/**
|
||||
* @brief Play PCM format audio
|
||||
*
|
||||
* @param[in] device_num The device number
|
||||
* @param[in] channel_num The channel number
|
||||
* @param[in] buf PCM data
|
||||
* @param[in] buf_len PCM data length
|
||||
* @param[in] frame Transmit amount once
|
||||
* @param[in] bits_per_sample Sample bit length
|
||||
* @param[in] track_num Track amount
|
||||
*/
|
||||
void i2s_play(i2s_device_number_t device_num, dmac_channel_number_t channel_num,
|
||||
const uint8_t *buf, size_t buf_len, size_t frame, size_t bits_per_sample, uint8_t track_num);
|
||||
|
||||
/**
|
||||
* @brief Play PCM format audio
|
||||
*
|
||||
* @param[in] device_num The device number
|
||||
* @param[in] sample_rate The Sample rate
|
||||
*
|
||||
*
|
||||
* @return The real sample rate
|
||||
*/
|
||||
uint32_t i2s_set_sample_rate(i2s_device_number_t device_num, uint32_t sample_rate);
|
||||
|
||||
/**
|
||||
* @brief Set dma_divide_16 split 32bit data to two 16 bit data and filled in left
|
||||
* and right channel. Used with dma_tx_en or dma_rx_en
|
||||
*
|
||||
* @param[in] device_num The device number
|
||||
* @param[in] enable The value of dma_divide_16 0:disable 1:enable
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int i2s_set_dma_divide_16(i2s_device_number_t device_num, uint32_t enable);
|
||||
|
||||
/**
|
||||
* @brief Get dma_divide_16.
|
||||
*
|
||||
* @param[in] device_num The device number
|
||||
*
|
||||
* @return result
|
||||
* - <0 Fail
|
||||
* - other value of dma_divide_16
|
||||
*/
|
||||
int i2s_get_dma_divide_16(i2s_device_number_t device_num);
|
||||
|
||||
/**
|
||||
* @brief I2s handle transfer data operations
|
||||
*
|
||||
* @param[in] device_num I2s device number
|
||||
* @param[in] data I2s data information
|
||||
* @param[in] cb I2s dma callback
|
||||
*
|
||||
*/
|
||||
void i2s_handle_data_dma(i2s_device_number_t device_num, i2s_data_t data, plic_interrupt_t *cb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,74 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/* Enable kernel-mode log API */
|
||||
|
||||
/**
|
||||
* @file interrupt.c
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "interrupt.h"
|
||||
#include "encoding.h"
|
||||
#include "syscalls.h"
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_irq_dummy(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
//dump_core("unhandled interrupt", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak, alias("handle_irq_dummy")))
|
||||
handle_irq_m_soft(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32]);
|
||||
|
||||
uintptr_t __attribute__((weak, alias("handle_irq_dummy")))
|
||||
handle_irq_m_timer(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32]);
|
||||
|
||||
extern uintptr_t
|
||||
handle_irq_m_ext(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32]);
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_irq(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Woverride-init"
|
||||
#endif
|
||||
/* clang-format off */
|
||||
static uintptr_t (* const irq_table[])(
|
||||
uintptr_t cause,
|
||||
uintptr_t epc,
|
||||
uintptr_t regs[32],
|
||||
uintptr_t fregs[32]) =
|
||||
{
|
||||
[0 ... 14] = handle_irq_dummy,
|
||||
[IRQ_M_SOFT] = handle_irq_m_soft,
|
||||
[IRQ_M_TIMER] = handle_irq_m_timer,
|
||||
[IRQ_M_EXT] = handle_irq_m_ext,
|
||||
};
|
||||
/* clang-format on */
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic warning "-Woverride-init"
|
||||
#endif
|
||||
return irq_table[cause & CAUSE_MACHINE_IRQ_REASON_MASK](cause, epc, regs, fregs);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file interrupt.h
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#ifndef _BSP_INTERRUPT_H
|
||||
#define _BSP_INTERRUPT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* clang-format off */
|
||||
/* Machine interrupt mask for 64 bit system, 0x8000 0000 0000 0000 */
|
||||
#define CAUSE_MACHINE_IRQ_MASK (0x1ULL << 63)
|
||||
|
||||
/* Machine interrupt reason mask for 64 bit system, 0x7FFF FFFF FFFF FFFF */
|
||||
#define CAUSE_MACHINE_IRQ_REASON_MASK (CAUSE_MACHINE_IRQ_MASK - 1)
|
||||
|
||||
/* Hypervisor interrupt mask for 64 bit system, 0x8000 0000 0000 0000 */
|
||||
#define CAUSE_HYPERVISOR_IRQ_MASK (0x1ULL << 63)
|
||||
|
||||
/* Hypervisor interrupt reason mask for 64 bit system, 0x7FFF FFFF FFFF FFFF */
|
||||
#define CAUSE_HYPERVISOR_IRQ_REASON_MASK (CAUSE_HYPERVISOR_IRQ_MASK - 1)
|
||||
|
||||
/* Supervisor interrupt mask for 64 bit system, 0x8000 0000 0000 0000 */
|
||||
#define CAUSE_SUPERVISOR_IRQ_MASK (0x1ULL << 63)
|
||||
|
||||
/* Supervisor interrupt reason mask for 64 bit system, 0x7FFF FFFF FFFF FFFF */
|
||||
#define CAUSE_SUPERVISOR_IRQ_REASON_MASK (CAUSE_SUPERVISOR_IRQ_MASK - 1)
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BSP_INTERRUPT_H */
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file io.h
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#ifndef _DRIVER_IO_H
|
||||
#define _DRIVER_IO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define readb(addr) (*(volatile uint8_t *)(addr))
|
||||
#define readw(addr) (*(volatile uint16_t *)(addr))
|
||||
#define readl(addr) (*(volatile uint32_t *)(addr))
|
||||
#define readq(addr) (*(volatile uint64_t *)(addr))
|
||||
|
||||
#define writeb(v, addr) \
|
||||
{ \
|
||||
(*(volatile uint8_t *)(addr)) = (v); \
|
||||
}
|
||||
#define writew(v, addr) \
|
||||
{ \
|
||||
(*(volatile uint16_t *)(addr)) = (v); \
|
||||
}
|
||||
#define writel(v, addr) \
|
||||
{ \
|
||||
(*(volatile uint32_t *)(addr)) = (v); \
|
||||
}
|
||||
#define writeq(v, addr) \
|
||||
{ \
|
||||
(*(volatile uint64_t *)(addr)) = (v); \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_IO_H */
|
||||
@@ -0,0 +1,51 @@
|
||||
/************************************************************************************
|
||||
* arch/risc-v/src/nr5m100/nr5_arch.c
|
||||
*
|
||||
* Copyright (C) 2016 Ken Pettit. All rights reserved.
|
||||
* Author: Ken Pettit <pettitkd@gmail.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file k210_arch.c
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include "k210.h"
|
||||
#include "uarths.h"
|
||||
|
||||
void up_puts(const char *p)
|
||||
{
|
||||
uarths_puts(p);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
/****************************************************************************
|
||||
* arch/risc-v/src/k210/k210_head.S
|
||||
*
|
||||
* 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 <nuttx/config.h>
|
||||
#include <arch/csr.h>
|
||||
#include <arch/rv64gc/irq.h>
|
||||
|
||||
#include "chip.h"
|
||||
#include "k210_memorymap.h"
|
||||
#include "riscv_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Symbols
|
||||
****************************************************************************/
|
||||
|
||||
.global exception_common
|
||||
|
||||
/* Imported symbols */
|
||||
|
||||
.extern __trap_vec
|
||||
|
||||
.section .text
|
||||
.global __start
|
||||
|
||||
__start:
|
||||
|
||||
#if defined(__riscv_flen) && __riscv_flen > 0
|
||||
/* Enable FPU */
|
||||
li a0, MSTATUS_FS
|
||||
csrs mstatus, a0
|
||||
csrw fcsr, x0
|
||||
#endif
|
||||
|
||||
/* Load mhartid (cpuid) */
|
||||
|
||||
csrr a0, mhartid
|
||||
|
||||
/* Set stack pointer to the idle thread stack */
|
||||
|
||||
bnez a0, 1f
|
||||
la sp, K210_IDLESTACK0_TOP
|
||||
j 2f
|
||||
1:
|
||||
la sp, K210_IDLESTACK1_TOP
|
||||
|
||||
/* In case of single CPU config, stop here */
|
||||
|
||||
#if !(defined CONFIG_SMP) || (CONFIG_SMP_NCPUS == 1)
|
||||
wfi
|
||||
#endif
|
||||
2:
|
||||
|
||||
/* Disable all interrupts (i.e. timer, external) in mie */
|
||||
|
||||
csrw mie, zero
|
||||
|
||||
/* Initialize the Machine Trap Vector */
|
||||
|
||||
la t0, __trap_vec
|
||||
csrw mtvec, t0
|
||||
|
||||
/* Jump to __k210_start with mhartid */
|
||||
|
||||
j __k210_start
|
||||
|
||||
/* We shouldn't return from __k210_start */
|
||||
|
||||
.global _init
|
||||
.global _fini
|
||||
|
||||
_init:
|
||||
_fini:
|
||||
|
||||
/* These don't have to do anything since we use init_array/fini_array. */
|
||||
|
||||
ret
|
||||
|
||||
/****************************************************************************
|
||||
* Name: exception_common
|
||||
****************************************************************************/
|
||||
|
||||
exception_common:
|
||||
|
||||
#if 0
|
||||
csrr gp, mcause /* exception cause */
|
||||
addi tp, zero, 10 /* 10 = machine ecall */
|
||||
bgtu gp, tp, normal_irq
|
||||
ld sp, g_fstack_top /* Set sp to fault stack */
|
||||
|
||||
normal_irq:
|
||||
addi gp, zero, 0 /* clear */
|
||||
#endif
|
||||
|
||||
addi sp, sp, -XCPTCONTEXT_SIZE
|
||||
|
||||
sd x1, 1*8(sp) /* ra */
|
||||
sd x3, 3*8(sp) /* gp */
|
||||
sd x4, 4*8(sp) /* tp */
|
||||
sd x5, 5*8(sp) /* t0 */
|
||||
sd x6, 6*8(sp) /* t1 */
|
||||
sd x7, 7*8(sp) /* t2 */
|
||||
sd x8, 8*8(sp) /* s0 */
|
||||
sd x9, 9*8(sp) /* s1 */
|
||||
sd x10, 10*8(sp) /* a0 */
|
||||
sd x11, 11*8(sp) /* a1 */
|
||||
sd x12, 12*8(sp) /* a2 */
|
||||
sd x13, 13*8(sp) /* a3 */
|
||||
sd x14, 14*8(sp) /* a4 */
|
||||
sd x15, 15*8(sp) /* a5 */
|
||||
sd x16, 16*8(sp) /* a6 */
|
||||
sd x17, 17*8(sp) /* a7 */
|
||||
sd x18, 18*8(sp) /* s2 */
|
||||
sd x19, 19*8(sp) /* s3 */
|
||||
sd x20, 20*8(sp) /* s4 */
|
||||
sd x21, 21*8(sp) /* s5 */
|
||||
sd x22, 22*8(sp) /* s6 */
|
||||
sd x23, 23*8(sp) /* s7 */
|
||||
sd x24, 24*8(sp) /* s8 */
|
||||
sd x25, 25*8(sp) /* s9 */
|
||||
sd x26, 26*8(sp) /* s10 */
|
||||
sd x27, 27*8(sp) /* s11 */
|
||||
sd x28, 28*8(sp) /* t3 */
|
||||
sd x29, 29*8(sp) /* t4 */
|
||||
sd x30, 30*8(sp) /* t5 */
|
||||
sd x31, 31*8(sp) /* t6 */
|
||||
|
||||
csrr s0, mstatus
|
||||
sd s0, 32*8(sp) /* mstatus */
|
||||
|
||||
addi s0, sp, XCPTCONTEXT_SIZE
|
||||
sd s0, 2*8(sp) /* original SP */
|
||||
|
||||
/* Setup arg0(exception cause), arg1(context) */
|
||||
|
||||
csrr a0, mcause /* exception cause */
|
||||
csrr s0, mepc
|
||||
sd s0, 0(sp) /* exception PC */
|
||||
|
||||
mv a1, sp /* context = sp */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||
/* Load mhartid (cpuid) */
|
||||
|
||||
csrr s0, mhartid
|
||||
|
||||
/* Switch to interrupt stack */
|
||||
|
||||
bnez s0, 3f
|
||||
la sp, g_intstacktop
|
||||
j 4f
|
||||
3:
|
||||
la sp, g_intstacktop
|
||||
addi sp, sp, -(CONFIG_ARCH_INTERRUPTSTACK & ~15)
|
||||
4:
|
||||
|
||||
#endif
|
||||
|
||||
/* Call interrupt handler in C */
|
||||
|
||||
jal x1, k210_dispatch_irq
|
||||
|
||||
/* If context switch is needed, return a new sp */
|
||||
|
||||
mv sp, a0
|
||||
ld s0, 0(sp) /* restore mepc */
|
||||
csrw mepc, s0
|
||||
|
||||
ld s0, 32*8(sp) /* restore mstatus */
|
||||
li s1, MSTATUS_FS
|
||||
or s0, s0, s1
|
||||
csrw mstatus, s0
|
||||
|
||||
ld x3, 3*8(sp) /* gp */
|
||||
ld x4, 4*8(sp) /* tp */
|
||||
ld x5, 5*8(sp) /* t0 */
|
||||
ld x6, 6*8(sp) /* t1 */
|
||||
ld x7, 7*8(sp) /* t2 */
|
||||
ld x8, 8*8(sp) /* s0 */
|
||||
ld x9, 9*8(sp) /* s1 */
|
||||
ld x10, 10*8(sp) /* a0 */
|
||||
ld x11, 11*8(sp) /* a1 */
|
||||
ld x12, 12*8(sp) /* a2 */
|
||||
ld x13, 13*8(sp) /* a3 */
|
||||
ld x14, 14*8(sp) /* a4 */
|
||||
ld x15, 15*8(sp) /* a5 */
|
||||
ld x16, 16*8(sp) /* a6 */
|
||||
ld x17, 17*8(sp) /* a7 */
|
||||
ld x18, 18*8(sp) /* s2 */
|
||||
ld x19, 19*8(sp) /* s3 */
|
||||
ld x20, 20*8(sp) /* s4 */
|
||||
ld x21, 21*8(sp) /* s5 */
|
||||
ld x22, 22*8(sp) /* s6 */
|
||||
ld x23, 23*8(sp) /* s7 */
|
||||
ld x24, 24*8(sp) /* s8 */
|
||||
ld x25, 25*8(sp) /* s9 */
|
||||
ld x26, 26*8(sp) /* s10 */
|
||||
ld x27, 27*8(sp) /* s11 */
|
||||
ld x28, 28*8(sp) /* t3 */
|
||||
ld x29, 29*8(sp) /* t4 */
|
||||
ld x30, 30*8(sp) /* t5 */
|
||||
ld x31, 31*8(sp) /* t6 */
|
||||
|
||||
ld x1, 1*8(sp) /* ra */
|
||||
|
||||
ld sp, 2*8(sp) /* restore original sp */
|
||||
|
||||
/* Return from Machine Interrupt */
|
||||
|
||||
mret
|
||||
|
||||
/************************************************************************************
|
||||
* Name: g_intstackalloc and g_intstacktop
|
||||
************************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||
.bss
|
||||
.balign 16
|
||||
.global g_intstackalloc
|
||||
.global g_intstacktop
|
||||
.type g_intstackalloc, object
|
||||
.type g_intstacktop, object
|
||||
g_intstackalloc:
|
||||
#ifndef CONFIG_SMP
|
||||
.skip ((CONFIG_ARCH_INTERRUPTSTACK + 8) & ~15)
|
||||
#else
|
||||
.skip (((CONFIG_ARCH_INTERRUPTSTACK * CONFIG_SMP_NCPUS) + 8) & ~15)
|
||||
#endif
|
||||
g_intstacktop:
|
||||
.size g_intstacktop, 0
|
||||
#ifndef CONFIG_SMP
|
||||
.size g_intstackalloc, (CONFIG_ARCH_INTERRUPTSTACK & ~15)
|
||||
#else
|
||||
.size g_intstackalloc, ((CONFIG_ARCH_INTERRUPTSTACK * CONFIG_SMP_NCPUS) & ~15)
|
||||
#endif
|
||||
#endif
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
/****************************************************************************
|
||||
* arch/risc-v/src/k210/k210_start.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
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file k210_start.c
|
||||
* @brief nuttx source code
|
||||
* https://github.com/apache/incubator-nuttx.git
|
||||
* @version 10.2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <nuttx/init.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <arch/board/board.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "riscv_arch.h"
|
||||
#include "k210_clockconfig.h"
|
||||
#include "k210_userspace.h"
|
||||
#include "k210.h"
|
||||
#include "chip.h"
|
||||
#include "plic.h"
|
||||
#include "uarths.h"
|
||||
#include "fpioa.h"
|
||||
#include "dmac.h"
|
||||
#include "fft.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
# define showprogress(c) riscv_lowputc(c)
|
||||
#else
|
||||
# define showprogress(c)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/* NOTE: g_idle_topstack needs to point the top of the idle stack
|
||||
* for CPU0 and this value is used in up_initial_state()
|
||||
*/
|
||||
|
||||
uintptr_t g_idle_topstack = K210_IDLESTACK0_TOP;
|
||||
volatile bool g_serial_ok = false;
|
||||
|
||||
extern void k210_cpu_boot(uint32_t);
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: k210_start
|
||||
****************************************************************************/
|
||||
|
||||
void __k210_start(uint32_t mhartid)
|
||||
{
|
||||
const uint32_t *src;
|
||||
uint32_t *dest;
|
||||
|
||||
if (0 < mhartid)
|
||||
{
|
||||
goto cpu1;
|
||||
}
|
||||
|
||||
/* Clear .bss. We'll do this inline (vs. calling memset) just to be
|
||||
* certain that there are no issues with the state of global variables.
|
||||
*/
|
||||
|
||||
for (dest = &_sbss; dest < &_ebss; )
|
||||
{
|
||||
*dest++ = 0;
|
||||
}
|
||||
|
||||
/* Move the initialized data section from his temporary holding spot in
|
||||
* FLASH into the correct place in SRAM. The correct place in SRAM is
|
||||
* give by _sdata and _edata. The temporary location is in FLASH at the
|
||||
* end of all of the other read-only data (.text, .rodata) at _eronly.
|
||||
*/
|
||||
|
||||
for (src = &_eronly, dest = &_sdata; dest < &_edata; )
|
||||
{
|
||||
*dest++ = *src++;
|
||||
}
|
||||
|
||||
/* Setup PLL */
|
||||
|
||||
k210_clockconfig();
|
||||
|
||||
/* Init PLIC */
|
||||
plic_init();
|
||||
/* Init UART */
|
||||
uarths_init();
|
||||
/* Init FPIOA */
|
||||
fpioa_init();
|
||||
/* Init DMA */
|
||||
dmac_init();
|
||||
|
||||
k210_lowsetup();
|
||||
|
||||
showprogress('A');
|
||||
|
||||
#ifdef USE_EARLYSERIALINIT
|
||||
riscv_earlyserialinit();
|
||||
#endif
|
||||
|
||||
showprogress('B');
|
||||
|
||||
g_serial_ok = true;
|
||||
|
||||
/* Do board initialization */
|
||||
|
||||
k210_boardinitialize();
|
||||
|
||||
showprogress('C');
|
||||
|
||||
/* For the case of the separate user-/kernel-space build, perform whatever
|
||||
* platform specific initialization of the user memory is required.
|
||||
* Normally this just means initializing the user space .data and .bss
|
||||
* segments.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
k210_userspace();
|
||||
showprogress('D');
|
||||
#endif
|
||||
|
||||
/* Call nx_start() */
|
||||
|
||||
nx_start();
|
||||
|
||||
cpu1:
|
||||
|
||||
showprogress('a');
|
||||
|
||||
#if defined(CONFIG_SMP) && (CONFIG_SMP_NCPUS == 2)
|
||||
k210_cpu_boot(mhartid);
|
||||
#endif
|
||||
|
||||
while (true)
|
||||
{
|
||||
asm("WFI");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file platform.h
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#ifndef _BSP_PLATFORM_H
|
||||
#define _BSP_PLATFORM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
/* Register base address */
|
||||
|
||||
/* Under Coreplex */
|
||||
#define CLINT_BASE_ADDR (0x02000000U)
|
||||
#define PLIC_BASE_ADDR (0x0C000000U)
|
||||
|
||||
/* Under TileLink */
|
||||
#define UARTHS_BASE_ADDR (0x38000000U)
|
||||
#define GPIOHS_BASE_ADDR (0x38001000U)
|
||||
|
||||
/* Under AXI 64 bit */
|
||||
#define RAM_BASE_ADDR (0x80000000U)
|
||||
//#define RAM_SIZE (6 * 1024 * 1024U)
|
||||
|
||||
#define IO_BASE_ADDR (0x40000000U)
|
||||
#define IO_SIZE (6 * 1024 * 1024U)
|
||||
|
||||
#define AI_RAM_BASE_ADDR (0x80600000U)
|
||||
#define AI_RAM_SIZE (2 * 1024 * 1024U)
|
||||
|
||||
#define AI_IO_BASE_ADDR (0x40600000U)
|
||||
#define AI_IO_SIZE (2 * 1024 * 1024U)
|
||||
|
||||
#define AI_BASE_ADDR (0x40800000U)
|
||||
#define AI_SIZE (12 * 1024 * 1024U)
|
||||
|
||||
#define FFT_BASE_ADDR (0x42000000U)
|
||||
#define FFT_SIZE (4 * 1024 * 1024U)
|
||||
|
||||
#define ROM_BASE_ADDR (0x88000000U)
|
||||
#define ROM_SIZE (128 * 1024U)
|
||||
|
||||
/* Under AHB 32 bit */
|
||||
#define DMAC_BASE_ADDR (0x50000000U)
|
||||
|
||||
/* Under APB1 32 bit */
|
||||
#define GPIO_BASE_ADDR (0x50200000U)
|
||||
#define UART1_BASE_ADDR (0x50210000U)
|
||||
#define UART2_BASE_ADDR (0x50220000U)
|
||||
#define UART3_BASE_ADDR (0x50230000U)
|
||||
#define SPI_SLAVE_BASE_ADDR (0x50240000U)
|
||||
#define I2S0_BASE_ADDR (0x50250000U)
|
||||
#define I2S1_BASE_ADDR (0x50260000U)
|
||||
#define I2S2_BASE_ADDR (0x50270000U)
|
||||
#define I2C0_BASE_ADDR (0x50280000U)
|
||||
#define I2C1_BASE_ADDR (0x50290000U)
|
||||
#define I2C2_BASE_ADDR (0x502A0000U)
|
||||
#define FPIOA_BASE_ADDR (0x502B0000U)
|
||||
#define SHA256_BASE_ADDR (0x502C0000U)
|
||||
#define TIMER0_BASE_ADDR (0x502D0000U)
|
||||
#define TIMER1_BASE_ADDR (0x502E0000U)
|
||||
#define TIMER2_BASE_ADDR (0x502F0000U)
|
||||
|
||||
/* Under APB2 32 bit */
|
||||
#define WDT0_BASE_ADDR (0x50400000U)
|
||||
#define WDT1_BASE_ADDR (0x50410000U)
|
||||
#define OTP_BASE_ADDR (0x50420000U)
|
||||
#define DVP_BASE_ADDR (0x50430000U)
|
||||
#define SYSCTL_BASE_ADDR (0x50440000U)
|
||||
#define AES_BASE_ADDR (0x50450000U)
|
||||
#define RTC_BASE_ADDR (0x50460000U)
|
||||
|
||||
|
||||
/* Under APB3 32 bit */
|
||||
#define SPI0_BASE_ADDR (0x52000000U)
|
||||
#define SPI1_BASE_ADDR (0x53000000U)
|
||||
#define SPI3_BASE_ADDR (0x54000000U)
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BSP_PLATFORM_H */
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file plic.c
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "encoding.h"
|
||||
#include "plic.h"
|
||||
#include "syscalls.h"
|
||||
#include "syslog.h"
|
||||
|
||||
volatile plic_t* const plic = (volatile plic_t*)PLIC_BASE_ADDR;
|
||||
|
||||
static plic_instance_t plic_instance[PLIC_NUM_CORES][IRQN_MAX];
|
||||
|
||||
void plic_init(void)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
/* Get current core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
|
||||
/* Disable all interrupts for the current core. */
|
||||
for (i = 0; i < ((PLIC_NUM_SOURCES + 32u) / 32u); i++)
|
||||
plic->target_enables.target[core_id].enable[i] = 0;
|
||||
|
||||
static uint8_t s_plic_priorities_init_flag = 0;
|
||||
/* Set priorities to zero. */
|
||||
if(s_plic_priorities_init_flag == 0)
|
||||
{
|
||||
for (i = 0; i < PLIC_NUM_SOURCES; i++)
|
||||
plic->source_priorities.priority[i] = 0;
|
||||
s_plic_priorities_init_flag = 1;
|
||||
}
|
||||
|
||||
/* Set the threshold to zero. */
|
||||
plic->targets.target[core_id].priority_threshold = 0;
|
||||
|
||||
/* Clear PLIC instance for every cores */
|
||||
for (i = 0; i < IRQN_MAX; i++)
|
||||
{
|
||||
/* clang-format off */
|
||||
plic_instance[core_id][i] = (const plic_instance_t){
|
||||
.callback = NULL,
|
||||
.ctx = NULL,
|
||||
};
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
/*
|
||||
* A successful claim will also atomically clear the corresponding
|
||||
* pending bit on the interrupt source. A target can perform a claim
|
||||
* at any time, even if the EIP is not set.
|
||||
*/
|
||||
i = 0;
|
||||
while (plic->targets.target[core_id].claim_complete > 0 && i < 100)
|
||||
{
|
||||
/* This loop will clear pending bit on the interrupt source */
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Enable machine external interrupts. */
|
||||
set_csr(mie, MIP_MEIP);
|
||||
}
|
||||
|
||||
int plic_irq_enable(plic_irq_t irq_number)
|
||||
{
|
||||
/* Check parameters */
|
||||
if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
|
||||
return -1;
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Get current enable bit array by IRQ number */
|
||||
uint32_t current = plic->target_enables.target[core_id].enable[irq_number / 32];
|
||||
/* Set enable bit in enable bit array */
|
||||
current |= (uint32_t)1 << (irq_number % 32);
|
||||
/* Write back the enable bit array */
|
||||
plic->target_enables.target[core_id].enable[irq_number / 32] = current;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plic_irq_disable(plic_irq_t irq_number)
|
||||
{
|
||||
/* Check parameters */
|
||||
if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
|
||||
return -1;
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Get current enable bit array by IRQ number */
|
||||
uint32_t current = plic->target_enables.target[core_id].enable[irq_number / 32];
|
||||
/* Clear enable bit in enable bit array */
|
||||
current &= ~((uint32_t)1 << (irq_number % 32));
|
||||
/* Write back the enable bit array */
|
||||
plic->target_enables.target[core_id].enable[irq_number / 32] = current;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plic_set_priority(plic_irq_t irq_number, uint32_t priority)
|
||||
{
|
||||
/* Check parameters */
|
||||
if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
|
||||
return -1;
|
||||
/* Set interrupt priority by IRQ number */
|
||||
plic->source_priorities.priority[irq_number] = priority;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t plic_get_priority(plic_irq_t irq_number)
|
||||
{
|
||||
/* Check parameters */
|
||||
if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
|
||||
return 0;
|
||||
/* Get interrupt priority by IRQ number */
|
||||
return plic->source_priorities.priority[irq_number];
|
||||
}
|
||||
|
||||
uint32_t plic_irq_claim(void)
|
||||
{
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Perform IRQ claim */
|
||||
return plic->targets.target[core_id].claim_complete;
|
||||
}
|
||||
|
||||
int plic_irq_complete(uint32_t source)
|
||||
{
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Perform IRQ complete */
|
||||
plic->targets.target[core_id].claim_complete = source;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void plic_irq_register(plic_irq_t irq, plic_irq_callback_t callback, void *ctx)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Set user callback function */
|
||||
plic_instance[core_id][irq].callback = callback;
|
||||
/* Assign user context */
|
||||
plic_instance[core_id][irq].ctx = ctx;
|
||||
}
|
||||
|
||||
void plic_irq_unregister(plic_irq_t irq)
|
||||
{
|
||||
/* Just assign NULL to user callback function and context */
|
||||
plic_irq_register(irq, NULL, NULL);
|
||||
}
|
||||
|
||||
void __attribute__((weak, alias("plic_irq_unregister"))) plic_irq_deregister(plic_irq_t irq);
|
||||
|
||||
plic_instance_t (*plic_get_instance(void))[IRQN_MAX]
|
||||
{
|
||||
return plic_instance;
|
||||
}
|
||||
|
||||
/*Entry Point for PLIC Interrupt Handler*/
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_irq_m_ext(uintptr_t cause, uintptr_t epc)
|
||||
{
|
||||
/*
|
||||
* After the highest-priority pending interrupt is claimed by a target
|
||||
* and the corresponding IP bit is cleared, other lower-priority
|
||||
* pending interrupts might then become visible to the target, and so
|
||||
* the PLIC EIP bit might not be cleared after a claim. The interrupt
|
||||
* handler can check the local meip/heip/seip/ueip bits before exiting
|
||||
* the handler, to allow more efficient service of other interrupts
|
||||
* without first restoring the interrupted context and taking another
|
||||
* interrupt trap.
|
||||
*/
|
||||
if (read_csr(mip) & MIP_MEIP)
|
||||
{
|
||||
/* Get current core id */
|
||||
uint64_t core_id = current_coreid();
|
||||
/* Get primitive interrupt enable flag */
|
||||
uint64_t ie_flag = read_csr(mie);
|
||||
/* Get current IRQ num */
|
||||
uint32_t int_num = plic->targets.target[core_id].claim_complete;
|
||||
/* Get primitive IRQ threshold */
|
||||
uint32_t int_threshold = plic->targets.target[core_id].priority_threshold;
|
||||
/* Set new IRQ threshold = current IRQ threshold */
|
||||
plic->targets.target[core_id].priority_threshold = plic->source_priorities.priority[int_num];
|
||||
/* Disable software interrupt and timer interrupt */
|
||||
clear_csr(mie, MIP_MTIP | MIP_MSIP);
|
||||
/* Enable global interrupt */
|
||||
set_csr(mstatus, MSTATUS_MIE);
|
||||
if (plic_instance[core_id][int_num].callback)
|
||||
plic_instance[core_id][int_num].callback(
|
||||
plic_instance[core_id][int_num].ctx);
|
||||
/* Perform IRQ complete */
|
||||
plic->targets.target[core_id].claim_complete = int_num;
|
||||
/* Disable global interrupt */
|
||||
clear_csr(mstatus, MSTATUS_MIE);
|
||||
/* Set MPIE and MPP flag used to MRET instructions restore MIE flag */
|
||||
set_csr(mstatus, MSTATUS_MPIE | MSTATUS_MPP);
|
||||
/* Restore primitive interrupt enable flag */
|
||||
write_csr(mie, ie_flag);
|
||||
/* Restore primitive IRQ threshold */
|
||||
plic->targets.target[core_id].priority_threshold = int_threshold;
|
||||
}
|
||||
|
||||
return epc;
|
||||
}
|
||||
@@ -0,0 +1,508 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @brief The PLIC complies with the RISC-V Privileged Architecture
|
||||
* specification, and can support a maximum of 1023 external
|
||||
* interrupt sources targeting up to 15,872 core contexts.
|
||||
*
|
||||
* @note PLIC RAM Layout
|
||||
*
|
||||
* | Address | Description |
|
||||
* |-----------|---------------------------------|
|
||||
* |0x0C000000 | Reserved |
|
||||
* |0x0C000004 | source 1 priority |
|
||||
* |0x0C000008 | source 2 priority |
|
||||
* |... | ... |
|
||||
* |0x0C000FFC | source 1023 priority |
|
||||
* | | |
|
||||
* |0x0C001000 | Start of pending array |
|
||||
* |... | (read-only) |
|
||||
* |0x0C00107C | End of pending array |
|
||||
* |0x0C001080 | Reserved |
|
||||
* |... | ... |
|
||||
* |0x0C001FFF | Reserved |
|
||||
* | | |
|
||||
* |0x0C002000 | target 0 enables |
|
||||
* |0x0C002080 | target 1 enables |
|
||||
* |... | ... |
|
||||
* |0x0C1F1F80 | target 15871 enables |
|
||||
* |0x0C1F2000 | Reserved |
|
||||
* |... | ... |
|
||||
* |0x0C1FFFFC | Reserved |
|
||||
* | | |
|
||||
* |0x0C200000 | target 0 priority threshold |
|
||||
* |0x0C200004 | target 0 claim/complete |
|
||||
* |... | ... |
|
||||
* |0x0C201000 | target 1 priority threshold |
|
||||
* |0x0C201004 | target 1 claim/complete |
|
||||
* |... | ... |
|
||||
* |0x0FFFF000 | target 15871 priority threshold |
|
||||
* |0x0FFFF004 | target 15871 claim/complete |
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file plic.h
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#ifndef _DRIVER_PLIC_H
|
||||
#define _DRIVER_PLIC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "encoding.h"
|
||||
#include "platform.h"
|
||||
|
||||
/* For c++ compatibility */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
/* IRQ number settings */
|
||||
#define PLIC_NUM_SOURCES (IRQN_MAX - 1)
|
||||
#define PLIC_NUM_PRIORITIES (7)
|
||||
|
||||
/* Real number of cores */
|
||||
#define PLIC_NUM_CORES (2)
|
||||
/* clang-format on */
|
||||
|
||||
/**
|
||||
* @brief PLIC External Interrupt Numbers
|
||||
*
|
||||
* @note PLIC interrupt sources
|
||||
*
|
||||
* | Source | Name | Description |
|
||||
* |--------|--------------------------|------------------------------------|
|
||||
* | 0 | IRQN_NO_INTERRUPT | The non-existent interrupt |
|
||||
* | 1 | IRQN_SPI0_INTERRUPT | SPI0 interrupt |
|
||||
* | 2 | IRQN_SPI1_INTERRUPT | SPI1 interrupt |
|
||||
* | 3 | IRQN_SPI_SLAVE_INTERRUPT | SPI_SLAVE interrupt |
|
||||
* | 4 | IRQN_SPI3_INTERRUPT | SPI3 interrupt |
|
||||
* | 5 | IRQN_I2S0_INTERRUPT | I2S0 interrupt |
|
||||
* | 6 | IRQN_I2S1_INTERRUPT | I2S1 interrupt |
|
||||
* | 7 | IRQN_I2S2_INTERRUPT | I2S2 interrupt |
|
||||
* | 8 | IRQN_I2C0_INTERRUPT | I2C0 interrupt |
|
||||
* | 9 | IRQN_I2C1_INTERRUPT | I2C1 interrupt |
|
||||
* | 10 | IRQN_I2C2_INTERRUPT | I2C2 interrupt |
|
||||
* | 11 | IRQN_UART1_INTERRUPT | UART1 interrupt |
|
||||
* | 12 | IRQN_UART2_INTERRUPT | UART2 interrupt |
|
||||
* | 13 | IRQN_UART3_INTERRUPT | UART3 interrupt |
|
||||
* | 14 | IRQN_TIMER0A_INTERRUPT | TIMER0 channel 0 or 1 interrupt |
|
||||
* | 15 | IRQN_TIMER0B_INTERRUPT | TIMER0 channel 2 or 3 interrupt |
|
||||
* | 16 | IRQN_TIMER1A_INTERRUPT | TIMER1 channel 0 or 1 interrupt |
|
||||
* | 17 | IRQN_TIMER1B_INTERRUPT | TIMER1 channel 2 or 3 interrupt |
|
||||
* | 18 | IRQN_TIMER2A_INTERRUPT | TIMER2 channel 0 or 1 interrupt |
|
||||
* | 19 | IRQN_TIMER2B_INTERRUPT | TIMER2 channel 2 or 3 interrupt |
|
||||
* | 20 | IRQN_RTC_INTERRUPT | RTC tick and alarm interrupt |
|
||||
* | 21 | IRQN_WDT0_INTERRUPT | Watching dog timer0 interrupt |
|
||||
* | 22 | IRQN_WDT1_INTERRUPT | Watching dog timer1 interrupt |
|
||||
* | 23 | IRQN_APB_GPIO_INTERRUPT | APB GPIO interrupt |
|
||||
* | 24 | IRQN_DVP_INTERRUPT | Digital video port interrupt |
|
||||
* | 25 | IRQN_AI_INTERRUPT | AI accelerator interrupt |
|
||||
* | 26 | IRQN_FFT_INTERRUPT | FFT accelerator interrupt |
|
||||
* | 27 | IRQN_DMA0_INTERRUPT | DMA channel0 interrupt |
|
||||
* | 28 | IRQN_DMA1_INTERRUPT | DMA channel1 interrupt |
|
||||
* | 29 | IRQN_DMA2_INTERRUPT | DMA channel2 interrupt |
|
||||
* | 30 | IRQN_DMA3_INTERRUPT | DMA channel3 interrupt |
|
||||
* | 31 | IRQN_DMA4_INTERRUPT | DMA channel4 interrupt |
|
||||
* | 32 | IRQN_DMA5_INTERRUPT | DMA channel5 interrupt |
|
||||
* | 33 | IRQN_UARTHS_INTERRUPT | Hi-speed UART0 interrupt |
|
||||
* | 34 | IRQN_GPIOHS0_INTERRUPT | Hi-speed GPIO0 interrupt |
|
||||
* | 35 | IRQN_GPIOHS1_INTERRUPT | Hi-speed GPIO1 interrupt |
|
||||
* | 36 | IRQN_GPIOHS2_INTERRUPT | Hi-speed GPIO2 interrupt |
|
||||
* | 37 | IRQN_GPIOHS3_INTERRUPT | Hi-speed GPIO3 interrupt |
|
||||
* | 38 | IRQN_GPIOHS4_INTERRUPT | Hi-speed GPIO4 interrupt |
|
||||
* | 39 | IRQN_GPIOHS5_INTERRUPT | Hi-speed GPIO5 interrupt |
|
||||
* | 40 | IRQN_GPIOHS6_INTERRUPT | Hi-speed GPIO6 interrupt |
|
||||
* | 41 | IRQN_GPIOHS7_INTERRUPT | Hi-speed GPIO7 interrupt |
|
||||
* | 42 | IRQN_GPIOHS8_INTERRUPT | Hi-speed GPIO8 interrupt |
|
||||
* | 43 | IRQN_GPIOHS9_INTERRUPT | Hi-speed GPIO9 interrupt |
|
||||
* | 44 | IRQN_GPIOHS10_INTERRUPT | Hi-speed GPIO10 interrupt |
|
||||
* | 45 | IRQN_GPIOHS11_INTERRUPT | Hi-speed GPIO11 interrupt |
|
||||
* | 46 | IRQN_GPIOHS12_INTERRUPT | Hi-speed GPIO12 interrupt |
|
||||
* | 47 | IRQN_GPIOHS13_INTERRUPT | Hi-speed GPIO13 interrupt |
|
||||
* | 48 | IRQN_GPIOHS14_INTERRUPT | Hi-speed GPIO14 interrupt |
|
||||
* | 49 | IRQN_GPIOHS15_INTERRUPT | Hi-speed GPIO15 interrupt |
|
||||
* | 50 | IRQN_GPIOHS16_INTERRUPT | Hi-speed GPIO16 interrupt |
|
||||
* | 51 | IRQN_GPIOHS17_INTERRUPT | Hi-speed GPIO17 interrupt |
|
||||
* | 52 | IRQN_GPIOHS18_INTERRUPT | Hi-speed GPIO18 interrupt |
|
||||
* | 53 | IRQN_GPIOHS19_INTERRUPT | Hi-speed GPIO19 interrupt |
|
||||
* | 54 | IRQN_GPIOHS20_INTERRUPT | Hi-speed GPIO20 interrupt |
|
||||
* | 55 | IRQN_GPIOHS21_INTERRUPT | Hi-speed GPIO21 interrupt |
|
||||
* | 56 | IRQN_GPIOHS22_INTERRUPT | Hi-speed GPIO22 interrupt |
|
||||
* | 57 | IRQN_GPIOHS23_INTERRUPT | Hi-speed GPIO23 interrupt |
|
||||
* | 58 | IRQN_GPIOHS24_INTERRUPT | Hi-speed GPIO24 interrupt |
|
||||
* | 59 | IRQN_GPIOHS25_INTERRUPT | Hi-speed GPIO25 interrupt |
|
||||
* | 60 | IRQN_GPIOHS26_INTERRUPT | Hi-speed GPIO26 interrupt |
|
||||
* | 61 | IRQN_GPIOHS27_INTERRUPT | Hi-speed GPIO27 interrupt |
|
||||
* | 62 | IRQN_GPIOHS28_INTERRUPT | Hi-speed GPIO28 interrupt |
|
||||
* | 63 | IRQN_GPIOHS29_INTERRUPT | Hi-speed GPIO29 interrupt |
|
||||
* | 64 | IRQN_GPIOHS30_INTERRUPT | Hi-speed GPIO30 interrupt |
|
||||
* | 65 | IRQN_GPIOHS31_INTERRUPT | Hi-speed GPIO31 interrupt |
|
||||
*
|
||||
*/
|
||||
/* clang-format off */
|
||||
typedef enum _plic_irq
|
||||
{
|
||||
IRQN_NO_INTERRUPT = 0, /*!< The non-existent interrupt */
|
||||
IRQN_SPI0_INTERRUPT = 1, /*!< SPI0 interrupt */
|
||||
IRQN_SPI1_INTERRUPT = 2, /*!< SPI1 interrupt */
|
||||
IRQN_SPI_SLAVE_INTERRUPT = 3, /*!< SPI_SLAVE interrupt */
|
||||
IRQN_SPI3_INTERRUPT = 4, /*!< SPI3 interrupt */
|
||||
IRQN_I2S0_INTERRUPT = 5, /*!< I2S0 interrupt */
|
||||
IRQN_I2S1_INTERRUPT = 6, /*!< I2S1 interrupt */
|
||||
IRQN_I2S2_INTERRUPT = 7, /*!< I2S2 interrupt */
|
||||
IRQN_I2C0_INTERRUPT = 8, /*!< I2C0 interrupt */
|
||||
IRQN_I2C1_INTERRUPT = 9, /*!< I2C1 interrupt */
|
||||
IRQN_I2C2_INTERRUPT = 10, /*!< I2C2 interrupt */
|
||||
IRQN_UART1_INTERRUPT = 11, /*!< UART1 interrupt */
|
||||
IRQN_UART2_INTERRUPT = 12, /*!< UART2 interrupt */
|
||||
IRQN_UART3_INTERRUPT = 13, /*!< UART3 interrupt */
|
||||
IRQN_TIMER0A_INTERRUPT = 14, /*!< TIMER0 channel 0 or 1 interrupt */
|
||||
IRQN_TIMER0B_INTERRUPT = 15, /*!< TIMER0 channel 2 or 3 interrupt */
|
||||
IRQN_TIMER1A_INTERRUPT = 16, /*!< TIMER1 channel 0 or 1 interrupt */
|
||||
IRQN_TIMER1B_INTERRUPT = 17, /*!< TIMER1 channel 2 or 3 interrupt */
|
||||
IRQN_TIMER2A_INTERRUPT = 18, /*!< TIMER2 channel 0 or 1 interrupt */
|
||||
IRQN_TIMER2B_INTERRUPT = 19, /*!< TIMER2 channel 2 or 3 interrupt */
|
||||
IRQN_RTC_INTERRUPT = 20, /*!< RTC tick and alarm interrupt */
|
||||
IRQN_WDT0_INTERRUPT = 21, /*!< Watching dog timer0 interrupt */
|
||||
IRQN_WDT1_INTERRUPT = 22, /*!< Watching dog timer1 interrupt */
|
||||
IRQN_APB_GPIO_INTERRUPT = 23, /*!< APB GPIO interrupt */
|
||||
IRQN_DVP_INTERRUPT = 24, /*!< Digital video port interrupt */
|
||||
IRQN_AI_INTERRUPT = 25, /*!< AI accelerator interrupt */
|
||||
IRQN_FFT_INTERRUPT = 26, /*!< FFT accelerator interrupt */
|
||||
IRQN_DMA0_INTERRUPT = 27, /*!< DMA channel0 interrupt */
|
||||
IRQN_DMA1_INTERRUPT = 28, /*!< DMA channel1 interrupt */
|
||||
IRQN_DMA2_INTERRUPT = 29, /*!< DMA channel2 interrupt */
|
||||
IRQN_DMA3_INTERRUPT = 30, /*!< DMA channel3 interrupt */
|
||||
IRQN_DMA4_INTERRUPT = 31, /*!< DMA channel4 interrupt */
|
||||
IRQN_DMA5_INTERRUPT = 32, /*!< DMA channel5 interrupt */
|
||||
IRQN_UARTHS_INTERRUPT = 33, /*!< Hi-speed UART0 interrupt */
|
||||
IRQN_GPIOHS0_INTERRUPT = 34, /*!< Hi-speed GPIO0 interrupt */
|
||||
IRQN_GPIOHS1_INTERRUPT = 35, /*!< Hi-speed GPIO1 interrupt */
|
||||
IRQN_GPIOHS2_INTERRUPT = 36, /*!< Hi-speed GPIO2 interrupt */
|
||||
IRQN_GPIOHS3_INTERRUPT = 37, /*!< Hi-speed GPIO3 interrupt */
|
||||
IRQN_GPIOHS4_INTERRUPT = 38, /*!< Hi-speed GPIO4 interrupt */
|
||||
IRQN_GPIOHS5_INTERRUPT = 39, /*!< Hi-speed GPIO5 interrupt */
|
||||
IRQN_GPIOHS6_INTERRUPT = 40, /*!< Hi-speed GPIO6 interrupt */
|
||||
IRQN_GPIOHS7_INTERRUPT = 41, /*!< Hi-speed GPIO7 interrupt */
|
||||
IRQN_GPIOHS8_INTERRUPT = 42, /*!< Hi-speed GPIO8 interrupt */
|
||||
IRQN_GPIOHS9_INTERRUPT = 43, /*!< Hi-speed GPIO9 interrupt */
|
||||
IRQN_GPIOHS10_INTERRUPT = 44, /*!< Hi-speed GPIO10 interrupt */
|
||||
IRQN_GPIOHS11_INTERRUPT = 45, /*!< Hi-speed GPIO11 interrupt */
|
||||
IRQN_GPIOHS12_INTERRUPT = 46, /*!< Hi-speed GPIO12 interrupt */
|
||||
IRQN_GPIOHS13_INTERRUPT = 47, /*!< Hi-speed GPIO13 interrupt */
|
||||
IRQN_GPIOHS14_INTERRUPT = 48, /*!< Hi-speed GPIO14 interrupt */
|
||||
IRQN_GPIOHS15_INTERRUPT = 49, /*!< Hi-speed GPIO15 interrupt */
|
||||
IRQN_GPIOHS16_INTERRUPT = 50, /*!< Hi-speed GPIO16 interrupt */
|
||||
IRQN_GPIOHS17_INTERRUPT = 51, /*!< Hi-speed GPIO17 interrupt */
|
||||
IRQN_GPIOHS18_INTERRUPT = 52, /*!< Hi-speed GPIO18 interrupt */
|
||||
IRQN_GPIOHS19_INTERRUPT = 53, /*!< Hi-speed GPIO19 interrupt */
|
||||
IRQN_GPIOHS20_INTERRUPT = 54, /*!< Hi-speed GPIO20 interrupt */
|
||||
IRQN_GPIOHS21_INTERRUPT = 55, /*!< Hi-speed GPIO21 interrupt */
|
||||
IRQN_GPIOHS22_INTERRUPT = 56, /*!< Hi-speed GPIO22 interrupt */
|
||||
IRQN_GPIOHS23_INTERRUPT = 57, /*!< Hi-speed GPIO23 interrupt */
|
||||
IRQN_GPIOHS24_INTERRUPT = 58, /*!< Hi-speed GPIO24 interrupt */
|
||||
IRQN_GPIOHS25_INTERRUPT = 59, /*!< Hi-speed GPIO25 interrupt */
|
||||
IRQN_GPIOHS26_INTERRUPT = 60, /*!< Hi-speed GPIO26 interrupt */
|
||||
IRQN_GPIOHS27_INTERRUPT = 61, /*!< Hi-speed GPIO27 interrupt */
|
||||
IRQN_GPIOHS28_INTERRUPT = 62, /*!< Hi-speed GPIO28 interrupt */
|
||||
IRQN_GPIOHS29_INTERRUPT = 63, /*!< Hi-speed GPIO29 interrupt */
|
||||
IRQN_GPIOHS30_INTERRUPT = 64, /*!< Hi-speed GPIO30 interrupt */
|
||||
IRQN_GPIOHS31_INTERRUPT = 65, /*!< Hi-speed GPIO31 interrupt */
|
||||
IRQN_MAX
|
||||
} plic_irq_t;
|
||||
/* clang-format on */
|
||||
|
||||
/**
|
||||
* @brief Interrupt Source Priorities
|
||||
*
|
||||
* Each external interrupt source can be assigned a priority by
|
||||
* writing to its 32-bit memory-mapped priority register. The
|
||||
* number and value of supported priority levels can vary by
|
||||
* implementa- tion, with the simplest implementations having all
|
||||
* devices hardwired at priority 1, in which case, interrupts with
|
||||
* the lowest ID have the highest effective priority. The priority
|
||||
* registers are all WARL.
|
||||
*/
|
||||
typedef struct _plic_source_priorities
|
||||
{
|
||||
/* 0x0C000000: Reserved, 0x0C000004-0x0C000FFC: 1-1023 priorities */
|
||||
uint32_t priority[1024];
|
||||
} __attribute__((packed, aligned(4))) plic_source_priorities_t;
|
||||
|
||||
/**
|
||||
* @brief Interrupt Pending Bits
|
||||
*
|
||||
* The current status of the interrupt source pending bits in the
|
||||
* PLIC core can be read from the pending array, organized as 32
|
||||
* words of 32 bits. The pending bit for interrupt ID N is stored
|
||||
* in bit (N mod 32) of word (N/32). Bit 0 of word 0, which
|
||||
* represents the non-existent interrupt source 0, is always
|
||||
* hardwired to zero. The pending bits are read-only. A pending
|
||||
* bit in the PLIC core can be cleared by setting enable bits to
|
||||
* only enable the desired interrupt, then performing a claim. A
|
||||
* pending bit can be set by instructing the associated gateway to
|
||||
* send an interrupt service request.
|
||||
*/
|
||||
typedef struct _plic_pending_bits
|
||||
{
|
||||
/* 0x0C001000-0x0C00107C: Bit 0 is zero, Bits 1-1023 is pending bits */
|
||||
uint32_t u32[32];
|
||||
/* 0x0C001080-0x0C001FFF: Reserved */
|
||||
uint8_t resv[0xF80];
|
||||
} __attribute__((packed, aligned(4))) plic_pending_bits_t;
|
||||
|
||||
/**
|
||||
* @brief Target Interrupt Enables
|
||||
*
|
||||
* For each interrupt target, each device’s interrupt can be
|
||||
* enabled by setting the corresponding bit in that target’s
|
||||
* enables registers. The enables for a target are accessed as a
|
||||
* contiguous array of 32×32-bit words, packed the same way as the
|
||||
* pending bits. For each target, bit 0 of enable word 0
|
||||
* represents the non-existent interrupt ID 0 and is hardwired to
|
||||
* 0. Unused interrupt IDs are also hardwired to zero. The enables
|
||||
* arrays for different targets are packed contiguously in the
|
||||
* address space. Only 32-bit word accesses are supported by the
|
||||
* enables array in RV32 systems. Implementations can trap on
|
||||
* accesses to enables for non-existent targets, but must allow
|
||||
* access to the full enables array for any extant target,
|
||||
* treating all non-existent interrupt source’s enables as
|
||||
* hardwired to zero.
|
||||
*/
|
||||
typedef struct _plic_target_enables
|
||||
{
|
||||
/* 0x0C002000-0x0C1F1F80: target 0-15871 enables */
|
||||
struct
|
||||
{
|
||||
uint32_t enable[32 * 2];/* Offset 0x00-0x7C: Bit 0 is zero, Bits 1-1023 is bits*/
|
||||
} target[15872 / 2];
|
||||
|
||||
/* 0x0C1F2000-0x0C1FFFFC: Reserved, size 0xE000 */
|
||||
uint8_t resv[0xE000];
|
||||
} __attribute__((packed, aligned(4))) plic_target_enables_t;
|
||||
|
||||
/**
|
||||
* @brief PLIC Targets
|
||||
*
|
||||
* Target Priority Thresholds The threshold for a pending
|
||||
* interrupt priority that can interrupt each target can be set in
|
||||
* the target’s threshold register. The threshold is a WARL field,
|
||||
* where different implementations can support different numbers
|
||||
* of thresholds. The simplest implementation has a threshold
|
||||
* hardwired to zero.
|
||||
*
|
||||
* Target Claim Each target can perform a claim by reading the
|
||||
* claim/complete register, which returns the ID of the highest
|
||||
* priority pending interrupt or zero if there is no pending
|
||||
* interrupt for the target. A successful claim will also
|
||||
* atomically clear the corresponding pending bit on the interrupt
|
||||
* source. A target can perform a claim at any time, even if the
|
||||
* EIP is not set. The claim operation is not affected by the
|
||||
* setting of the target’s priority threshold register.
|
||||
*
|
||||
* Target Completion A target signals it has completed running a
|
||||
* handler by writing the interrupt ID it received from the claim
|
||||
* to the claim/complete register. This is routed to the
|
||||
* corresponding interrupt gateway, which can now send another
|
||||
* interrupt request to the PLIC. The PLIC does not check whether
|
||||
* the completion ID is the same as the last claim ID for that
|
||||
* target. If the completion ID does not match an interrupt source
|
||||
* that is currently enabled for the target, the completion is
|
||||
* silently ignored.
|
||||
*/
|
||||
typedef struct _plic_target
|
||||
{
|
||||
/* 0x0C200000-0x0FFFF004: target 0-15871 */
|
||||
struct {
|
||||
uint32_t priority_threshold;/* Offset 0x000 */
|
||||
uint32_t claim_complete; /* Offset 0x004 */
|
||||
uint8_t resv[0x1FF8]; /* Offset 0x008, Size 0xFF8 */
|
||||
} target[15872 / 2];
|
||||
} __attribute__((packed, aligned(4))) plic_target_t;
|
||||
|
||||
/**
|
||||
* @brief Platform-Level Interrupt Controller
|
||||
*
|
||||
* PLIC is Platform-Level Interrupt Controller. The PLIC complies
|
||||
* with the RISC-V Privileged Architecture specification, and can
|
||||
* support a maximum of 1023 external interrupt sources targeting
|
||||
* up to 15,872 core contexts.
|
||||
*/
|
||||
typedef struct _plic
|
||||
{
|
||||
/* 0x0C000000-0x0C000FFC */
|
||||
plic_source_priorities_t source_priorities;
|
||||
/* 0x0C001000-0x0C001FFF */
|
||||
const plic_pending_bits_t pending_bits;
|
||||
/* 0x0C002000-0x0C1FFFFC */
|
||||
plic_target_enables_t target_enables;
|
||||
/* 0x0C200000-0x0FFFF004 */
|
||||
plic_target_t targets;
|
||||
} __attribute__((packed, aligned(4))) plic_t;
|
||||
|
||||
extern volatile plic_t *const plic;
|
||||
|
||||
/**
|
||||
* @brief Definitions for the interrupt callbacks
|
||||
*/
|
||||
typedef int (*plic_irq_callback_t)(void *ctx);
|
||||
|
||||
/**
|
||||
* @brief Definitions for IRQ table instance
|
||||
*/
|
||||
typedef struct _plic_instance_t
|
||||
{
|
||||
plic_irq_callback_t callback;
|
||||
void *ctx;
|
||||
} plic_instance_t;
|
||||
|
||||
typedef struct _plic_callback_t
|
||||
{
|
||||
plic_irq_callback_t callback;
|
||||
void *ctx;
|
||||
uint32_t priority;
|
||||
} plic_interrupt_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize PLIC external interrupt
|
||||
*
|
||||
* @note This function will set MIP_MEIP. The MSTATUS_MIE must set by user.
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void plic_init(void);
|
||||
|
||||
/**
|
||||
* @brief Enable PLIC external interrupt
|
||||
*
|
||||
* @param[in] irq_number external interrupt number
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
|
||||
int plic_irq_enable(plic_irq_t irq_number);
|
||||
|
||||
/**
|
||||
* @brief Disable PLIC external interrupt
|
||||
*
|
||||
* @param[in] irq_number The external interrupt number
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int plic_irq_disable(plic_irq_t irq_number);
|
||||
|
||||
/**
|
||||
* @brief Set IRQ priority
|
||||
*
|
||||
* @param[in] irq_number The external interrupt number
|
||||
* @param[in] priority The priority of external interrupt number
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int plic_set_priority(plic_irq_t irq_number, uint32_t priority);
|
||||
|
||||
/**
|
||||
* @brief Get IRQ priority
|
||||
*
|
||||
* @param[in] irq_number The external interrupt number
|
||||
*
|
||||
* @return The priority of external interrupt number
|
||||
*/
|
||||
uint32_t plic_get_priority(plic_irq_t irq_number);
|
||||
|
||||
/**
|
||||
* @brief Claim an IRQ
|
||||
*
|
||||
* @return The current IRQ number
|
||||
*/
|
||||
uint32_t plic_irq_claim(void);
|
||||
|
||||
/**
|
||||
* @brief Complete an IRQ
|
||||
*
|
||||
* @param[in] source The source IRQ number to complete
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int plic_irq_complete(uint32_t source);
|
||||
|
||||
/**
|
||||
* @brief Register user callback function by IRQ number
|
||||
*
|
||||
* @param[in] irq The irq
|
||||
* @param[in] callback The callback
|
||||
* @param ctx The context
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void plic_irq_register(plic_irq_t irq, plic_irq_callback_t callback, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief Deegister user callback function by IRQ number
|
||||
*
|
||||
* @param[in] irq The irq
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void plic_irq_deregister(plic_irq_t irq);
|
||||
|
||||
/**
|
||||
* @brief Deegister user callback function by IRQ number
|
||||
*
|
||||
* @param[in] irq The irq
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void plic_irq_unregister(plic_irq_t irq);
|
||||
|
||||
/**
|
||||
* @brief Get IRQ table, Usage:
|
||||
* plic_instance_t (*plic_instance)[IRQN_MAX] = plic_get_instance();
|
||||
* ... plic_instance[x][y] ...;
|
||||
*
|
||||
* @return the point of IRQ table
|
||||
*/
|
||||
plic_instance_t (*plic_get_instance(void))[IRQN_MAX];
|
||||
|
||||
/* For c++ compatibility */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_PLIC_H */
|
||||
@@ -0,0 +1,390 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file syscall.c
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
/* Enable kernel-mode log API */
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/board.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "riscv_arch.h"
|
||||
#include "riscv_internal.h"
|
||||
|
||||
#include "group/group.h"
|
||||
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <machine/syscall.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <debug.h>
|
||||
#include "syscalls.h"
|
||||
#include "clint.h"
|
||||
#include "interrupt.h"
|
||||
#include "sysctl.h"
|
||||
#include "syslog.h"
|
||||
#include "encoding.h"
|
||||
|
||||
|
||||
/**
|
||||
* @note System call list
|
||||
*
|
||||
* See also riscv-newlib/libgloss/riscv/syscalls.c
|
||||
*
|
||||
* | System call | Number |
|
||||
* |------------------|--------|
|
||||
* | SYS_exit | 93 |
|
||||
* | SYS_exit_group | 94 |
|
||||
* | SYS_getpid | 172 |
|
||||
* | SYS_kill | 129 |
|
||||
* | SYS_read | 63 |
|
||||
* | SYS_write | 64 |
|
||||
* | SYS_open | 1024 |
|
||||
* | SYS_openat | 56 |
|
||||
* | SYS_close | 57 |
|
||||
* | SYS_lseek | 62 |
|
||||
* | SYS_brk | 214 |
|
||||
* | SYS_link | 1025 |
|
||||
* | SYS_unlink | 1026 |
|
||||
* | SYS_mkdir | 1030 |
|
||||
* | SYS_chdir | 49 |
|
||||
* | SYS_getcwd | 17 |
|
||||
* | SYS_stat | 1038 |
|
||||
* | SYS_fstat | 80 |
|
||||
* | SYS_lstat | 1039 |
|
||||
* | SYS_fstatat | 79 |
|
||||
* | SYS_access | 1033 |
|
||||
* | SYS_faccessat | 48 |
|
||||
* | SYS_pread | 67 |
|
||||
* | SYS_pwrite | 68 |
|
||||
* | SYS_uname | 160 |
|
||||
* | SYS_getuid | 174 |
|
||||
* | SYS_geteuid | 175 |
|
||||
* | SYS_getgid | 176 |
|
||||
* | SYS_getegid | 177 |
|
||||
* | SYS_mmap | 222 |
|
||||
* | SYS_munmap | 215 |
|
||||
* | SYS_mremap | 216 |
|
||||
* | SYS_time | 1062 |
|
||||
* | SYS_getmainvars | 2011 |
|
||||
* | SYS_rt_sigaction | 134 |
|
||||
* | SYS_writev | 66 |
|
||||
* | SYS_gettimeofday | 169 |
|
||||
* | SYS_times | 153 |
|
||||
* | SYS_fcntl | 25 |
|
||||
* | SYS_getdents | 61 |
|
||||
* | SYS_dup | 23 |
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef UNUSED
|
||||
#define UNUSED(x) (void)(x)
|
||||
#endif
|
||||
|
||||
void __attribute__((noreturn)) sys_exit(int code)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* First print some diagnostic information. */
|
||||
syslog(LOG_WARNING, "SYSCALL sys_exit called by core %ld with 0x%lx\n", core_id, (uint64_t)code);
|
||||
while (1)
|
||||
continue;
|
||||
}
|
||||
|
||||
static int sys_nosys(long a0, long a1, long a2, long a3, long a4, long a5, unsigned long n)
|
||||
{
|
||||
UNUSED(a3);
|
||||
UNUSED(a4);
|
||||
UNUSED(a5);
|
||||
|
||||
syslog(LOG_ERR, "SYSCALL Unsupported syscall %ld: a0=%lx, a1=%lx, a2=%lx!\n", n, a0, a1, a2);
|
||||
while (1)
|
||||
continue;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int sys_success(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_ecall_u(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_ecall_h(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
return epc;
|
||||
}
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_ecall_s(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_ecall_m(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
uint64_t* ptr = (uint64_t*)regs;
|
||||
CURRENT_REGS = (uint64_t*)regs;
|
||||
ptr[0] = epc+4;
|
||||
ptr[2] = ptr[2] + 0x200 ;
|
||||
irq_dispatch(K210_IRQ_MSOFT, ptr);
|
||||
void* tmp = g_current_regs;
|
||||
epc = ((uint64_t*)tmp)[0];
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
return epc;
|
||||
}
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_misaligned_fetch(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
//dump_core("misaligned fetch", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_fault_fetch(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
//dump_core("fault fetch", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_illegal_instruction(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
//dump_core("illegal instruction", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_breakpoint(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
//dump_core("breakpoint", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_misaligned_load(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
/* notice this function only support 16bit or 32bit instruction */
|
||||
|
||||
bool compressed = (*(unsigned short *)epc & 3) != 3;
|
||||
bool fpu = 0; /* load to fpu ? */
|
||||
uintptr_t addr = 0; /* src addr */
|
||||
uint8_t src = 0; /* src register */
|
||||
uint8_t dst = 0; /* dst register */
|
||||
uint8_t len = 0; /* data length */
|
||||
int offset = 0; /* addr offset to addr in reg */
|
||||
bool unsigned_ = 0; /* unsigned */
|
||||
uint64_t data_load = 0;/* real data load */
|
||||
|
||||
if (compressed)
|
||||
{
|
||||
/* compressed instruction should not get this fault. */
|
||||
goto on_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t instruct = *(uint32_t *)epc;
|
||||
uint8_t opcode = instruct&0x7F;
|
||||
|
||||
dst = (instruct >> 7)&0x1F;
|
||||
len = (instruct >> 12)&3;
|
||||
unsigned_ = (instruct >> 14)&1;
|
||||
src = (instruct >> 15)&0x1F;
|
||||
offset = (instruct >> 20);
|
||||
len = 1 << len;
|
||||
switch (opcode)
|
||||
{
|
||||
case 3:/* load */
|
||||
break;
|
||||
case 7:/* fpu load */
|
||||
fpu = 1;
|
||||
break;
|
||||
default:
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset >> 11)
|
||||
offset = -((offset & 0x3FF) + 1);
|
||||
|
||||
addr = (uint64_t)((uint64_t)regs[src] + offset);
|
||||
|
||||
for (int i = 0; i < len; ++i)
|
||||
data_load |= ((uint64_t)*((uint8_t *)addr + i)) << (8 * i);
|
||||
|
||||
|
||||
if (!unsigned_ & !fpu)
|
||||
{
|
||||
/* adjust sign */
|
||||
switch (len)
|
||||
{
|
||||
case 1:
|
||||
data_load = (uint64_t)(int64_t)((int8_t)data_load);
|
||||
break;
|
||||
case 2:
|
||||
data_load = (uint64_t)(int64_t)((int16_t)data_load);
|
||||
break;
|
||||
case 4:
|
||||
data_load = (uint64_t)(int64_t)((int32_t)data_load);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fpu)
|
||||
fregs[dst] = data_load;
|
||||
else
|
||||
regs[dst] = data_load;
|
||||
|
||||
syslog(LOG_DEBUG, "misaligned load recovered at %08lx. len:%02d,addr:%08lx,reg:%02d,data:%016lx,signed:%1d,float:%1d", (uint64_t)epc, len, (uint64_t)addr, dst, data_load, !unsigned_, fpu);
|
||||
|
||||
return epc + (compressed ? 2 : 4);
|
||||
on_error:
|
||||
//dump_core("misaligned load", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_fault_load(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
//dump_core("fault load", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_misaligned_store(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
/* notice this function only support 16bit or 32bit instruction */
|
||||
|
||||
bool compressed = (*(unsigned short *)epc & 3) != 3;
|
||||
bool fpu = 0; /* store to fpu*/
|
||||
uintptr_t addr = 0; /* src addr*/
|
||||
uint8_t src = 0; /* src register*/
|
||||
uint8_t dst = 0; /* dst register*/
|
||||
uint8_t len = 0; /* data length*/
|
||||
int offset = 0; /* addr offset to addr in reg*/
|
||||
uint64_t data_store = 0;/* real data store*/
|
||||
|
||||
if (compressed)
|
||||
{
|
||||
/* compressed instruction should not get this fault. */
|
||||
goto on_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t instruct = *(uint32_t *)epc;
|
||||
uint8_t opcode = instruct&0x7F;
|
||||
|
||||
len = (instruct >> 12)&7;
|
||||
dst = (instruct >> 15)&0x1F;
|
||||
src = (instruct >> 20)&0x1F;
|
||||
offset = ((instruct >> 7)&0x1F) | ((instruct >> 20)&0xFE0);
|
||||
len = 1 << len;
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x23:/* store */
|
||||
break;
|
||||
case 0x27:/* fpu store */
|
||||
fpu = 1;
|
||||
break;
|
||||
default:
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset >> 11)
|
||||
offset = -((offset & 0x3FF) + 1);
|
||||
|
||||
addr = (uint64_t)((uint64_t)regs[dst] + offset);
|
||||
|
||||
|
||||
if (fpu)
|
||||
data_store = fregs[src];
|
||||
else
|
||||
data_store = regs[src];
|
||||
|
||||
for (int i = 0; i < len; ++i)
|
||||
*((uint8_t *)addr + i) = (data_store >> (i*8)) & 0xFF;
|
||||
|
||||
syslog(LOG_DEBUG, "misaligned store recovered at %08lx. len:%02d,addr:%08lx,reg:%02d,data:%016lx,float:%1d", (uint64_t)epc, len, (uint64_t)addr, src, data_store, fpu);
|
||||
|
||||
return epc + (compressed ? 2 : 4);
|
||||
on_error:
|
||||
//dump_core("misaligned store", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_fault_store(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
//dump_core("fault store", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t handle_syscall(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
static uintptr_t (* const cause_table[])(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32]) =
|
||||
{
|
||||
[CAUSE_MISALIGNED_FETCH] = handle_misaligned_fetch,
|
||||
[CAUSE_FAULT_FETCH] = handle_fault_fetch,
|
||||
[CAUSE_ILLEGAL_INSTRUCTION] = handle_illegal_instruction,
|
||||
[CAUSE_BREAKPOINT] = handle_breakpoint,
|
||||
[CAUSE_MISALIGNED_LOAD] = handle_misaligned_load,
|
||||
[CAUSE_FAULT_LOAD] = handle_fault_load,
|
||||
[CAUSE_MISALIGNED_STORE] = handle_misaligned_store,
|
||||
[CAUSE_FAULT_STORE] = handle_fault_store,
|
||||
[CAUSE_USER_ECALL] = handle_ecall_u,
|
||||
[CAUSE_SUPERVISOR_ECALL] = handle_ecall_h,
|
||||
[CAUSE_HYPERVISOR_ECALL] = handle_ecall_s,
|
||||
[CAUSE_MACHINE_ECALL] = handle_ecall_m,
|
||||
};
|
||||
return cause_table[cause](cause, epc, regs, fregs);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file syscall.h
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#ifndef _BSP_SYSCALLS_H
|
||||
#define _BSP_SYSCALLS_H
|
||||
|
||||
#include <machine/syscall.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void __attribute__((noreturn)) sys_exit(int code);
|
||||
|
||||
void setStats(int enable);
|
||||
|
||||
#undef putchar
|
||||
int putchar(int ch);
|
||||
void printstr(const char *s);
|
||||
|
||||
void printhex(uint64_t x);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BSP_SYSCALLS_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,191 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file uarths.c
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "uarths.h"
|
||||
#include "sysctl.h"
|
||||
#include "encoding.h"
|
||||
#include <nuttx/arch.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
volatile uarths_t *const uarths = (volatile uarths_t *)UARTHS_BASE_ADDR;
|
||||
|
||||
typedef struct _uarths_instance
|
||||
{
|
||||
plic_irq_callback_t callback;
|
||||
void *ctx;
|
||||
uarths_interrupt_mode_t uarths_interrupt_mode;
|
||||
} uarths_instance_t;
|
||||
|
||||
uarths_instance_t g_uarths_instance;
|
||||
|
||||
uarths_interrupt_mode_t uarths_get_interrupt_mode(void)
|
||||
{
|
||||
uint32_t v_rx_interrupt = uarths->ip.rxwm;
|
||||
uint32_t v_tx_interrupt = uarths->ip.txwm;
|
||||
return (v_rx_interrupt << 1) | v_tx_interrupt;
|
||||
}
|
||||
|
||||
int uarths_irq_callback(int irq, void *ctx, void *arg)
|
||||
{
|
||||
uarths_instance_t *uart_context = (uarths_instance_t *)ctx;
|
||||
|
||||
if(uart_context->callback)
|
||||
uart_context->callback(uart_context->ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uarths_set_interrupt_cnt(uarths_interrupt_mode_t interrupt_mode, uint8_t cnt)
|
||||
{
|
||||
switch(interrupt_mode)
|
||||
{
|
||||
case UARTHS_SEND:
|
||||
uarths->txctrl.txcnt = cnt;
|
||||
break;
|
||||
case UARTHS_RECEIVE:
|
||||
uarths->rxctrl.rxcnt = cnt;
|
||||
break;
|
||||
case UARTHS_SEND_RECEIVE:
|
||||
default:
|
||||
uarths->txctrl.txcnt = cnt;
|
||||
uarths->rxctrl.rxcnt = cnt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void uarths_set_irq(uarths_interrupt_mode_t interrupt_mode, plic_irq_callback_t uarths_callback, void *ctx, uint32_t priority)
|
||||
{
|
||||
int ret;
|
||||
g_uarths_instance.callback = uarths_callback;
|
||||
g_uarths_instance.ctx = ctx;
|
||||
|
||||
switch(interrupt_mode)
|
||||
{
|
||||
case UARTHS_SEND:
|
||||
uarths->ie.txwm = 1;
|
||||
uarths->ie.rxwm = 0;
|
||||
break;
|
||||
case UARTHS_RECEIVE:
|
||||
uarths->ie.txwm = 0;
|
||||
uarths->ie.rxwm = 1;
|
||||
break;
|
||||
default:
|
||||
uarths->ie.txwm = 1;
|
||||
uarths->ie.rxwm = 1;
|
||||
break;
|
||||
}
|
||||
g_uarths_instance.uarths_interrupt_mode = interrupt_mode;
|
||||
|
||||
plic_set_priority(IRQN_UARTHS_INTERRUPT, priority);
|
||||
ret = irq_attach(IRQN_UARTHS_INTERRUPT, uarths_irq_callback, &g_uarths_instance);
|
||||
if (ret == OK)
|
||||
{
|
||||
up_enable_irq(IRQN_UARTHS_INTERRUPT);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int uarths_putc(char c)
|
||||
{
|
||||
while (uarths->txdata.full)
|
||||
continue;
|
||||
uarths->txdata.data = (uint8_t)c;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t uarths_receive_data(uint8_t *buf, size_t buf_len)
|
||||
{
|
||||
size_t i;
|
||||
for(i = 0; i < buf_len; i++)
|
||||
{
|
||||
uarths_rxdata_t recv = uarths->rxdata;
|
||||
if(recv.empty)
|
||||
break;
|
||||
else
|
||||
buf[i] = (recv.data & 0xFF);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
size_t uarths_send_data(const uint8_t *buf, size_t buf_len)
|
||||
{
|
||||
size_t write = 0;
|
||||
while (write < buf_len)
|
||||
{
|
||||
uarths_putc(*buf++);
|
||||
write++;
|
||||
}
|
||||
return write;
|
||||
}
|
||||
|
||||
int uarths_getc(void)
|
||||
{
|
||||
/* while not empty */
|
||||
uarths_rxdata_t recv = uarths->rxdata;
|
||||
|
||||
if (recv.empty)
|
||||
return EOF;
|
||||
else
|
||||
return recv.data;
|
||||
}
|
||||
|
||||
int uarths_putchar(char c)
|
||||
{
|
||||
return uarths_putc(c);
|
||||
}
|
||||
|
||||
int uarths_puts(const char *s)
|
||||
{
|
||||
while (*s)
|
||||
if (uarths_putc(*s++) != 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uarths_init(void)
|
||||
{
|
||||
uint32_t freq = sysctl_clock_get_freq(SYSCTL_CLOCK_CPU);
|
||||
uint16_t div = freq / 115200 - 1;
|
||||
|
||||
/* Set UART registers */
|
||||
uarths->div.div = div;
|
||||
uarths->txctrl.txen = 1;
|
||||
uarths->rxctrl.rxen = 1;
|
||||
uarths->txctrl.txcnt = 0;
|
||||
uarths->rxctrl.rxcnt = 0;
|
||||
uarths->ip.txwm = 1;
|
||||
uarths->ip.rxwm = 1;
|
||||
uarths->ie.txwm = 0;
|
||||
uarths->ie.rxwm = 1;
|
||||
}
|
||||
|
||||
void uarths_config(uint32_t baud_rate, uarths_stopbit_t stopbit)
|
||||
{
|
||||
uint32_t freq = sysctl_clock_get_freq(SYSCTL_CLOCK_CPU);
|
||||
uint16_t div = freq / baud_rate - 1;
|
||||
uarths->div.div = div;
|
||||
uarths->txctrl.nstop = stopbit;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,302 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Universal Asynchronous Receiver/Transmitter (UART)
|
||||
*
|
||||
* The UART peripheral supports the following features:
|
||||
*
|
||||
* - 8-N-1 and 8-N-2 formats: 8 data bits, no parity bit, 1 start
|
||||
* bit, 1 or 2 stop bits
|
||||
*
|
||||
* - 8-entry transmit and receive FIFO buffers with programmable
|
||||
* watermark interrupts
|
||||
*
|
||||
* - 16× Rx oversampling with 2/3 majority voting per bit
|
||||
*
|
||||
* The UART peripheral does not support hardware flow control or
|
||||
* other modem control signals, or synchronous serial data
|
||||
* tranfesrs.
|
||||
*
|
||||
* @note UART RAM Layout
|
||||
*
|
||||
* | Address | Name | Description |
|
||||
* |-----------|----------|---------------------------------|
|
||||
* | 0x000 | txdata | Transmit data register |
|
||||
* | 0x004 | rxdata | Receive data register |
|
||||
* | 0x008 | txctrl | Transmit control register |
|
||||
* | 0x00C | rxctrl | Receive control register |
|
||||
* | 0x010 | ie | UART interrupt enable |
|
||||
* | 0x014 | ip | UART Interrupt pending |
|
||||
* | 0x018 | div | Baud rate divisor |
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file uarths.h
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#ifndef _DRIVER_UARTHS_H
|
||||
#define _DRIVER_UARTHS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "plic.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
/* Register address offsets */
|
||||
#define UARTHS_REG_TXFIFO (0x00)
|
||||
#define UARTHS_REG_RXFIFO (0x04)
|
||||
#define UARTHS_REG_TXCTRL (0x08)
|
||||
#define UARTHS_REG_RXCTRL (0x0c)
|
||||
#define UARTHS_REG_IE (0x10)
|
||||
#define UARTHS_REG_IP (0x14)
|
||||
#define UARTHS_REG_DIV (0x18)
|
||||
|
||||
/* TXCTRL register */
|
||||
#define UARTHS_TXEN (0x01)
|
||||
#define UARTHS_TXWM(x) (((x) & 0xffff) << 16)
|
||||
|
||||
/* RXCTRL register */
|
||||
#define UARTHS_RXEN (0x01)
|
||||
#define UARTHS_RXWM(x) (((x) & 0xffff) << 16)
|
||||
|
||||
/* IP register */
|
||||
#define UARTHS_IP_TXWM (0x01)
|
||||
#define UARTHS_IP_RXWM (0x02)
|
||||
/* clang-format on */
|
||||
|
||||
typedef struct _uarths_txdata
|
||||
{
|
||||
/* Bits [7:0] is data */
|
||||
uint32_t data : 8;
|
||||
/* Bits [30:8] is 0 */
|
||||
uint32_t zero : 23;
|
||||
/* Bit 31 is full status */
|
||||
uint32_t full : 1;
|
||||
} __attribute__((packed, aligned(4))) uarths_txdata_t;
|
||||
|
||||
typedef struct _uarths_rxdata
|
||||
{
|
||||
/* Bits [7:0] is data */
|
||||
uint32_t data : 8;
|
||||
/* Bits [30:8] is 0 */
|
||||
uint32_t zero : 23;
|
||||
/* Bit 31 is empty status */
|
||||
uint32_t empty : 1;
|
||||
} __attribute__((packed, aligned(4))) uarths_rxdata_t;
|
||||
|
||||
typedef struct _uarths_txctrl
|
||||
{
|
||||
/* Bit 0 is txen, controls whether the Tx channel is active. */
|
||||
uint32_t txen : 1;
|
||||
/* Bit 1 is nstop, 0 for one stop bit and 1 for two stop bits */
|
||||
uint32_t nstop : 1;
|
||||
/* Bits [15:2] is reserved */
|
||||
uint32_t resv0 : 14;
|
||||
/* Bits [18:16] is threshold of interrupt triggers */
|
||||
uint32_t txcnt : 3;
|
||||
/* Bits [31:19] is reserved */
|
||||
uint32_t resv1 : 13;
|
||||
} __attribute__((packed, aligned(4))) uarths_txctrl_t;
|
||||
|
||||
typedef struct _uarths_rxctrl
|
||||
{
|
||||
/* Bit 0 is txen, controls whether the Tx channel is active. */
|
||||
uint32_t rxen : 1;
|
||||
/* Bits [15:1] is reserved */
|
||||
uint32_t resv0 : 15;
|
||||
/* Bits [18:16] is threshold of interrupt triggers */
|
||||
uint32_t rxcnt : 3;
|
||||
/* Bits [31:19] is reserved */
|
||||
uint32_t resv1 : 13;
|
||||
} __attribute__((packed, aligned(4))) uarths_rxctrl_t;
|
||||
|
||||
typedef struct _uarths_ip
|
||||
{
|
||||
/* Bit 0 is txwm, raised less than txcnt */
|
||||
uint32_t txwm : 1;
|
||||
/* Bit 1 is txwm, raised greater than rxcnt */
|
||||
uint32_t rxwm : 1;
|
||||
/* Bits [31:2] is 0 */
|
||||
uint32_t zero : 30;
|
||||
} __attribute__((packed, aligned(4))) uarths_ip_t;
|
||||
|
||||
typedef struct _uarths_ie
|
||||
{
|
||||
/* Bit 0 is txwm, raised less than txcnt */
|
||||
uint32_t txwm : 1;
|
||||
/* Bit 1 is txwm, raised greater than rxcnt */
|
||||
uint32_t rxwm : 1;
|
||||
/* Bits [31:2] is 0 */
|
||||
uint32_t zero : 30;
|
||||
} __attribute__((packed, aligned(4))) uarths_ie_t;
|
||||
|
||||
typedef struct _uarths_div
|
||||
{
|
||||
/* Bits [31:2] is baud rate divisor register */
|
||||
uint32_t div : 16;
|
||||
/* Bits [31:16] is 0 */
|
||||
uint32_t zero : 16;
|
||||
} __attribute__((packed, aligned(4))) uarths_div_t;
|
||||
|
||||
typedef struct _uarths
|
||||
{
|
||||
/* Address offset 0x00 */
|
||||
uarths_txdata_t txdata;
|
||||
/* Address offset 0x04 */
|
||||
uarths_rxdata_t rxdata;
|
||||
/* Address offset 0x08 */
|
||||
uarths_txctrl_t txctrl;
|
||||
/* Address offset 0x0c */
|
||||
uarths_rxctrl_t rxctrl;
|
||||
/* Address offset 0x10 */
|
||||
uarths_ie_t ie;
|
||||
/* Address offset 0x14 */
|
||||
uarths_ip_t ip;
|
||||
/* Address offset 0x18 */
|
||||
uarths_div_t div;
|
||||
} __attribute__((packed, aligned(4))) uarths_t;
|
||||
|
||||
typedef enum _uarths_interrupt_mode
|
||||
{
|
||||
UARTHS_SEND = 1,
|
||||
UARTHS_RECEIVE = 2,
|
||||
UARTHS_SEND_RECEIVE = 3,
|
||||
} uarths_interrupt_mode_t;
|
||||
|
||||
typedef enum _uarths_stopbit
|
||||
{
|
||||
UARTHS_STOP_1,
|
||||
UARTHS_STOP_2
|
||||
} uarths_stopbit_t;
|
||||
|
||||
extern volatile uarths_t *const uarths;
|
||||
|
||||
/**
|
||||
* @brief Initialization Core UART
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void uarths_init(void);
|
||||
|
||||
/**
|
||||
* @brief Put a char to UART
|
||||
*
|
||||
* @param[in] c The char to put
|
||||
*
|
||||
* @note If c is '\n', a '\r' will be appended automatically
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int uarths_putchar(char c);
|
||||
|
||||
/**
|
||||
* @brief Send a string to UART
|
||||
*
|
||||
* @param[in] s The string to send
|
||||
*
|
||||
* @note The string must ending with '\0'
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int uarths_puts(const char *s);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a byte from UART
|
||||
*
|
||||
* @return byte as int type from UART
|
||||
*/
|
||||
int uarths_getc(void);
|
||||
|
||||
/**
|
||||
* @brief Set uarths interrupt callback
|
||||
*
|
||||
* @param[in] interrupt_mode Interrupt mode recevice or send
|
||||
* @param[in] uarths_callback Interrupt callback
|
||||
* @param[in] ctx Param of callback
|
||||
* @param[in] priority Interrupt priority
|
||||
*
|
||||
*/
|
||||
void uarths_set_irq(uarths_interrupt_mode_t interrupt_mode, plic_irq_callback_t uarths_callback, void *ctx, uint32_t priority);
|
||||
|
||||
/**
|
||||
* @brief Uarths receive data
|
||||
*
|
||||
* @param[in] buf The data received
|
||||
* @param[in] buf_len The length of data
|
||||
*
|
||||
* @return Number of received data
|
||||
*/
|
||||
size_t uarths_receive_data(uint8_t *buf, size_t buf_len);
|
||||
|
||||
/**
|
||||
* @brief Uarths receive data
|
||||
*
|
||||
* @param[in] buf The data sended
|
||||
* @param[in] buf_len The length of data
|
||||
*
|
||||
* @return Number of sended data
|
||||
*/
|
||||
size_t uarths_send_data(const uint8_t *buf, size_t buf_len);
|
||||
|
||||
/**
|
||||
* @brief Get interrupt mode
|
||||
*
|
||||
* @return Mode of interrupt
|
||||
*/
|
||||
uarths_interrupt_mode_t uarths_get_interrupt_mode(void);
|
||||
|
||||
/**
|
||||
* @brief Set uarths baud rate and stopbit
|
||||
*
|
||||
* @param[in] baud_rate The baud rate
|
||||
* @param[in] stopbit The stopbit of data
|
||||
*
|
||||
*/
|
||||
void uarths_config(uint32_t baud_rate, uarths_stopbit_t stopbit);
|
||||
|
||||
/**
|
||||
* @brief Set uart interrupt condition
|
||||
*
|
||||
* @param[in] interrupt_mode The interrupt mode
|
||||
* @param[in] cnt The count of tigger
|
||||
*
|
||||
*/
|
||||
void uarths_set_interrupt_cnt(uarths_interrupt_mode_t interrupt_mode, uint8_t cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_UARTHS_H */
|
||||
@@ -0,0 +1,54 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file utils.c
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "encoding.h"
|
||||
#include "utils.h"
|
||||
|
||||
void set_bit(volatile uint32_t *bits, uint32_t mask, uint32_t value)
|
||||
{
|
||||
uint32_t org = (*bits) & ~mask;
|
||||
*bits = org | (value & mask);
|
||||
}
|
||||
|
||||
void set_bit_offset(volatile uint32_t *bits, uint32_t mask, size_t offset, uint32_t value)
|
||||
{
|
||||
set_bit(bits, mask << offset, value << offset);
|
||||
}
|
||||
|
||||
void set_gpio_bit(volatile uint32_t *bits, size_t offset, uint32_t value)
|
||||
{
|
||||
set_bit_offset(bits, 1, offset, value);
|
||||
}
|
||||
|
||||
uint32_t get_bit(volatile uint32_t *bits, uint32_t mask, size_t offset)
|
||||
{
|
||||
return ((*bits) & (mask << offset)) >> offset;
|
||||
}
|
||||
|
||||
uint32_t get_gpio_bit(volatile uint32_t *bits, size_t offset)
|
||||
{
|
||||
return get_bit(bits, 1, offset);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file utils.h
|
||||
* @brief kendryte k210 source code
|
||||
* https://github.com/kendryte/kendryte-standalone-sdk.git
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
#ifndef _DRIVER_UTILS_H
|
||||
#define _DRIVER_UTILS_H
|
||||
#include "uarths.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstdbool>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#else /* __cplusplus */
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define KENDRYTE_MIN(a, b) ((a) > (b) ? (b) : (a))
|
||||
#define KENDRYTE_MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
#define KENDRYTE_CAST(type, ptr) ptr
|
||||
#else /* __ASSEMBLY__ */
|
||||
/**
|
||||
* @brief Cast the pointer to specified pointer type.
|
||||
*
|
||||
* @param[in] type The pointer type to cast to
|
||||
* @param[in] ptr The pointer to apply the type cast to
|
||||
*/
|
||||
#define KENDRYTE_CAST(type, ptr) ((type)(ptr))
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/**
|
||||
* @addtogroup UTIL_RW_FUNC Memory Read/Write Utilities
|
||||
*
|
||||
* This section implements read and write functionality for various
|
||||
* memory untis. The memory unit terms used for these functions are
|
||||
* consistent with those used in the ARM Architecture Reference Manual
|
||||
* ARMv7-A and ARMv7-R edition manual. The terms used for units of memory are:
|
||||
*
|
||||
* Unit of Memory | Abbreviation | Size in Bits
|
||||
* :---------------|:-------------|:------------:
|
||||
* Byte | byte | 8
|
||||
* Half Word | hword | 16
|
||||
* Word | word | 32
|
||||
* Double Word | dword | 64
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Write the 8 bit byte to the destination address in device memory.
|
||||
*
|
||||
* @param[in] dest Write destination pointer address
|
||||
* @param[in] src 8 bit data byte to write to memory
|
||||
*/
|
||||
#define kendryte_write_byte(dest, src) \
|
||||
(*KENDRYTE_CAST(volatile uint8_t*, (dest)) = (src))
|
||||
|
||||
/**
|
||||
* @brief Read and return the 8 bit byte from the source address in device memory.
|
||||
*
|
||||
* @param[in] src Read source pointer address
|
||||
*
|
||||
* @return 8 bit data byte value
|
||||
*/
|
||||
#define kendryte_read_byte(src) (*KENDRYTE_CAST(volatile uint8_t*, (src)))
|
||||
|
||||
/**
|
||||
* @brief Write the 16 bit half word to the destination address in device memory.
|
||||
*
|
||||
* @param[in] dest Write destination pointer address
|
||||
* @param[in] src 16 bit data half word to write to memory
|
||||
*/
|
||||
#define kendryte_write_hword(dest, src) \
|
||||
(*KENDRYTE_CAST(volatile uint16_t*, (dest)) = (src))
|
||||
|
||||
/**
|
||||
* @brief Read and return the 16 bit half word from the source address in device
|
||||
*
|
||||
* @param[in] src Read source pointer address
|
||||
*
|
||||
* @return 16 bit data half word value
|
||||
*/
|
||||
#define kendryte_read_hword(src) (*KENDRYTE_CAST(volatile uint16_t*, (src)))
|
||||
|
||||
/**
|
||||
* @brief Write the 32 bit word to the destination address in device memory.
|
||||
*
|
||||
* @param[in] dest Write destination pointer address
|
||||
* @param[in] src 32 bit data word to write to memory
|
||||
*/
|
||||
#define kendryte_write_word(dest, src) \
|
||||
(*KENDRYTE_CAST(volatile uint32_t*, (dest)) = (src))
|
||||
|
||||
/**
|
||||
* @brief Read and return the 32 bit word from the source address in device memory.
|
||||
*
|
||||
* @param[in] src Read source pointer address
|
||||
*
|
||||
* @return 32 bit data half word value
|
||||
*/
|
||||
#define kendryte_read_word(src) (*KENDRYTE_CAST(volatile uint32_t*, (src)))
|
||||
|
||||
/**
|
||||
* @brief Write the 64 bit double word to the destination address in device memory.
|
||||
*
|
||||
* @param[in] dest Write destination pointer address
|
||||
* @param[in] src 64 bit data word to write to memory
|
||||
*/
|
||||
#define kendryte_write_dword(dest, src) \
|
||||
(*KENDRYTE_CAST(volatile uint64_t*, (dest)) = (src))
|
||||
|
||||
/**
|
||||
* @brief Read and return the 64 bit double word from the source address in device
|
||||
*
|
||||
* @param[in] src Read source pointer address
|
||||
*
|
||||
* @return 64 bit data half word value
|
||||
*/
|
||||
#define kendryte_read_dword(src) (*KENDRYTE_CAST(volatile uint64_t*, (src)))
|
||||
|
||||
/**
|
||||
* @brief Set selected bits in the 8 bit byte at the destination address in device
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to set in destination byte
|
||||
*/
|
||||
#define kendryte_setbits_byte(dest, bits) \
|
||||
(kendryte_write_byte(dest, kendryte_read_byte(dest) | (bits)))
|
||||
|
||||
/**
|
||||
* @brief Clear selected bits in the 8 bit byte at the destination address in device
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to clear in destination byte
|
||||
*/
|
||||
#define kendryte_clrbits_byte(dest, bits) \
|
||||
(kendryte_write_byte(dest, kendryte_read_byte(dest) & ~(bits)))
|
||||
|
||||
/**
|
||||
* @brief Change or toggle selected bits in the 8 bit byte at the destination address
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to change in destination byte
|
||||
*/
|
||||
#define kendryte_xorbits_byte(dest, bits) \
|
||||
(kendryte_write_byte(dest, kendryte_read_byte(dest) ^ (bits)))
|
||||
|
||||
/**
|
||||
* @brief Replace selected bits in the 8 bit byte at the destination address in device
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] msk Bits to replace in destination byte
|
||||
* @param[in] src Source bits to write to cleared bits in destination byte
|
||||
*/
|
||||
#define kendryte_replbits_byte(dest, msk, src) \
|
||||
(kendryte_write_byte(dest, (kendryte_read_byte(dest) & ~(msk)) | ((src) & (msk))))
|
||||
|
||||
/**
|
||||
* @brief Set selected bits in the 16 bit halfword at the destination address in
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to set in destination halfword
|
||||
*/
|
||||
#define kendryte_setbits_hword(dest, bits) \
|
||||
(kendryte_write_hword(dest, kendryte_read_hword(dest) | (bits)))
|
||||
|
||||
/**
|
||||
* @brief Clear selected bits in the 16 bit halfword at the destination address in
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to clear in destination halfword
|
||||
*/
|
||||
#define kendryte_clrbits_hword(dest, bits) \
|
||||
(kendryte_write_hword(dest, kendryte_read_hword(dest) & ~(bits)))
|
||||
|
||||
/**
|
||||
* @brief Change or toggle selected bits in the 16 bit halfword at the destination
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to change in destination halfword
|
||||
*/
|
||||
#define kendryte_xorbits_hword(dest, bits) \
|
||||
(kendryte_write_hword(dest, kendryte_read_hword(dest) ^ (bits)))
|
||||
|
||||
/**
|
||||
* @brief Replace selected bits in the 16 bit halfword at the destination address in
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] msk Bits to replace in destination byte
|
||||
* @param[in] src Source bits to write to cleared bits in destination halfword
|
||||
*/
|
||||
#define kendryte_replbits_hword(dest, msk, src) \
|
||||
(kendryte_write_hword(dest, (kendryte_read_hword(dest) & ~(msk)) | ((src) & (msk))))
|
||||
|
||||
/**
|
||||
* @brief Set selected bits in the 32 bit word at the destination address in device
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to set in destination word
|
||||
*/
|
||||
#define kendryte_setbits_word(dest, bits) \
|
||||
(kendryte_write_word(dest, kendryte_read_word(dest) | (bits)))
|
||||
|
||||
/**
|
||||
* @brief Clear selected bits in the 32 bit word at the destination address in device
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to clear in destination word
|
||||
*/
|
||||
#define kendryte_clrbits_word(dest, bits) \
|
||||
(kendryte_write_word(dest, kendryte_read_word(dest) & ~(bits)))
|
||||
|
||||
/**
|
||||
* @brief Change or toggle selected bits in the 32 bit word at the destination address
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to change in destination word
|
||||
*/
|
||||
#define kendryte_xorbits_word(dest, bits) \
|
||||
(kendryte_write_word(dest, kendryte_read_word(dest) ^ (bits)))
|
||||
|
||||
/**
|
||||
* @brief Replace selected bits in the 32 bit word at the destination address in
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] msk Bits to replace in destination word
|
||||
* @param[in] src Source bits to write to cleared bits in destination word
|
||||
*/
|
||||
#define kendryte_replbits_word(dest, msk, src) \
|
||||
(kendryte_write_word(dest, (kendryte_read_word(dest) & ~(msk)) | ((src) & (msk))))
|
||||
|
||||
/**
|
||||
* @brief Set selected bits in the 64 bit doubleword at the destination address in
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to set in destination doubleword
|
||||
*/
|
||||
#define kendryte_setbits_dword(dest, bits) \
|
||||
(kendryte_write_dword(dest, kendryte_read_dword(dest) | (bits)))
|
||||
|
||||
/**
|
||||
* @brief Clear selected bits in the 64 bit doubleword at the destination address in
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to clear in destination doubleword
|
||||
*/
|
||||
#define kendryte_clrbits_dword(dest, bits) \
|
||||
(kendryte_write_dword(dest, kendryte_read_dword(dest) & ~(bits)))
|
||||
|
||||
/**
|
||||
* @brief Change or toggle selected bits in the 64 bit doubleword at the destination
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to change in destination doubleword
|
||||
*/
|
||||
#define kendryte_xorbits_dword(dest, bits) \
|
||||
(kendryte_write_dword(dest, kendryte_read_dword(dest) ^ (bits)))
|
||||
|
||||
/**
|
||||
* @brief Replace selected bits in the 64 bit doubleword at the destination address in
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] msk its to replace in destination doubleword
|
||||
* @param[in] src Source bits to write to cleared bits in destination word
|
||||
*/
|
||||
#define kendryte_replbits_dword(dest, msk, src) \
|
||||
(kendryte_write_dword(dest, (kendryte_read_dword(dest) & ~(msk)) | ((src) & (msk))))
|
||||
|
||||
/**
|
||||
* @brief Set value by mask
|
||||
*
|
||||
* @param[in] bits The one be set
|
||||
* @param[in] mask mask value
|
||||
* @param[in] value The value to set
|
||||
*/
|
||||
void set_bit(volatile uint32_t *bits, uint32_t mask, uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Set value by mask
|
||||
*
|
||||
* @param[in] bits The one be set
|
||||
* @param[in] mask Mask value
|
||||
* @param[in] offset Mask's offset
|
||||
* @param[in] value The value to set
|
||||
*/
|
||||
void set_bit_offset(volatile uint32_t *bits, uint32_t mask, size_t offset, uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Set bit for gpio, only set one bit
|
||||
*
|
||||
* @param[in] bits The one be set
|
||||
* @param[in] idx Offset value
|
||||
* @param[in] value The value to set
|
||||
*/
|
||||
void set_gpio_bit(volatile uint32_t *bits, size_t idx, uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Get bits value of mask
|
||||
*
|
||||
* @param[in] bits The source data
|
||||
* @param[in] mask Mask value
|
||||
* @param[in] offset Mask's offset
|
||||
*
|
||||
* @return The bits value of mask
|
||||
*/
|
||||
uint32_t get_bit(volatile uint32_t *bits, uint32_t mask, size_t offset);
|
||||
|
||||
/**
|
||||
* @brief Get a bit value by offset
|
||||
*
|
||||
* @param[in] bits The source data
|
||||
* @param[in] offset Bit's offset
|
||||
*
|
||||
*
|
||||
* @return The bit value
|
||||
*/
|
||||
uint32_t get_gpio_bit(volatile uint32_t *bits, size_t offset);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* _DRIVER_COMMON_H */
|
||||
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
/****************************************************************************
|
||||
* arch/riscv/src/rv32im/up_syscall.S
|
||||
*
|
||||
* Copyright (C) 2011, 2015 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Modified for RISC-V:
|
||||
*
|
||||
* Copyright (C) 2016 Ken Pettit. All rights reserved.
|
||||
* Author: Ken Pettit <pettitkd@gmail.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Symbols
|
||||
****************************************************************************/
|
||||
|
||||
.file "up_syscall0.S"
|
||||
.global sys_call0
|
||||
.global sys_call1
|
||||
.global sys_call2
|
||||
.global sys_call3
|
||||
.global sys_call4
|
||||
.global sys_call5
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_syscall0, up_syscall1, up_syscall2, up_syscall3
|
||||
*
|
||||
* Description:
|
||||
* up_syscall0 - System call SYS_ argument and no additional parameters.
|
||||
* up_syscall1 - System call SYS_ argument and one additional parameter.
|
||||
* up_syscall2 - System call SYS_ argument and two additional parameters.
|
||||
* up_syscall3 - System call SYS_ argument and three additional parameters.
|
||||
* up_syscall4 - System call SYS_ argument and four additional parameters.
|
||||
* up_syscall5 - System call SYS_ argument and five additional parameters.
|
||||
*
|
||||
* Assumption:
|
||||
* All interrupts are disabled except for the software interrupts.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.text
|
||||
|
||||
sys_call0: /* a0 holds the syscall number */
|
||||
sys_call1: /* a0 holds the syscall number, argument in a1 */
|
||||
sys_call2: /* a0 holds the syscall number, arguments in a1 and a2 */
|
||||
sys_call3: /* a0 holds the syscall number, arguments in a1, a2, and a3 */
|
||||
sys_call4: /* a0 holds the syscall number, arguments in a1, a2, a3 and a4 */
|
||||
sys_call5: /* a0 holds the syscall number, arguments in a1, a2, a3, a4 and a5 */
|
||||
|
||||
/* Issue the ECALL opcode to perform a SW interrupt to the OS */
|
||||
|
||||
ecall
|
||||
|
||||
/* The actual interrupt may not a occur for a few more cycles. Let's
|
||||
* put a few nop's here in hope that the SW interrupt occurs during
|
||||
* the sequence of nops.
|
||||
*/
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* Then return with the result of the software interrupt in v0 */
|
||||
|
||||
ret
|
||||
nop
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,980 @@
|
||||
Board-Specific Configurations
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This directory contains the board support logic for all boards supported
|
||||
by NuttX.
|
||||
|
||||
The nuttx/boards directory is a part of the internal OS. It should contain
|
||||
only OS bring-up logic and driver initialization logic. THERE SHOULD BE NO
|
||||
APPLICATION CALLABLE LOGIC IN THIS DIRECTORY.
|
||||
|
||||
If you have board-specific, application callable logic, that logic should not
|
||||
go here. Please consider using a sub-directory under apps/platform instead.
|
||||
|
||||
Table of Contents
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
o Board-Specific Configurations
|
||||
o Summary of Files
|
||||
o Configuration Variables
|
||||
o Supported Boards
|
||||
o Configuring NuttX
|
||||
o Building Symbol Tables
|
||||
|
||||
Board-Specific Configurations
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The NuttX configuration consists of:
|
||||
|
||||
o Processor architecture specific files. These are the files contained
|
||||
in the arch/<arch>/ directory.
|
||||
|
||||
o Chip/SoC specific files. Each processor architecture is embedded
|
||||
in a chip or System-on-a-Chip (SoC) architecture. The full chip
|
||||
architecture includes the processor architecture plus chip-specific
|
||||
interrupt logic, general purpose I/O (GIO) logic, and specialized,
|
||||
internal peripherals (such as UARTs, USB, etc.).
|
||||
|
||||
These chip-specific files are contained within chip-specific
|
||||
sub-directories in the arch/<arch>/ directory and are selected
|
||||
via the CONFIG_ARCH_name selection
|
||||
|
||||
o Board specific files. In order to be usable, the chip must be
|
||||
contained in a board environment. The board configuration defines
|
||||
additional properties of the board including such things as
|
||||
peripheral LEDs, external peripherals (such as network, USB, etc.).
|
||||
|
||||
These board-specific configuration files can be found in the
|
||||
boards/<arch>/<chip>/<board>/ sub-directories and are
|
||||
discussed in this README. Additional configuration information may be
|
||||
available in board-specific README files at
|
||||
boards/<arch>/<chip>/<board>/README.txt files.
|
||||
|
||||
The boards/ subdirectory contains configuration data for each board. These
|
||||
board-specific configurations plus the architecture-specific configurations in
|
||||
the arch/ subdirectory completely define a customized port of NuttX.
|
||||
|
||||
Directory Structure
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The boards/ directory contains board specific configuration logic. Each
|
||||
board must provide a subdirectory <board> under boards/ with the
|
||||
following characteristics:
|
||||
|
||||
|
||||
<board>
|
||||
|-- README.txt
|
||||
|-- include/
|
||||
| `-- (board-specific header files)
|
||||
|-- src/
|
||||
| |-- Makefile
|
||||
| `-- (board-specific source files)
|
||||
|-- <config1-dir>
|
||||
| |-- Make.defs
|
||||
| `-- defconfig
|
||||
|-- <config2-dir>
|
||||
| |-- Make.defs
|
||||
| `-- defconfig
|
||||
...
|
||||
|
||||
Summary of Files
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
README.txt -- This text file provides additional information unique to
|
||||
each board configuration sub-directory.
|
||||
|
||||
include/ -- This directory contains board specific header files. This
|
||||
directory will be linked as include/arch/board at configuration time and
|
||||
can be included via '#include <arch/board/header.h>'. These header file
|
||||
can only be included by files in arch/<arch>include/ and
|
||||
arch/<arch>/src
|
||||
|
||||
src/ -- This directory contains board specific drivers. This
|
||||
directory will be linked as arch/<arch>/src/board at configuration
|
||||
time and will be integrated into the build system.
|
||||
|
||||
src/Makefile -- This makefile will be invoked to build the board specific
|
||||
drivers. It must support the following targets: libext$(LIBEXT), clean,
|
||||
and distclean.
|
||||
|
||||
A board may have various different configurations using these common source
|
||||
files. Each board configuration is described by two files: Make.defs and
|
||||
defconfig. Typically, each set of configuration files is retained in a
|
||||
separate configuration sub-directory (<config1-dir>, <config2-dir>, .. in
|
||||
the above diagram).
|
||||
|
||||
Make.defs -- This makefile fragment provides architecture and
|
||||
tool-specific build options. It will be included by all other
|
||||
makefiles in the build (once it is installed). This make fragment
|
||||
should define:
|
||||
|
||||
Tools: CC, LD, AR, NM, OBJCOPY, OBJDUMP
|
||||
Tool options: CFLAGS, LDFLAGS
|
||||
|
||||
When this makefile fragment runs, it will be passed TOPDIR which
|
||||
is the path to the root directory of the build. This makefile
|
||||
fragment should include:
|
||||
|
||||
$(TOPDIR)/.config : NuttX configuration
|
||||
$(TOPDIR)/tools/Config.mk : Common definitions
|
||||
|
||||
Definitions in the Make.defs file probably depend on some of the
|
||||
settings in the .config file. For example, the CFLAGS will most likely be
|
||||
different if CONFIG_DEBUG_FEATURES=y.
|
||||
|
||||
The included tools/Config.mk file contains additional definitions that may
|
||||
be overridden in the architecture-specific Make.defs file as necessary:
|
||||
|
||||
COMPILE, ASSEMBLE, ARCHIVE, CLEAN, and MKDEP macros
|
||||
|
||||
defconfig -- This is a configuration file similar to the Linux
|
||||
configuration file. In contains variable/value pairs like:
|
||||
|
||||
CONFIG_VARIABLE=value
|
||||
|
||||
This configuration file will be used at build time:
|
||||
|
||||
(1) as a makefile fragment included in other makefiles, and
|
||||
(2) to generate include/nuttx/config.h which is included by
|
||||
most C files in the system.
|
||||
|
||||
Configuration Variables
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
At one time, this section provided a list of all NuttX configuration
|
||||
variables. However, NuttX has since converted to use the kconfig-frontends
|
||||
tools (See https://bitbucket.org/nuttx/tools/src/master/kconfig-frontends/.)
|
||||
Now, the NuttX configuration is determined by a self-documenting set of
|
||||
Kconfig files.
|
||||
|
||||
The current NuttX configuration variables are also documented in separate,
|
||||
auto-generated configuration variable document. That configuration variable
|
||||
document is generated using the kconfig2html tool that can be found in the
|
||||
nuttx/tools directory. That tool analyzes the NuttX Kconfig files and
|
||||
generates an excruciatingly boring HTML document.
|
||||
|
||||
The latest boring configuration variable documentation can be regenerated at
|
||||
any time using that tool or, more appropriately, the wrapper script at
|
||||
nuttx/tools/mkconfigvars.sh. That script will generate the file
|
||||
nuttx/Documentation/NuttXConfigVariables.html.
|
||||
|
||||
Supported Boards
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
boards/avr/atmega/amber
|
||||
This is placeholder for the SoC Robotics Amber Web Server that is based
|
||||
on the Atmel AVR ATMega128 MCU. There is not much there yet and what is
|
||||
there is untested due to tool-related issues.
|
||||
|
||||
boards/arm/sam34/arduino-due
|
||||
This sub-directory holds board support for the Arduino DUE board featuring
|
||||
the Atmel ATSAM3X8E MCU running at 84 MHz.
|
||||
|
||||
boards/avr/at32uc3/avr32dev1
|
||||
This is a port of NuttX to the Atmel AVR32DEV1 board. That board is
|
||||
based on the Atmel AT32UC3B0256 MCU and uses a specially patched
|
||||
version of the GNU toolchain: The patches provide support for the
|
||||
AVR32 family. That patched GNU toolchain is available only from the
|
||||
Atmel website. STATUS: This port is functional but very basic. There
|
||||
are configurations for NSH and the OS test.
|
||||
|
||||
boards/arm/stm32/axoloti
|
||||
Support for the Axoloti synthesizer board based on the STMicro
|
||||
STM32F427IGH6 MCU. See: http://www.axoloti.com/
|
||||
|
||||
boards/arm/stm32/b-g474e-dpow1
|
||||
Initial support for booting NuttX to a functional NSH prompt on the
|
||||
STMicro B-G474E-DPOW1 Discovery kit with STM32G474RE MCU.
|
||||
|
||||
boards/arm/stm32/nucleo-g431kb
|
||||
STMicro Nucleo G431KB board based on the STMicro STM32G431KB MCU.
|
||||
|
||||
boards/arm/stm32/nucleo-g431rb
|
||||
STMicro Nucleo G431RB board based on the STMicro STM32G431RB MCU.
|
||||
|
||||
boards/arm/stm32f0l0g0/b-l072z-lrwan1
|
||||
STMicro STM32L0 Discovery kit with LoRa/SigFox based on STM32L072CZ MCU.
|
||||
|
||||
boards/arm/lpc43xx/bambino-200e
|
||||
Micromint Bambino board. This board is based on the LPC4330FBD144.
|
||||
|
||||
boards/arm/c5471/c5471evm
|
||||
This is a port to the Spectrum Digital C5471 evaluation board. The
|
||||
TMS320C5471 is a dual core processor from TI with an ARM7TDMI general
|
||||
purpose processor and a c54 DSP. It is also known as TMS320DA180 or just DA180.
|
||||
NuttX runs on the ARM core and is built with a GNU arm-nuttx-elf toolchain*.
|
||||
This port is complete and verified.
|
||||
|
||||
boards/arm/tiva/launchxl_cc1310
|
||||
Port to the TI SimpleLink CC1310 LaunchPad Evaluation Kit (LAUNCHXL-CC1310)
|
||||
featuring the SimpleLinkCC1310 chip. This board features the CC1310F128
|
||||
part with 128Kb of FLASH and 20Kb of SRAM.
|
||||
|
||||
boards/arm/tiva/launchxl_cc1312r1
|
||||
Port to the TI SimpleLink CC1312R1 LaunchPad Evaluation Kit (LAUNCHXL-CC1312R1)
|
||||
featuring the SimpleLinkCC1312R1 chip.
|
||||
|
||||
boards/arm/stm32/clicker2-stm32
|
||||
Mikroe Clicker2 STM32 board based on the STMicro STM32F407VGT6 MCU.
|
||||
|
||||
boards/arm/stm32/cloudctrl
|
||||
Darcy's CloudController board. This is a small network relay development
|
||||
board. Based on the Shenzhou IV development board design. It is based on
|
||||
the STM32F107VC MCU.
|
||||
|
||||
boards/hc/m9s12/demo9s12ne64
|
||||
NXP/FreeScale DMO9S12NE64 board based on the MC9S12NE64 hcs12 cpu. This
|
||||
port uses the m9s12x GCC toolchain. STATUS: (Still) under development; it
|
||||
is code complete but has not yet been verified.
|
||||
|
||||
boards/arm/tiva/dk-tm4c129x
|
||||
This is the port of NuttX to the Tiva DK-TM4C129x Connected Development Kit. The
|
||||
Tiva DK-TM4C129x features the TM4C129XNCZAD MCU.
|
||||
|
||||
boards/arm/lpc31xx/ea3131
|
||||
Embedded Artists EA3131 Development board. This board is based on the
|
||||
an NXP LPC3131 MCU. This OS is built with the arm-nuttx-elf toolchain*.
|
||||
STATUS: This port is complete and mature.
|
||||
|
||||
boards/arm/lpc31xx/ea3152
|
||||
Embedded Artists EA3152 Development board. This board is based on the
|
||||
an NXP LPC3152 MCU. This OS is built with the arm-nuttx-elf toolchain*.
|
||||
STATUS: This port is has not be exercised well, but since it is
|
||||
a simple derivative of the ea3131, it should be fully functional.
|
||||
|
||||
boards/arm/tiva/eagle100
|
||||
Micromint Eagle-100 Development board. This board is based on the
|
||||
an ARM Cortex-M3 MCU, the Luminary LM3S6918. This OS is built with the
|
||||
arm-nuttx-elf toolchain*. STATUS: This port is complete and mature.
|
||||
|
||||
boards/arm/efm32/efm32-g8xx-stk
|
||||
The port of NuttX to the EFM32 Gecko Starter Kit (EFM32-G8XX-STK).
|
||||
|
||||
boards/arm/efm32/efm32gg-stk3700
|
||||
The port of NuttX to the EFM32 Giant Gecko Starter Kit
|
||||
(EFM32GG-STK3700).
|
||||
|
||||
boards/arm/tiva/ekk-lm3s9b96
|
||||
TI/Stellaris EKK-LM3S9B96 board. This board is based on the
|
||||
an EKK-LM3S9B96 which is a Cortex-M3.
|
||||
|
||||
boards/arm/stm32/emw3162
|
||||
A configuration for the EMW3162 Wi-Fi board
|
||||
(https://www.waveshare.com/wiki/EMW3162). This board features
|
||||
the STM32F205RGY6 MCU from STMicro.
|
||||
|
||||
boards/xtensa/esp32/esp-core
|
||||
The ESP32 is a dual-core system from Espressif with two Harvard architecture
|
||||
Xtensa LX6 CPUs. All embedded memory, external memory and peripherals are
|
||||
located on the data bus and/or the instruction bus of bus of these CPUs.
|
||||
With some minor exceptions, the address mapping of two CPUs is symmetric,
|
||||
meaning they use the same addresses to access the same memory.
|
||||
|
||||
boards/z80/ez80/ez80f0910200kitg
|
||||
ez80Acclaim! Microcontroller. This port use the Zilog ez80f0910200kitg
|
||||
development kit, eZ80F091 part, and the Zilog ZDS-II Windows command line
|
||||
tools. The development environment is Cygwin under WinXP.
|
||||
|
||||
boards/z80/ez80/ez80f0910200zco
|
||||
ez80Acclaim! Microcontroller. This port use the Zilog ez80f0910200zco
|
||||
development kit, eZ80F091 part, and the Zilog ZDS-II Windows command line
|
||||
tools. The development environment is Cygwin under WinXP.
|
||||
|
||||
boards/arm/stm32/fire-stm32v2
|
||||
A configuration for the M3 Wildfire STM32 board. This board is based on the
|
||||
STM32F103VET6 chip. See http://firestm32.taobao.com . Version 2 and 3 of
|
||||
the boards are supported but only version 2 has been tested.
|
||||
|
||||
boards/mips/pic32mz/flipnclick-pic32mz
|
||||
Board support for the Mikroe Flip&Click PIC32MZ board. This board is a
|
||||
chipKit Arduino-compatible board (but can also be used with the Mikroe
|
||||
bootloader). It has with four Mikroe Click bus interfaces in addition to
|
||||
standard Arduino connectors. This board features the Microchip
|
||||
PIC32MZ2048EFH100 MCU running at 200 MHz (252 MHz capable).
|
||||
|
||||
boards/mips/pic32mz/chipkit-wifire
|
||||
Board support for the chipKIT Wi-FIRE board. This board is a chipKIT
|
||||
Arduino-compatible board. This board features
|
||||
the Microchip PIC32MZ2048EFG100 MCU running at 200 MHz.
|
||||
|
||||
boards/arm/sam34/flipnclick-sam3x
|
||||
Board support for the Mikroe Flip&Click STM32X board. This board is an
|
||||
Arduino-Due work-alike with four Mikroe Click bus interfaces. Like the
|
||||
Arduino DUE, this board features the Atmel ATSAM3X8E MCU running at 84
|
||||
MHz.
|
||||
|
||||
boards/arm/kinetis/freedom-k28f
|
||||
This port uses the NXP/FreeScale FREEDOM-K28F development board. This
|
||||
board uses the Kinetis K28F MK28FN2M0VMI15 Cortex-M4 MCU.
|
||||
|
||||
boards/arm/kinetis/freedom-k64f
|
||||
This port uses the NXP/FreeScale FREEDOM-K64F development board. This board
|
||||
uses the Kinetis K64 MK64FN1M0VLL12 Cortex-M4 MCU.
|
||||
|
||||
boards/arm/kl/freedom-kl25z
|
||||
boards/arm/kl/freedom-kl26z
|
||||
These configurations are for the NXP/FreeScale Freedom KL25Z and very similar
|
||||
KL26Z board. The Freedom-KL25Z features the K25Z120LE3AN chip; the
|
||||
Freedom-KL26Z has the K26Z128VLH4 chip. These are separate configurations
|
||||
because of minor differences in the on-board logic. Both include a
|
||||
built-in SDA debugger.
|
||||
|
||||
boards/arm/stm32/hymini-stm32v
|
||||
A configuration for the HY-Mini STM32v board. This board is based on the
|
||||
STM32F103VCT chip.
|
||||
|
||||
boards/arm/kinetis/kwikstik-k40.
|
||||
Kinetis K40 Cortex-M4 MCU. This port uses the NXP/FreeScale KwikStik-K40
|
||||
development board.
|
||||
|
||||
boards/arm/tms570/launchxl-tms57004
|
||||
TI Hercules TMS570LS04x/03x LaunchPad Evaluation Kit (LAUNCHXL-TMS57004)
|
||||
featuring the Hercules TMS570LS0432PZ chip.
|
||||
|
||||
boards/arm/lpc17xx_40xx/lincoln60
|
||||
NuttX port to the Micromint Lincoln 60 board.
|
||||
|
||||
boards/arm/tiva/lm3s6432-s2e
|
||||
Stellaris RDK-S2E Reference Design Kit and the MDL-S2E Ethernet to
|
||||
Serial module.
|
||||
|
||||
boards/arm/tiva/lm3s6965-ek
|
||||
Stellaris LM3S6965 Evaluation Kit. This board is based on the
|
||||
an ARM Cortex-M3 MCU, the Luminary/TI LM3S6965. This OS is built with the
|
||||
arm-nuttx-elf toolchain*. STATUS: This port is complete and mature.
|
||||
|
||||
boards/arm/tiva/lm3s8962-ek
|
||||
Stellaris LMS38962 Evaluation Kit.
|
||||
|
||||
boards/arm/tiva/lm4f120-launchpad
|
||||
This is the port of NuttX to the Stellaris LM4F120 LaunchPad. The
|
||||
Stellaris LM4F120 LaunchPad Evaluation Board is a low-cost evaluation
|
||||
platform for ARM Cortex-M4F-based microcontrollers from Texas
|
||||
Instruments.
|
||||
|
||||
boards/arm/lpc17xx_40xx/lpcxpresso-lpc1768
|
||||
Embedded Artists base board with NXP LPCExpresso LPC1768. This board
|
||||
is based on the NXP LPC1768. The Code Red toolchain is used by default.
|
||||
STATUS: Under development.
|
||||
|
||||
boards/arm/lpc54xx/lpcxpresso-lpc54628
|
||||
NXP LPCExpresso LPC54628. This board is based on the NXP LPC54628.
|
||||
|
||||
boards/arm/lpc43xx/lpc4330-xplorer
|
||||
NuttX port to the LPC4330-Xplorer board from NGX Technologies featuring
|
||||
the NXP LPC4330FET100 MCU
|
||||
|
||||
boards/arm/lpc43xx/lpc4337-ws
|
||||
NuttX port to the WaveShare LPC4337-ws board featuring the NXP LPC4337JBD144
|
||||
MCU.
|
||||
|
||||
boards/arm/lpc43xx/lpc4357-evb
|
||||
NuttX port to the LPC4357-EVB board from Embest featuring the NXP
|
||||
LPC4357FET256 MCU. Based on the LPC4300 Xplorer port and provided by
|
||||
Toby Duckworth.
|
||||
|
||||
boards/arm/lpc43xx/lpc4370-link2
|
||||
NuttX port to the NXP LPC4370-Link2 development board featuring the NXP
|
||||
LPC4370FET100 MCU. Based on the LPC4300 Xplorer port and provided by
|
||||
Lok Tep.
|
||||
|
||||
boards/arm/lpc17xx_40xx/lx_cpu
|
||||
This port uses the PiKRON LX_CPU board. See the
|
||||
http://pikron.com/pages/products/cpu_boards/lx_cpu.html for further
|
||||
information. This board features the NXP LPC4088 (compatible with
|
||||
LPC1788) and Xilinx Spartan 6 XC6SLX9
|
||||
|
||||
boards/z80/ez80/makerlisp
|
||||
This port use the MakerLisp machine based on an eZ80F091 ez80Acclaim!
|
||||
Microcontroller, and the Zilog ZDS-II Windows command line tools. The
|
||||
development environment is Cygwin under Windows. A Windows native
|
||||
development environment is available but has not been verified.
|
||||
|
||||
boards/arm/stm32/maple
|
||||
NuttX support for the LeafLab's Maple and Maple Mini boards. These boards
|
||||
are based on the STM32F103RBT6 chip for the standard version and on the
|
||||
STM32F103CBT6 for the mini version (See http://leaflabs.com/docs/hardware/maple.html)
|
||||
|
||||
boards/arm/max326xx/max32660-evsys
|
||||
The configurations in this directory support the Maxim Integrated
|
||||
MAX32660-EVSYS board.
|
||||
|
||||
boards/arm/lpc17xx_40xx/mbed
|
||||
The configurations in this directory support the mbed board (http://mbed.org)
|
||||
that features the NXP LPC1768 microcontroller. This OS is also built
|
||||
with the arm-nuttx-elf toolchain*. STATUS: Contributed.
|
||||
|
||||
boards/arm/lpc17xx_40xx/mcb1700
|
||||
Board support for the Keil MCB1700
|
||||
|
||||
boards/arm/samd5e5/metro-m4
|
||||
Th configurations in this directory are part of the port of NuttX to the
|
||||
Adafruit Metro M4. The Metro M4 uses a Arduino form factor and and pinout.
|
||||
It's powered with an ATSAMD51J19
|
||||
|
||||
boards/arm/stm32/mikroe-stm32f4
|
||||
This is the port of NuttX to the MikroElektronika Mikromedia for STM32F4
|
||||
development board. Contributed by Ken Petit.
|
||||
|
||||
boards/misoc/lm32/misoc
|
||||
This directory holds the port to NuttX running on a Qemu LM32 system.
|
||||
You can find the Qemu setup at https://bitbucket.org/key2/qemu
|
||||
|
||||
boards/arm/lpc214x/mcu123-lpc214x
|
||||
This port is for the NXP LPC2148 as provided on the mcu123.com
|
||||
lpc214x development board. This OS is also built with the arm-nuttx-elf
|
||||
toolchain*. The port supports serial, timer0, spi, and usb.
|
||||
|
||||
boards/avr/at90usb/micropendous3
|
||||
This is a port to the Opendous Micropendous 3 board. This board may
|
||||
be populated with either an AVR AT90USB646, 647, 1286, or 1287 MCU.
|
||||
Support is configured for the AT90USB647.
|
||||
|
||||
boards/mips/pic32mx/mirtoo
|
||||
This is the port to the DTX1-4000L "Mirtoo" module. This module uses MicroChip
|
||||
PIC32MX250F128D. See http://www.dimitech.com/ for further information.
|
||||
|
||||
boards/avr/atmega/moteino-mega
|
||||
This is placeholder for the LowPowerLab MoteinoMEGA that is based
|
||||
on the Atmel AVR ATMega1284P MCU. There is not much there yet and what is
|
||||
there is untested due to tool-related issues.
|
||||
|
||||
boards/arm/moxart/moxa
|
||||
Moxa NP51x0 series of 2-port advanced RS-232/422/485 serial device servers.
|
||||
|
||||
boards/hc/mcs92s12ne6/ne64badge
|
||||
Future Electronics Group NE64 /PoE Badge board based on the
|
||||
MC9S12NE64 hcs12 cpu. This port uses the m9s12x GCC toolchain.
|
||||
STATUS: Under development. The port is code-complete but has
|
||||
not yet been fully tested.
|
||||
|
||||
boards/arm/nrf52/nrf52-feather
|
||||
NuttX port to the Adafruit nRF52832 Feather board
|
||||
|
||||
boards/arm/nrf52/nrf52832-dk
|
||||
NuttX port to the Nordic nRF52832 Development Kit (PCA10040)
|
||||
|
||||
boards/arm/nrf52/nrf52840-dk
|
||||
NuttX port to the Nordic nRF52840 Development Kit (PCA10056)
|
||||
|
||||
boards/arm/nrf52/nrf52840-dongle
|
||||
NuttX port to the Nordic nRF52840 Dongle (PCA10059)
|
||||
|
||||
boards/arm/dm320/ntosd-dm320
|
||||
This port uses the Neuros OSD v1.0 Dev Board with a GNU arm-nuttx-elf
|
||||
toolchain*: see
|
||||
|
||||
http://wiki.neurostechnology.com/index.php/OSD_1.0_Developer_Home
|
||||
|
||||
There are some differences between the Dev Board and the currently
|
||||
available commercial v1.0 Boards. See
|
||||
|
||||
http://wiki.neurostechnology.com/index.php/OSD_Developer_Board_v1
|
||||
|
||||
NuttX operates on the ARM9EJS of this dual core processor.
|
||||
STATUS: This port is code complete, verified, and included in the
|
||||
NuttX 0.2.1 release.
|
||||
|
||||
boards/arm/stm32f7/nucleo-144
|
||||
STMicro Nucleo-144 development board family. Included support for (1) the
|
||||
Nucleo-F767ZG board featuring the STM32F746ZGT6U MCU. The STM32F746ZGT6U
|
||||
is a 216MHz Cortex-M7 operation with 1024Kb Flash memory and 320Kb SRAM.
|
||||
And (2) the Nucleo-F746ZG board featuring the STM32F767ZIT6 MCU. The
|
||||
STM32F767ZIT6 is a 216MHz Cortex-M7 operation with 2048Kb Flash memory
|
||||
and 512Kb SRAM.
|
||||
|
||||
boards/arm/stm32f0l0g0/nucleo-f072rb
|
||||
STMicro Nucleo F072RB board based on the STMicro STM32F072RBT6 MCU.
|
||||
|
||||
boards/arm/stm32/nucleo-f4x1re
|
||||
STMicro ST Nucleo F401RE and F411RE boards. See
|
||||
http://mbed.org/platforms/ST-Nucleo-F401RE and
|
||||
http://developer.mbed.org/platforms/ST-Nucleo-F411RE for more
|
||||
information about these boards.
|
||||
|
||||
boards/arm/stm32/nucleo-f410rb
|
||||
NuttX configuration for the STMicro NucleoF410RB board from ST Micro.
|
||||
This board features the STM32F410RB 100MHz Cortex-M4 with 128 KB Flash
|
||||
and 32 KB SRAM.
|
||||
|
||||
boards/arm/stm32/nucleo-f303re
|
||||
STMicro ST Nucleo F303RE board. Contributed by Paul Alexander Patience.
|
||||
|
||||
boards/arm/stm32f0l0g0/nucleo-l073rz
|
||||
STMicro STM32L0 Discovery kit with LoRa/SigFox based on STM32L072CZ MCU.
|
||||
|
||||
boards/arm/nuc1xx/nutiny-nuc120
|
||||
This is the port of NuttX to the NuvoTon NuTiny-SDK-NUC120 board. This
|
||||
board has the NUC120LE3AN chip with a built-in NuLink debugger.
|
||||
|
||||
boards/arm/efm32/olimex-efm32g880f128-stk
|
||||
This is the port of NuttX to the Olimex EFM32G880F128-STK development
|
||||
board.
|
||||
|
||||
boards/arm/lpc17xx_40xx/olimex-lpc1766stk
|
||||
This port uses the Olimex LPC1766-STK board and a GNU GCC toolchain* under
|
||||
Linux or Cygwin. STATUS: Complete and mature.
|
||||
|
||||
boards/arm/lpc2378/olimex-lpc2378
|
||||
This port uses the Olimex-lpc2378 board and a GNU arm-nuttx-elf toolchain* under
|
||||
Linux or Cygwin. STATUS: ostest and NSH configurations available.
|
||||
This port for the NXP LPC2378 was contributed by Rommel Marcelo.
|
||||
|
||||
boards/arm/stm32/olimex-stm32-h405
|
||||
This port uses the Olimex STM32 H405 board and a GNU arm-nuttx-elf
|
||||
toolchain* under Linux or Cygwin. See the http://www.olimex.com for
|
||||
further information. This board features the STMicro STM32F405RGT6 MCU.
|
||||
Contributed by Martin Lederhilger.
|
||||
|
||||
boards/arm/stm32/olimex-stm32-h407
|
||||
This port uses the Olimex STM32 H407 board and a GNU arm-nuttx-elf
|
||||
toolchain* under Linux or Cygwin. See the http://www.olimex.com for
|
||||
further information. This board features the STMicro STM32F407ZGT6 (144
|
||||
pins). Contributed by Neil Hancock.
|
||||
|
||||
boards/arm/stm32/olimex-stm32-e407
|
||||
Olimex STM32 E407 board based on the STMicro STM32F407ZGT6 (144pins).
|
||||
Contributed by Mateusz Szafoni.
|
||||
|
||||
boards/arm/stm32/olimex-stm32-p107
|
||||
This port uses the Olimex STM32-P107 board (STM32F107VC) and a GNU arm-nuttx-elf
|
||||
toolchain* under Linux or Cygwin. See the https://www.olimex.com/dev/stm32-p107.html
|
||||
for further information. Contributed by Max Holtzberg.
|
||||
|
||||
boards/arm/stm32/olimex-stm32-p207
|
||||
This port uses the Olimex STM32-P207 board (STM32F207ZE) and a GNU arm-nuttx-elf
|
||||
toolchain under Linux or Cygwin. See the https://www.olimex.com/dev/stm32-p207.html
|
||||
for further information. Contributed by Martin Lederhilger.
|
||||
|
||||
boards/arm/stm32/olimex-stm32-p407
|
||||
This port uses the Olimex STM32-P407 board (STM32F407ZG) and a GNU arm-nuttx-elf
|
||||
toolchain under Linux or Cygwin. See the https://www.olimex.com/dev/stm32-p407.html
|
||||
for further information.
|
||||
|
||||
boards/arm/stm32/olimexino-stm32
|
||||
This port uses the Olimexino STM32 board (STM32F103RBT6) and a GNU arm-nuttx-elf
|
||||
toolchain* under Linux or Cygwin. See the http://www.olimex.com for further\
|
||||
information. Contributed by David Sidrane.
|
||||
|
||||
boards/arm/str71x/olimex-strp711
|
||||
This port uses the Olimex STR-P711 board and a GNU arm-nuttx-elf toolchain* under
|
||||
Linux or Cygwin. See the http://www.olimex.com/dev/str-p711.html" for
|
||||
further information. STATUS: Configurations for the basic OS test and NSH
|
||||
are complete and verified.
|
||||
|
||||
boards/arm/stm32/omnibusf4
|
||||
Flight controllers compatible with the OMINBUSF4 Betaflight target
|
||||
|
||||
boards/or1k/mor1kx/or1k
|
||||
Generic OpenRISC board.
|
||||
|
||||
boards/arm/a1x/pcduino-a10
|
||||
This directory contains the port of NuttX to the pcDuino v1 board
|
||||
See http://www.pcduino.com/ for information about pcDuino Lite, v1,
|
||||
and v2. These boards are based around the Allwinner A10 Cortex-A8 CPU.
|
||||
I have not compared these boards in detail, but I believe that the
|
||||
differences are cosmetic. This port was developed on the v1 board, but
|
||||
the others may be compatible.
|
||||
|
||||
boards/z80/z180/p112
|
||||
The P112 is notable because it was the first of the hobbyist single board
|
||||
computers to reach the production stage. The P112 hobbyist computers
|
||||
were relatively widespread and inspired other hobbyist centered home brew
|
||||
computing projects such as N8VEM home brew computing project. The P112
|
||||
project still maintains many devoted enthusiasts and has an online
|
||||
repository of software and other information.
|
||||
|
||||
The P112 computer originated as a commercial product of "D-X Designs Pty
|
||||
Ltd" of Australia. They describe the computer as "The P112 is a stand-alone
|
||||
8-bit CPU board. Typically running CP/M (tm) or a similar operating system,
|
||||
it provides a Z80182 (Z-80 upgrade) CPU with up to 1MB of memory, serial,
|
||||
parallel and diskette IO, and realtime clock, in a 3.5-inch drive form factor.
|
||||
Powered solely from 5V, it draws 150mA (nominal: not including disk drives)
|
||||
with a 16MHz CPU clock. Clock speeds up to 24.576MHz are possible."
|
||||
|
||||
The P112 board was last available new in 1996 by Dave Brooks. In late 2004
|
||||
on the Usenet Newsgroup comp.os.cpm, talk about making another run of P112
|
||||
boards was discussed. David Griffith decided to produce additional P112 kits
|
||||
with Dave Brooks blessing and the assistance of others. In addition Terry
|
||||
Gulczynski makes additional P112 derivative hobbyist home brew computers.
|
||||
Hal Bower was very active in the mid 1990's on the P112 project and ported
|
||||
the "Banked/Portable BIOS".
|
||||
|
||||
Dave Brooks was successfully funded through Kickstarter for and another
|
||||
run of P112 boards in November of 2012.
|
||||
|
||||
boards/arm/stm32/photon
|
||||
A configuration for the Photon Wifi board from Particle Devices
|
||||
(https://www.particle.io). This board features the STM32F205RGY6 MCU from
|
||||
STMicro.
|
||||
|
||||
boards/mips/pic32mx/pic32mx-starterkit
|
||||
This directory contains the port of NuttX to the Microchip PIC32 Ethernet
|
||||
Starter Kit (DM320004) with the Multimedia Expansion Board (MEB, DM320005).
|
||||
See www.microchip.com for further information.
|
||||
|
||||
boards/mips/pic32mx/pic32mx7mmb
|
||||
This directory will (eventually) contain the port of NuttX to the
|
||||
Mikroelektronika PIC32MX7 Multimedia Board (MMB). See
|
||||
http://www.mikroe.com/ for further information.
|
||||
|
||||
boards/mips/pic32mz/pic32mz-starterkit
|
||||
This directory contains the port of NuttX to the Microchip PIC32MZ
|
||||
Embedded Connectivity (EC) Starter Kit. There are two configurations of
|
||||
the starter kit:
|
||||
|
||||
1) The PIC32MZ Embedded Connectivity Starter Kit based on the
|
||||
PIC32MZ2048ECH144-I/PH chip (DM320006), and
|
||||
2) The PIC32MZ Embedded Connectivity Starter Kit based on the
|
||||
PIC32MZ2048ECM144-I/PH w/Crypto Engine (DM320006-C)
|
||||
|
||||
See www.microchip.com for further information.
|
||||
|
||||
boards/arm/lpc17xx_40xx/pnev5180b
|
||||
NXP Semiconductors' PN5180 NFC Frontend Development Kit. This board is
|
||||
based on the NXP LPC1769 MCU.
|
||||
|
||||
boards/x86/qemu/qemu-i486
|
||||
Port of NuttX to QEMU in i486 mode. This port will also run on real i486
|
||||
hardware (Google the Bifferboard).
|
||||
|
||||
boards/arm/s32k1xx/s32k118evb
|
||||
This directory holds the port of NuttX to the NXP S32K118EVB board
|
||||
featuring the S32K118 Cortex-M0+.
|
||||
|
||||
boards/arm/s32k1xx/s32k146evb
|
||||
This directory holds the port of NuttX to the NXP S32K146EVB board
|
||||
featuring the S32K146 Cortex-M4F.
|
||||
|
||||
boards/arm/s32k1xx/s32k148evb
|
||||
This directory holds the port of NuttX to the NXP S32K148EVB board
|
||||
featuring the S32K148 Cortex-M4F.
|
||||
|
||||
boards/arm/imx6/sabre-6quad
|
||||
This directory holds a port of NuttX to the NXP/Freescale Sabre board
|
||||
featuring the iMX 6Quad CPU.
|
||||
|
||||
boards/arm/sama5/sama5d2-xult
|
||||
This is the port of NuttX to the Microchip SAMA5D2-Xplained Ultra development
|
||||
board. This board features the Microchip SAMA5D27. See
|
||||
https://www.microchip.com/Developmenttools/ProductDetails/ATSAMA5D2C-XULT
|
||||
|
||||
boards/arm/sama5/giant-board
|
||||
This is the port of NuttX to the Groboards Giant Board board. This board
|
||||
features the Atmel SAMA5D27C-D1G. See http://groboards.com/giant-board.
|
||||
|
||||
boards/arm/sama5/sama5d3x-ek
|
||||
This is the port of NuttX to the Atmel SAMA5D3x-EK development boards
|
||||
(where x=1,3,4, or 5). These boards feature the Atmel SAMA5D3
|
||||
microprocessors. Four different SAMA5D3x-EK kits are available
|
||||
|
||||
- SAMA5D31-EK with the ATSAMA5D1 (http://www.atmel.com/devices/sama5d31.aspx)
|
||||
- SAMA5D33-EK with the ATSAMA5D3 (http://www.atmel.com/devices/sama5d33.aspx)
|
||||
- SAMA5D34-EK with the ATSAMA5D4 (http://www.atmel.com/devices/sama5d34.aspx)
|
||||
- SAMA5D35-EK with the ATSAMA5D5 (http://www.atmel.com/devices/sama5d35.aspx)
|
||||
|
||||
The each consist of an identical base board with different plug-in modules
|
||||
for each CPU. An option 7 inch LCD is also available. All four boards
|
||||
are supported by NuttX with a simple reconfiguration of the processor
|
||||
type.
|
||||
|
||||
boards/arm/sama5/sama5d3-xplained
|
||||
This is the port of NuttX to the Atmel SAMA5D3x-Xplained development board.
|
||||
This board features the Atmel SAMA5D36. See
|
||||
http://www.atmel.com/devices/sama5d36.aspx.
|
||||
|
||||
boards/arm/sama5/sama5d4-ek
|
||||
This is the port of NuttX to the Atmel SAMA5D4-EK development board.
|
||||
This board features the Atmel SAMA5D44. See http://www.atmel.com.
|
||||
|
||||
boards/arm/samd2l2/samd20-xplained
|
||||
The port of NuttX to the Atmel SAMD20-Xplained Pro development board. This
|
||||
board features the ATSAMD20J18A MCU (Cortex-M0+ with 256KB of FLASH and
|
||||
32KB of SRAM).
|
||||
|
||||
boards/arm/samd2l2/samd21-xplained
|
||||
The port of NuttX to the Atmel SAMD21-Xplained Pro development board. This
|
||||
board features the ATSAMD21J18A MCU (Cortex-M0+ with 256KB of FLASH and
|
||||
32KB of SRAM).
|
||||
|
||||
boards/arm/sam34/sam3u-ek
|
||||
The port of NuttX to the Atmel SAM3U-EK development board.
|
||||
|
||||
boards/arm/sam34/sam4cmp-db
|
||||
The port of NuttX to the Atmel SAM4CMP-DB development board.
|
||||
|
||||
boards/arm/sam34/sam4e-ek
|
||||
The port of NuttX to the Atmel SAM4E-EK development board. This board
|
||||
features the SAM4E16 MCU running at up to 120MHz.
|
||||
|
||||
boards/arm/sam34/sam4l-xplained
|
||||
The port of NuttX to the Atmel SAM4L-Xplained development board.
|
||||
|
||||
boards/arm/sam34/sam4s-xplained
|
||||
The port of NuttX to the Atmel SAM4S-Xplained development board.
|
||||
|
||||
boards/arm/sam34/sam4s-xplained-pro
|
||||
The port of NuttX to the Atmel SAM4S-Xplained Pro development board.
|
||||
|
||||
boards/arm/samv7/same70-xplained
|
||||
The port of NuttX to the Atmel SAME70 Xplained evaluation board.
|
||||
|
||||
boards/arm/samv7/samv71-xult
|
||||
The port of NuttX to the Atmel SAMV71 Xplained Ultra evaluation board.
|
||||
|
||||
boards/sim/sim/sim
|
||||
A user-mode port of NuttX to the x86 Linux platform is available.
|
||||
The purpose of this port is primarily to support OS feature development.
|
||||
This port does not support interrupts or a real timer (and hence no
|
||||
round robin scheduler) Otherwise, it is complete.
|
||||
|
||||
boards/arm/stm32/shenzhou
|
||||
This is the port of NuttX to the Shenzhou development board from
|
||||
www.armjishu.com. This board features the STMicro STM32F107VCT MCU.
|
||||
|
||||
boards/renesas/m16c/skp16c26
|
||||
Renesas M16C processor on the Renesas SKP16C26 StarterKit. This port
|
||||
uses the GNU m32c toolchain. STATUS: The port is complete but untested
|
||||
due to issues with compiler internal errors.
|
||||
|
||||
boards/arm/stm32/stm3210e-eval
|
||||
STMicro STM3210E-EVAL development board based on the STMicro STM32F103ZET6
|
||||
microcontroller (ARM Cortex-M3). This port uses the GNU Cortex-M3
|
||||
toolchain.
|
||||
|
||||
boards/arm/stm32/stm3220g-eval
|
||||
STMicro STM3220G-EVAL development board based on the STMicro STM32F407IG
|
||||
microcontroller (ARM Cortex-M3).
|
||||
|
||||
boards/arm/stm32/stm3240g-eval
|
||||
STMicro STM3240G-EVAL development board based on the STMicro STM32F103ZET6
|
||||
microcontroller (ARM Cortex-M4 with FPU). This port uses a GNU Cortex-M4
|
||||
toolchain (such as CodeSourcery).
|
||||
|
||||
boards/arm/stm32/stm32butterfly2
|
||||
Kamami stm32butterfly2 development board with optional ETH phy. See
|
||||
https://kamami.pl/zestawy-uruchomieniowe-stm32/178507-stm32butterfly2.html
|
||||
|
||||
boards/arm/stm32/stm32f051-discovery
|
||||
STMicro STM32F051-Discovery board based on the STMicro ARCH_CHIP_STM32F051R8
|
||||
MCU.
|
||||
|
||||
boards/arm/stm32/stm32f072-discovery
|
||||
STMicro STM32F072-Discovery board based on the STMicro ARCH_CHIP_STM32F072RB
|
||||
MCU.
|
||||
|
||||
boards/arm/stm32/stm32f103-minimum
|
||||
Generic STM32F103C8T6 Minimum ARM Development Board.
|
||||
|
||||
boards/arm/stm32/stm32f4discovery
|
||||
STMicro STM32F4-Discovery board based on the STMicro STM32F407VGT6 MCU.
|
||||
|
||||
boards/arm/stm32/aiit-arm32-board
|
||||
STMicro STM32F4-AIIT board based on the STMicro STM32F407VGT6 MCU.
|
||||
|
||||
boards/arm/stm32/stm32f411e-disco
|
||||
This is a minimal configuration that supports low-level test of the
|
||||
STMicro STM32F411E-Discovery Board.
|
||||
|
||||
boards/arm/stm32/stm32f429i-disco
|
||||
STMicro STM32F429I-Discovery board based on the STMicro STM32F429ZIT6 MCU.
|
||||
|
||||
boards/arm/stm32f7/stm32f746g-disco
|
||||
STMicro STM32F746G-DISCO development board featuring the STM32F746NGH6
|
||||
MCU. The STM32F746NGH6 is a 216MHz Cortex-M7 operation with 1024Kb Flash
|
||||
memory and 300Kb SRAM.
|
||||
|
||||
boards/arm/stm32f7/stm32f746g-ws
|
||||
Waveshare STM32F746 development board featuring the STM32F746IG MCU.
|
||||
|
||||
boards/arm/stm32l4/stm32l476-mdk
|
||||
Motorola Mods Development Board (MDK) features STM32L476ME MCU.
|
||||
The STM32L476ME is a Cortex-M4 optimised for low-power operation
|
||||
at up to 80MHz operation with 1024Kb Flash memory and 96+32Kb SRAM.
|
||||
|
||||
boards/arm/stm32f7/stm32f769i-disco
|
||||
NuttX configurations for the STMicro STM32F769I-DISCO development board
|
||||
featuring the STM32F769NIH6 MCU. The STM32F769NIH6 is a 216MHz Cortex-M7
|
||||
operating with 2048K Flash memory and 512Kb SRAM.
|
||||
|
||||
boards/arm/stm32l4/stm32l476vg-disco
|
||||
STMicro STM32L476VG_DISCO development board featuring the STM32L476VG
|
||||
MCU. The STM32L476VG is a Cortex-M4 optimised for low-power operation
|
||||
at up to 80MHz operation with 1024Kb Flash memory and 96+32Kb SRAM.
|
||||
|
||||
boards/arm/stm32/stm32ldiscovery
|
||||
STMicro STM32L-Discovery board based on the STMicro STM32L152RB MCU.
|
||||
|
||||
boards/arm/stm32/stm32vldiscovery
|
||||
STMicro STM32VL-Discovery board based on the STMicro STM32F100RB MCU.
|
||||
|
||||
boards/mips/pic32mx/sure-pic32mx
|
||||
The "Advanced USB Storage Demo Board," Model DB-DP11215, from Sure
|
||||
Electronics (http://www.sureelectronics.net/). This board features
|
||||
the MicroChip PIC32MX440F512H. See also
|
||||
http://www.sureelectronics.net/goods.php?id=1168 for further
|
||||
information about the Sure DB-DP11215 board.
|
||||
|
||||
boards/avr/at90usb/teensy-2.0
|
||||
This is the port of NuttX to the PJRC Teensy++ 2.0 board. This board is
|
||||
developed by http://pjrc.com/teensy/. The Teensy++ 2.0 is based
|
||||
on an Atmel AT90USB1286 MCU.
|
||||
|
||||
boards/arm/kinetis/teensy-3.x
|
||||
This is the port of NuttX to the Teensy-3.1 from PJRC
|
||||
(https://www.pjrc.com/). The Teensy-3.1 features the Freescale
|
||||
MK30DX256VLH7 chip (now NXP). The MK30DX256VLH7 is a 64-pin Cortex-M4
|
||||
running at 72MHz. It has 256KiB of program FLASH memory and 64KiB of
|
||||
SRAM. For more information about the Teensy 3.1, see
|
||||
|
||||
https://www.pjrc.com/teensy/teensy31.html
|
||||
https://www.pjrc.com/store/teensy31.html
|
||||
|
||||
This board configuration can also be used with the older Teensy-3.0. The
|
||||
Teensy-3.0 has the same schematic (although some pins are not used on the
|
||||
Teensy-3.0). the primary difference is that the Teensy 3.0 has a
|
||||
MK30DX128VLH5 with slightly less capability.
|
||||
|
||||
boards/arm/imxrt/teensy-4.x
|
||||
This is the port of NuttX to the PJRC Teensy++ 4.x board. This board is
|
||||
developed by http://pjrc.com/teensy/. The Teensy++ 4.x is based
|
||||
on an NXP MIMXRT1062DVL6A MCU. The port can support both Teensy 4.0 and
|
||||
Teensy 4.1 boards.
|
||||
|
||||
https://www.pjrc.com/store/teensy40.html
|
||||
https://www.pjrc.com/store/teensy41.html
|
||||
|
||||
boards/arm/kl/teensy-lc
|
||||
This is the port of nuttx for the Teensy LC board. The Teensy LC
|
||||
is a DIP style breakout board for the MKL25Z64 and comes with a USB
|
||||
based bootloader.
|
||||
|
||||
boards/arm/tiva/tm4c123g-launchpad
|
||||
This is the port of NuttX to the Tiva TM4C123G LaunchPad. The
|
||||
Tiva TM4C123G LaunchPad Evaluation Board is a low-cost evaluation
|
||||
platform for ARM Cortex-M4F-based microcontrollers from Texas
|
||||
Instruments.
|
||||
|
||||
boards/arm/tiva/tm4c1294-launchpad
|
||||
This is the port of NuttX to the Tiva TM4C1294 LaunchPad. The
|
||||
Tiva TM4C123G LaunchPad Evaluation Board is a low-cost evaluation
|
||||
platform for ARM Cortex-M4F-based microcontrollers from Texas
|
||||
Instruments.
|
||||
|
||||
boards/arm/tmx570/tms570ls31x-usb-kit
|
||||
TI Hercules TMS570LS31xx Evaluation Kit (TMDS570ls31xx USB Kit)
|
||||
featuring the Hercules TMS570LS3137ZWT chip.
|
||||
|
||||
boards/arm/kinetis/twr-k60n512
|
||||
Kinetis K60 Cortex-M4 MCU. This port uses the FreeScale TWR-K60N512
|
||||
development board.
|
||||
|
||||
boards/arm/kinetis/twr-k64f120m
|
||||
Kinetis K64 Cortex-M4 MCU. This port uses the FreeScale TWR-K64F120M
|
||||
development board.
|
||||
|
||||
boards/mips/pic32mx/ubw32
|
||||
This is the port to the Sparkfun UBW32 board. This port uses the original v2.4
|
||||
board which is based on the MicroChip PIC32MX460F512L. See
|
||||
http://www.sparkfun.com/products/8971. This older version has been replaced
|
||||
with this board http://www.sparkfun.com/products/9713. See also
|
||||
http://www.schmalzhaus.com/UBW32/.
|
||||
|
||||
boards/renesas/sh1/us7032evb1
|
||||
This is a port of the Hitachi SH-1 on the Hitachi SH-1/US7032EVB1 board.
|
||||
STATUS: Work has just began on this port.
|
||||
|
||||
boards/arm/stm32/viewtool-stm32f107
|
||||
NuttX configurations for the ViewTool STM32F103/F107 V1.2 board. This
|
||||
board may be fitted with either: (1) STM32F107VCT6 or (2) STM32F103VCT6.
|
||||
See http://www.viewtool.com/ for further information.
|
||||
|
||||
config/xmc4500-relax
|
||||
Infineon XMC4500 Relax Lite v1
|
||||
|
||||
config/xmc4700-relax
|
||||
Infineon XMC4700 Relax
|
||||
|
||||
boards/z16/z16f/z16f2800100zcog
|
||||
z16f Microcontroller. This port use the Zilog z16f2800100zcog
|
||||
development kit and the Zilog ZDS-II Windows command line tools. The
|
||||
development environment is Cygwin under WinXP.
|
||||
|
||||
boards/z80/ez80/z20x
|
||||
Microcontroller. This directory holds the port of NuttX to the z80x board
|
||||
based on an ez80Acclaim! eZ80F091 microcontroller.
|
||||
|
||||
boards/z80/z80/z80sim
|
||||
z80 Microcontroller. This port uses a Z80 instruction set simulator
|
||||
called z80sim. This port also uses the SDCC toolchain
|
||||
(http://sdcc.sourceforge.net/") (verified with version 2.6.0).
|
||||
|
||||
boards/z80/z8/z8encore000zco
|
||||
z8Encore! Microcontroller. This port use the Zilog z8encore000zco
|
||||
development kit, Z8F6403 part, and the Zilog ZDS-II Windows command line
|
||||
tools. The development environment is Cygwin under WinXP.
|
||||
|
||||
boards/z80/z8/z8f64200100kit
|
||||
z8Encore! Microcontroller. This port use the Zilog z8f64200100kit
|
||||
development kit, Z8F6423 part, and the Zilog ZDS-II Windows command line
|
||||
tools. The development environment is Cygwin under WinXP.
|
||||
|
||||
boards/arm/lpc214x/zp214xpa
|
||||
This port is for the NXP LPC2148 as provided on the The0.net
|
||||
ZPA213X/4XPA development board. Includes support for the
|
||||
UG-2864AMBAG01 OLED also from The0.net
|
||||
|
||||
boards/arm/lpc17xx_40xx/zkit-arm-1769
|
||||
Zilogic System's ARM development Kit, ZKIT-ARM-1769. This board is based
|
||||
on the NXP LPC1769. The NuttX Buildroot toolchain is used by default.
|
||||
|
||||
Configuring NuttX
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Configuring NuttX requires only copying
|
||||
|
||||
boards/<arch>/<chip>/<board>/<config-dir>/Make.def to ${TOPDIR}/Make.defs
|
||||
boards/<arch>/<chip>/<board>/<config-dir>/defconfig to ${TOPDIR}/.config
|
||||
|
||||
tools/configure.sh
|
||||
There is a script that automates these steps. The following steps will
|
||||
accomplish the same configuration:
|
||||
|
||||
tools/configure.sh <board>:<config-dir>
|
||||
|
||||
There is an alternative Windows batch file that can be used in the
|
||||
windows native environment like:
|
||||
|
||||
tools\configure.bat <board>:<config-dir>
|
||||
|
||||
See tools/README.txt for more information about these scripts.
|
||||
|
||||
And if your application directory is not in the standard location (../apps
|
||||
or ../apps-<version>), then you should also specify the location of the
|
||||
application directory on the command line like:
|
||||
|
||||
cd tools
|
||||
./configure.sh -a <app-dir> <board>:<config-dir>
|
||||
|
||||
Building Symbol Tables
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Symbol tables are needed at several of the binfmt interfaces in order to bind
|
||||
a module to the base code. These symbol tables can be tricky to create and
|
||||
will probably have to be tailored for any specific application, balancing
|
||||
the number of symbols and the size of the symbol table against the symbols
|
||||
required by the applications.
|
||||
|
||||
The top-level System.map file is one good source of symbol information
|
||||
(which, or course, was just generated from the top-level nuttx file
|
||||
using the GNU 'nm' tool).
|
||||
|
||||
There are also common-separated value (CSV) values in the source try that
|
||||
provide information about symbols. In particular:
|
||||
|
||||
nuttx/syscall/syscall.csv - Describes the NuttX RTOS interface, and
|
||||
nuttx/lib/libc.csv - Describes the NuttX C library interface.
|
||||
|
||||
There is a tool at nuttx/tools/mksymtab that will use these CSV files as
|
||||
input to generate a generic symbol table. See nuttx/tools/README.txt for
|
||||
more information about using the mksymtab tool.
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/****************************************************************************
|
||||
* boards/arm/stm32/common/include/stm32_hs300x.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 __STM32_HS300X_H
|
||||
#define __STM32_HS300X_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Inline Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_hs300x_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize and register the hs300x Temperature Sensor driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* devno - The device number
|
||||
* busno - The I2C bus number
|
||||
* used to build the device path as /dev/i2c1_dev0
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int board_hs300x_initialize(int devno, int busno);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __STM32_HS300X_H
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
#############################################################################
|
||||
# boards/arm/stm32/common/src/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.
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_BMP180),y)
|
||||
CSRCS += stm32_bmp180.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_LEDS_APA102),y)
|
||||
CSRCS += stm32_apa102.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_WS2812),y)
|
||||
CSRCS += stm32_ws2812.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_MAX6675),y)
|
||||
CSRCS += stm32_max6675.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_VEML6070),y)
|
||||
CSRCS += stm32_veml6070.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_INPUT_NUNCHUCK),y)
|
||||
CSRCS += stm32_nunchuck.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_AUDIO_TONE),y)
|
||||
CSRCS += stm32_tone.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_LCD_BACKPACK),y)
|
||||
CSRCS += stm32_lcd_backpack.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_LCD_SSD1306),y)
|
||||
CSRCS += stm32_ssd1306.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_LM75),y)
|
||||
CSRCS += stm32_lm75.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_WL_NRF24L01),y)
|
||||
CSRCS += stm32_nrf24l01.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_HCSR04),y)
|
||||
CSRCS += stm32_hcsr04.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_APDS9960),y)
|
||||
CSRCS += stm32_apds9960.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_ZEROCROSS),y)
|
||||
CSRCS += stm32_zerocross.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_QENCODER),y)
|
||||
CSRCS += stm32_qencoder.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_HALL3PHASE),y)
|
||||
CSRCS += board_hall3ph.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_INA219),y)
|
||||
CSRCS += stm32_ina219.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_L3GD20),y)
|
||||
CSRCS += stm32_l3gd20.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_MPL115A),y)
|
||||
CSRCS += stm32_mpl115a.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_DHTXX),y)
|
||||
CSRCS += stm32_dhtxx.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_XEN1210),y)
|
||||
CSRCS += stm32_xen1210.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_BH1750FVI),y)
|
||||
CSRCS += stm32_bh1750.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_MLX90614),y)
|
||||
CSRCS += stm32_mlx90614.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_MAX31855),y)
|
||||
CSRCS += stm32_max31855.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_LIS3DSH),y)
|
||||
CSRCS += stm32_lis3dsh.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BOARD_STM32_IHM07M1),y)
|
||||
CSRCS += stm32_ihm07m1.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BOARD_STM32_IHM08M1),y)
|
||||
CSRCS += stm32_ihm08m1.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BOARD_STM32_IHM16M1),y)
|
||||
CSRCS += stm32_ihm16m1.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_HS300X),y)
|
||||
CSRCS += stm32_hs300x.c
|
||||
endif
|
||||
|
||||
DEPPATH += --dep-path src
|
||||
VPATH += :src
|
||||
CFLAGS += $(shell $(INCDIR) "$(CC)" $(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)src)
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/****************************************************************************
|
||||
* boards/arm/stm32/common/src/stm32_hs300x.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 <nuttx/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
#include <nuttx/sensors/hs300x.h>
|
||||
|
||||
#include "stm32.h"
|
||||
#include "stm32_i2c.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_hs300x_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize and register the hs300x Temperature Sensor driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* devno - The device number
|
||||
* busno - The I2C bus number
|
||||
* used to build the device path as /dev/i2c1_dev0
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int board_hs300x_initialize(int devno, int busno)
|
||||
{
|
||||
FAR struct i2c_master_s *i2c;
|
||||
char devpath[20];
|
||||
int ret;
|
||||
|
||||
sninfo("Initializing HS300x!\n");
|
||||
|
||||
/* Get an instance of the I2C interface */
|
||||
i2c = stm32_i2cbus_initialize(busno);
|
||||
if (!i2c)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Then register the temperature sensor,such as /dev/i2c1_dev0. */
|
||||
snprintf(devpath, 20, "/dev/i2c%d_dev%d", busno, devno);
|
||||
ret = hs300x_register(devpath, i2c, CONFIG_SENSOR_DEVICE_HS300X_I2C_ADDR);
|
||||
if (ret < 0)
|
||||
{
|
||||
stm32_i2cbus_uninitialize(i2c);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
############################################################################
|
||||
# boards/arm/stm32/stm32f4discovery/scripts/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 $(TOPDIR)/.config
|
||||
include $(TOPDIR)/tools/Config.mk
|
||||
include $(TOPDIR)/arch/arm/src/armv7-m/Toolchain.defs
|
||||
|
||||
LDSCRIPT = ld.script
|
||||
|
||||
ifeq ($(CONFIG_CYGWIN_WINTOOL),y)
|
||||
ARCHSCRIPT = -T "${shell cygpath -w $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT)}"
|
||||
else
|
||||
ARCHSCRIPT = -T$(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT)
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DEBUG_SYMBOLS),y)
|
||||
ARCHOPTIMIZATION = -g
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_DEBUG_NOOPT),y)
|
||||
ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fomit-frame-pointer
|
||||
endif
|
||||
|
||||
ARCHCFLAGS = -fno-builtin
|
||||
ARCHCXXFLAGS = -fno-builtin -fno-exceptions -fcheck-new
|
||||
ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef
|
||||
ARCHWARNINGSXX = -Wall -Wshadow -Wundef
|
||||
ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10
|
||||
|
||||
ifeq ($(CONFIG_ARMV7M_TOOLCHAIN_CLANGL),y)
|
||||
ARCHCFLAGS += -nostdlib -ffreestanding
|
||||
ARCHCXXFLAGS += -nostdlib -ffreestanding
|
||||
else
|
||||
ARCHCFLAGS += -funwind-tables
|
||||
ARCHCXXFLAGS += -fno-rtti -funwind-tables
|
||||
ifneq ($(CONFIG_DEBUG_NOOPT),y)
|
||||
ARCHOPTIMIZATION += -fno-strength-reduce
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
CFLAGS := $(APPPATHS) $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe
|
||||
CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS)
|
||||
CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe
|
||||
CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS)
|
||||
CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS)
|
||||
AFLAGS := $(CFLAGS) -D__ASSEMBLY__
|
||||
|
||||
NXFLATLDFLAGS1 = -r -d -warn-common
|
||||
NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-pcrel.ld -no-check-sections
|
||||
LDNXFLATFLAGS = -e main -s 2048
|
||||
|
||||
# Loadable module definitions
|
||||
|
||||
CMODULEFLAGS = $(CFLAGS) -mlong-calls # --target1-abs
|
||||
|
||||
LDMODULEFLAGS = -r -e module_initialize
|
||||
ifeq ($(CONFIG_CYGWIN_WINTOOL),y)
|
||||
LDMODULEFLAGS += -T "${shell cygpath -w $(TOPDIR)/libs/libc/modlib/gnu-elf.ld}"
|
||||
else
|
||||
LDMODULEFLAGS += -T $(TOPDIR)/libs/libc/modlib/gnu-elf.ld
|
||||
endif
|
||||
|
||||
# ELF module definitions
|
||||
|
||||
CELFFLAGS = $(CFLAGS) -mlong-calls # --target1-abs
|
||||
CXXELFFLAGS = $(CXXFLAGS) -mlong-calls # --target1-abs
|
||||
|
||||
LDELFFLAGS = -r -e main
|
||||
ifeq ($(CONFIG_CYGWIN_WINTOOL),y)
|
||||
LDELFFLAGS += -T "${shell cygpath -w $(BOARD_DIR)$(DELIM)scripts$(DELIM)gnu-elf.ld}"
|
||||
else
|
||||
LDELFFLAGS += -T $(BOARD_DIR)$(DELIM)scripts$(DELIM)gnu-elf.ld
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DEBUG_SYMBOLS),y)
|
||||
LDFLAGS += -g
|
||||
endif
|
||||
+560
@@ -0,0 +1,560 @@
|
||||
/****************************************************************************
|
||||
* boards/arm/stm32/stm32f4discovery/src/stm32_bringup.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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file stm32_bringup.c
|
||||
* @brief nuttx source code
|
||||
* https://github.com/apache/incubator-nuttx.git
|
||||
* @version 10.2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/fs/fs.h>
|
||||
|
||||
#ifdef CONFIG_USBMONITOR
|
||||
# include <nuttx/usb/usbmonitor.h>
|
||||
#endif
|
||||
|
||||
#include "stm32.h"
|
||||
#include "stm32_romfs.h"
|
||||
|
||||
#ifdef CONFIG_STM32_OTGFS
|
||||
# include "stm32_usbhost.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_INPUT_BUTTONS
|
||||
# include <nuttx/input/buttons.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USERLED
|
||||
# include <nuttx/leds/userled.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RNDIS
|
||||
# include <nuttx/usb/rndis.h>
|
||||
#endif
|
||||
|
||||
#include "stm32f4discovery.h"
|
||||
|
||||
/* Conditional logic in stm32f4discovery.h will determine if certain features
|
||||
* are supported. Tests for these features need to be made after including
|
||||
* stm32f4discovery.h.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_RTC_DRIVER
|
||||
# include <nuttx/timers/rtc.h>
|
||||
# include "stm32_rtc.h"
|
||||
#endif
|
||||
|
||||
/* The following are includes from board-common logic */
|
||||
|
||||
#ifdef CONFIG_SENSORS_BMP180
|
||||
#include "stm32_bmp180.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_MAX6675
|
||||
#include "stm32_max6675.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_INPUT_NUNCHUCK
|
||||
#include "stm32_nunchuck.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_ZEROCROSS
|
||||
#include "stm32_zerocross.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_QENCODER
|
||||
#include "board_qencoder.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_BH1750FVI
|
||||
#include "stm32_bh1750.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LIS3DSH
|
||||
#include "stm32_lis3dsh.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LCD_BACKPACK
|
||||
#include "stm32_lcd_backpack.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_MAX31855
|
||||
#include "stm32_max31855.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_MLX90614
|
||||
#include "stm32_mlx90614.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_XEN1210
|
||||
#include "stm32_xen1210.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USBADB
|
||||
# include <nuttx/usb/adb.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_HS300X
|
||||
#include "stm32_hs300x.h"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_i2c_register
|
||||
*
|
||||
* Description:
|
||||
* Register one I2C drivers for the I2C tool.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_I2C) && defined(CONFIG_SYSTEM_I2CTOOL)
|
||||
static void stm32_i2c_register(int bus)
|
||||
{
|
||||
FAR struct i2c_master_s *i2c;
|
||||
int ret;
|
||||
|
||||
i2c = stm32_i2cbus_initialize(bus);
|
||||
if (i2c == NULL)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to get I2C%d interface\n", bus);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = i2c_register(i2c, bus);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to register I2C%d driver: %d\n",
|
||||
bus, ret);
|
||||
stm32_i2cbus_uninitialize(i2c);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_i2ctool
|
||||
*
|
||||
* Description:
|
||||
* Register I2C drivers for the I2C tool.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_I2C) && defined(CONFIG_SYSTEM_I2CTOOL)
|
||||
static void stm32_i2ctool(void)
|
||||
{
|
||||
stm32_i2c_register(1);
|
||||
#if 0
|
||||
stm32_i2c_register(1);
|
||||
stm32_i2c_register(2);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
# define stm32_i2ctool()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_bringup
|
||||
*
|
||||
* Description:
|
||||
* Perform architecture-specific initialization
|
||||
*
|
||||
* CONFIG_BOARD_LATE_INITIALIZE=y :
|
||||
* Called from board_late_initialize().
|
||||
*
|
||||
* CONFIG_BOARD_LATE_INITIALIZE=n && CONFIG_BOARDCTL=y :
|
||||
* Called from the NSH library
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int stm32_bringup(void)
|
||||
{
|
||||
#ifdef HAVE_RTC_DRIVER
|
||||
FAR struct rtc_lowerhalf_s *lower;
|
||||
#endif
|
||||
int ret = OK;
|
||||
|
||||
#if defined(CONFIG_I2C) && defined(CONFIG_SYSTEM_I2CTOOL)
|
||||
stm32_i2ctool();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_BMP180
|
||||
/* Initialize the BMP180 pressure sensor. */
|
||||
|
||||
ret = board_bmp180_initialize(0, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Failed to initialize BMP180, error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_BH1750FVI
|
||||
ret = board_bh1750_initialize(0, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: stm32_bh1750initialize() failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_ZEROCROSS
|
||||
/* Configure the zero-crossing driver */
|
||||
|
||||
board_zerocross_initialize(0);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LEDS_MAX7219
|
||||
ret = stm32_max7219init("/dev/numdisp0");
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: max7219_leds_register failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LCD_ST7032
|
||||
ret = stm32_st7032init("/dev/slcd0");
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: st7032_register failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RGBLED
|
||||
/* Configure the RGB LED driver */
|
||||
|
||||
stm32_rgbled_setup();
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PCA9635PW)
|
||||
/* Initialize the PCA9635 chip */
|
||||
|
||||
ret = stm32_pca9635_initialize();
|
||||
if (ret < 0)
|
||||
{
|
||||
serr("ERROR: stm32_pca9635_initialize failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VIDEO_FB
|
||||
/* Initialize and register the framebuffer driver */
|
||||
|
||||
ret = fb_register(0, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: fb_register() failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LCD_BACKPACK
|
||||
/* slcd:0, i2c:1, rows=2, cols=16 */
|
||||
|
||||
ret = board_lcd_backpack_init(0, 1, 2, 16);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Failed to initialize PCF8574 LCD, error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SDIO
|
||||
/* Initialize the SDIO block driver */
|
||||
|
||||
ret = stm32_sdio_initialize();
|
||||
if (ret != OK)
|
||||
{
|
||||
ferr("ERROR: Failed to initialize MMC/SD driver: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MMCSD_SPI
|
||||
/* Initialize the MMC/SD SPI driver (SPI2 is used) */
|
||||
|
||||
ret = stm32_mmcsd_initialize(2, CONFIG_NSH_MMCSDMINOR);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Failed to initialize SD slot %d: %d\n",
|
||||
CONFIG_NSH_MMCSDMINOR, ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_USBHOST
|
||||
/* Initialize USB host operation. stm32_usbhost_initialize() starts a
|
||||
* thread will monitor for USB connection and disconnection events.
|
||||
*/
|
||||
|
||||
ret = stm32_usbhost_initialize();
|
||||
if (ret != OK)
|
||||
{
|
||||
uerr("ERROR: Failed to initialize USB host: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_USBMONITOR
|
||||
/* Start the USB Monitor */
|
||||
|
||||
ret = usbmonitor_start();
|
||||
if (ret != OK)
|
||||
{
|
||||
uerr("ERROR: Failed to start USB monitor: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PWM
|
||||
/* Initialize PWM and register the PWM device. */
|
||||
|
||||
ret = stm32_pwm_setup();
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: stm32_pwm_setup() failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CAN
|
||||
/* Initialize CAN and register the CAN driver. */
|
||||
|
||||
ret = stm32_can_setup();
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: stm32_can_setup failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_INPUT_BUTTONS
|
||||
/* Register the BUTTON driver */
|
||||
|
||||
ret = btn_lower_initialize("/dev/buttons");
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: btn_lower_initialize() failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_INPUT_NUNCHUCK
|
||||
/* Register the Nunchuck driver */
|
||||
|
||||
ret = board_nunchuck_initialize(0, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: nunchuck_initialize() failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_MLX90614
|
||||
ret = board_mlx90614_initialize(0, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Failed to initialize MLX90614, error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_QENCODER
|
||||
/* Initialize and register the qencoder driver */
|
||||
|
||||
ret = board_qencoder_initialize(0, CONFIG_STM32F4DISCO_QETIMER);
|
||||
if (ret != OK)
|
||||
{
|
||||
syslog(LOG_ERR,
|
||||
"ERROR: Failed to register the qencoder: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USERLED
|
||||
/* Register the LED driver */
|
||||
|
||||
ret = userled_lower_initialize("/dev/userleds");
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: userled_lower_initialize() failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RTC_DS1307
|
||||
ret = stm32_ds1307_init();
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Failed to initialize DS1307 RTC driver: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_RTC_DRIVER
|
||||
/* Instantiate the STM32 lower-half RTC driver */
|
||||
|
||||
lower = stm32_rtc_lowerhalf();
|
||||
if (!lower)
|
||||
{
|
||||
serr("ERROR: Failed to instantiate the RTC lower-half driver\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Bind the lower half driver and register the combined RTC driver
|
||||
* as /dev/rtc0
|
||||
*/
|
||||
|
||||
ret = rtc_initialize(0, lower);
|
||||
if (ret < 0)
|
||||
{
|
||||
serr("ERROR: Failed to bind/register the RTC driver: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CS43L22
|
||||
/* Configure CS43L22 audio */
|
||||
|
||||
ret = stm32_cs43l22_initialize(1);
|
||||
if (ret != OK)
|
||||
{
|
||||
serr("Failed to initialize CS43L22 audio: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_MAX31855
|
||||
/* Register device 0 on spi channel 2 */
|
||||
|
||||
ret = board_max31855_initialize(0, 2);
|
||||
if (ret < 0)
|
||||
{
|
||||
serr("ERROR: stm32_max31855initialize failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_MAX6675
|
||||
ret = board_max6675_initialize(0, 2);
|
||||
if (ret < 0)
|
||||
{
|
||||
serr("ERROR: stm32_max6675initialize failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FS_PROCFS
|
||||
/* Mount the procfs file system */
|
||||
|
||||
ret = nx_mount(NULL, STM32_PROCFS_MOUNTPOINT, "procfs", 0, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
serr("ERROR: Failed to mount procfs at %s: %d\n",
|
||||
STM32_PROCFS_MOUNTPOINT, ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32_ROMFS
|
||||
ret = stm32_romfs_initialize();
|
||||
if (ret < 0)
|
||||
{
|
||||
serr("ERROR: Failed to mount romfs at %s: %d\n",
|
||||
CONFIG_STM32_ROMFS_MOUNTPOINT, ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_XEN1210
|
||||
ret = board_xen1210_initialize(0, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
serr("ERROR: xen1210_archinitialize failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LIS3DSH
|
||||
/* Create a lis3dsh driver instance fitting the chip built into
|
||||
* stm32f4discovery
|
||||
*/
|
||||
|
||||
ret = board_lis3dsh_initialize(0, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
serr("ERROR: Failed to initialize LIS3DSH driver: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_HCIUART
|
||||
ret = hciuart_dev_initialize();
|
||||
if (ret < 0)
|
||||
{
|
||||
serr("ERROR: Failed to initialize HCI UART driver: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_RNDIS)
|
||||
uint8_t mac[6];
|
||||
mac[0] = 0xa0; /* TODO */
|
||||
mac[1] = (CONFIG_NETINIT_MACADDR_2 >> (8 * 0)) & 0xff;
|
||||
mac[2] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 3)) & 0xff;
|
||||
mac[3] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 2)) & 0xff;
|
||||
mac[4] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 1)) & 0xff;
|
||||
mac[5] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 0)) & 0xff;
|
||||
usbdev_rndis_initialize(mac);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_WL_GS2200M
|
||||
ret = stm32_gs2200m_initialize("/dev/gs2200m", 3);
|
||||
if (ret < 0)
|
||||
{
|
||||
serr("ERROR: Failed to initialize GS2200M: %d \n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LPWAN_SX127X
|
||||
ret = stm32_lpwaninitialize();
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to initialize wireless driver:"
|
||||
" %d\n", ret);
|
||||
}
|
||||
#endif /* CONFIG_LPWAN_SX127X */
|
||||
|
||||
#ifdef CONFIG_USBADB
|
||||
usbdev_adb_initialize();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_HS300X
|
||||
ret = board_hs300x_initialize(0, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Failed to initialize HS300x, error %d\n", ret);
|
||||
}
|
||||
#endif /* CONFIG_SENSORS_HS300X */
|
||||
|
||||
return ret;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,335 @@
|
||||
############################################################################
|
||||
# drivers/sensors/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 sensor drivers
|
||||
|
||||
ifeq ($(CONFIG_SENSORS),y)
|
||||
|
||||
CSRCS += sensor.c
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_WTGAHRS2),y)
|
||||
CSRCS += wtgahrs2.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_FAKESENSOR),y)
|
||||
CSRCS += fakesensor.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_HCSR04),y)
|
||||
CSRCS += hc_sr04.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_ADXL345),y)
|
||||
CSRCS += adxl345_base.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_DHTXX),y)
|
||||
CSRCS += dhtxx.c
|
||||
endif
|
||||
|
||||
# These drivers depend on I2C support
|
||||
|
||||
ifeq ($(CONFIG_I2C),y)
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_APDS9960),y)
|
||||
CSRCS += apds9960.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_AK09912),y)
|
||||
CSRCS += ak09912.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_AS5048B),y)
|
||||
CSRCS += as5048b.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_AS726X),y)
|
||||
CSRCS += as726x.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_FXOS8700CQ),y)
|
||||
CSRCS += fxos8700cq.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_HYT271),y)
|
||||
CSRCS += hyt271.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_KXTJ9),y)
|
||||
CSRCS += kxtj9.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_LIS2DH),y)
|
||||
CSRCS += lis2dh.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_LIS331DL),y)
|
||||
CSRCS += lis331dl.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_LSM303AGR),y)
|
||||
CSRCS += lsm303agr.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_LSM6DSL),y)
|
||||
CSRCS += lsm6dsl.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_LSM9DS1),y)
|
||||
CSRCS += lsm9ds1.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_MSA301),y)
|
||||
CSRCS += msa301.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_LPS25H),y)
|
||||
CSRCS += lps25h.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ADXL345_I2C),y)
|
||||
CSRCS += adxl345_i2c.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_BH1750FVI),y)
|
||||
CSRCS += bh1750fvi.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_BMG160),y)
|
||||
CSRCS += bmg160.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_BMI160),y)
|
||||
CSRCS += bmi160.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_BMP180),y)
|
||||
CSRCS += bmp180.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_BMP280),y)
|
||||
CSRCS += bmp280.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_ISL29023),y)
|
||||
CSRCS += isl29023.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_HTS221),y)
|
||||
CSRCS += hts221.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_LM75_I2C),y)
|
||||
CSRCS += lm75.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_LM92),y)
|
||||
CSRCS += lm92.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_MAX44009),y)
|
||||
CSRCS += max44009.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_MB7040),y)
|
||||
CSRCS += mb7040.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_MCP9844),y)
|
||||
CSRCS += mcp9844.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_MLX90393),y)
|
||||
CSRCS += mlx90393.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_MLX90614),y)
|
||||
CSRCS += mlx90614.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_MS58XX),y)
|
||||
CSRCS += ms58xx.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_LTC4151),y)
|
||||
CSRCS += ltc4151.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_INA219),y)
|
||||
CSRCS += ina219.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_INA226),y)
|
||||
CSRCS += ina226.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_INA3221),y)
|
||||
CSRCS += ina3221.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_SCD30),y)
|
||||
CSRCS += scd30.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_SGP30),y)
|
||||
CSRCS += sgp30.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_AHT10),y)
|
||||
CSRCS += aht10.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_SHT21),y)
|
||||
CSRCS += sht21.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_SHT3X),y)
|
||||
CSRCS += sht3x.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_SPS30),y)
|
||||
CSRCS += sps30.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_T67XX),y)
|
||||
CSRCS += t67xx.c
|
||||
endif
|
||||
|
||||
endif # CONFIG_I2C
|
||||
|
||||
# These drivers depend on SPI support
|
||||
|
||||
ifeq ($(CONFIG_SPI),y)
|
||||
|
||||
ifeq ($(CONFIG_ADXL345_SPI),y)
|
||||
CSRCS += adxl345_spi.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_ADXL372),y)
|
||||
CSRCS += adxl372.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_LIS3DSH),y)
|
||||
CSRCS += lis3dsh.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_LIS3DH),y)
|
||||
CSRCS += lis3dh.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_MAX31855),y)
|
||||
CSRCS += max31855.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_MAX6675),y)
|
||||
CSRCS += max6675.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_MPL115A),y)
|
||||
CSRCS += mpl115a.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_LIS3MDL),y)
|
||||
CSRCS += lis3mdl.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_LSM330SPI),y)
|
||||
CSRCS += lsm330_spi.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_L3GD20),y)
|
||||
CSRCS += l3gd20.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_ADT7320),y)
|
||||
CSRCS += adt7320.c
|
||||
endif
|
||||
|
||||
endif # CONFIG_SPI
|
||||
|
||||
# These drivers depend on 1WIRE support
|
||||
|
||||
ifeq ($(CONFIG_1WIRE),y)
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_DS18B20),y)
|
||||
CSRCS += ds18b20.c
|
||||
endif
|
||||
|
||||
endif # CONFIG_1WIRE
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_MPU60X0),y)
|
||||
CSRCS += mpu60x0.c
|
||||
endif
|
||||
|
||||
# Quadrature encoder upper half
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_QENCODER),y)
|
||||
CSRCS += qencoder.c
|
||||
endif
|
||||
|
||||
# 3-phase Hall effect sensor upper half
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_HALL3PHASE),y)
|
||||
CSRCS += hall3ph.c
|
||||
endif
|
||||
|
||||
# Vishay VEML6070
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_VEML6070),y)
|
||||
CSRCS += veml6070.c
|
||||
endif
|
||||
|
||||
# ST VL53L1X
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_VL53L1X),y)
|
||||
CSRCS += vl53l1x.c
|
||||
endif
|
||||
|
||||
# Sensixs XEN1210
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_XEN1210),y)
|
||||
CSRCS += xen1210.c
|
||||
endif
|
||||
|
||||
# Zero Cross upper half
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_ZEROCROSS),y)
|
||||
CSRCS += zerocross.c
|
||||
endif
|
||||
|
||||
# TI HDC1008
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_HDC1008),y)
|
||||
CSRCS += hdc1008.c
|
||||
endif
|
||||
|
||||
# HS300x
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_HS300X),y)
|
||||
CSRCS += hs300x.c
|
||||
endif
|
||||
|
||||
# Include sensor driver build support
|
||||
|
||||
DEPPATH += --dep-path sensors
|
||||
VPATH += :sensors
|
||||
CFLAGS += ${shell $(INCDIR) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)sensors}
|
||||
|
||||
endif # CONFIG_SENSORS
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file hs300x.c
|
||||
* @brief hs300x sensor driver
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.03.17
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <fixedmath.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
#include <nuttx/sensors/hs300x.h>
|
||||
#include <nuttx/random.h>
|
||||
|
||||
#if defined(CONFIG_I2C) && defined(CONFIG_HS300X_I2C)
|
||||
|
||||
/****************************************************************************
|
||||
* Private
|
||||
****************************************************************************/
|
||||
struct hs300x_dev_s
|
||||
{
|
||||
FAR struct i2c_master_s *i2c; /* I2C interface */
|
||||
uint8_t addr; /* I2C address */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* I2C Helpers */
|
||||
static int hs300x_i2c_write(FAR struct hs300x_dev_s *priv, FAR char *buffer, int buflen);
|
||||
static int hs300x_i2c_read(FAR struct hs300x_dev_s *priv, FAR char *buffer, int buflen);
|
||||
|
||||
/* Character driver methods */
|
||||
static int hs300x_open(FAR struct file *filep);
|
||||
static int hs300x_close(FAR struct file *filep);
|
||||
static ssize_t hs300x_read(FAR struct file *filep, FAR char *buffer, size_t buflen);
|
||||
static ssize_t hs300x_write(FAR struct file *filep, FAR const char *buffer, size_t buflen);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct file_operations g_hs300xfops =
|
||||
{
|
||||
hs300x_open,
|
||||
hs300x_close,
|
||||
hs300x_read,
|
||||
hs300x_write,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: hs300x_i2c_write
|
||||
*
|
||||
* Description:
|
||||
* Write to the I2C device.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int hs300x_i2c_write(FAR struct hs300x_dev_s *priv,
|
||||
FAR char *buffer, int buflen)
|
||||
{
|
||||
struct i2c_msg_s msg;
|
||||
int ret;
|
||||
|
||||
/* Setup for the transfer */
|
||||
msg.frequency = CONFIG_HS300X_I2C_FREQUENCY,
|
||||
msg.addr = priv->addr;
|
||||
msg.flags = 0;
|
||||
msg.buffer = (FAR uint8_t *)buffer; /* Override const */
|
||||
msg.length = buflen;
|
||||
|
||||
/* Then perform the transfer. */
|
||||
ret = I2C_TRANSFER(priv->i2c, &msg, 1);
|
||||
return (ret >= 0) ? OK : ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: hs300x_i2c_read
|
||||
*
|
||||
* Description:
|
||||
* Read from the I2C device.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int hs300x_i2c_read(FAR struct hs300x_dev_s *priv,
|
||||
FAR char *buffer, int buflen)
|
||||
{
|
||||
struct i2c_msg_s msg;
|
||||
int ret;
|
||||
|
||||
/* Setup for the transfer */
|
||||
|
||||
msg.frequency = CONFIG_HS300X_I2C_FREQUENCY,
|
||||
msg.addr = priv->addr,
|
||||
msg.flags = I2C_M_READ;
|
||||
msg.buffer = (FAR uint8_t *)buffer;
|
||||
msg.length = buflen;
|
||||
|
||||
/* Then perform the transfer. */
|
||||
ret = I2C_TRANSFER(priv->i2c, &msg, 1);
|
||||
return (ret >= 0) ? OK : ret;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Name: hs300x_open
|
||||
****************************************************************************/
|
||||
static int hs300x_open(FAR struct file *filep)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: hs300x_close
|
||||
****************************************************************************/
|
||||
|
||||
static int hs300x_close(FAR struct file *filep)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: hs300x_read
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t hs300x_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct hs300x_dev_s *priv = inode->i_private;
|
||||
int ret;
|
||||
|
||||
if (buflen != 4)
|
||||
{
|
||||
snerr("ERROR: You can't read something other than 32 bits (4 bytes)\n");
|
||||
return -1;
|
||||
}
|
||||
/* Restart and read 32-bits from the register */
|
||||
ret = hs300x_i2c_read(priv, buffer, 4);
|
||||
if (ret < 0)
|
||||
{
|
||||
snerr("ERROR: i2c_read failed: %d\n", ret);
|
||||
return (ssize_t)ret;;
|
||||
}
|
||||
|
||||
return buflen;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: hs300x_write
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t hs300x_write(FAR struct file *filep, FAR const char *buffer,
|
||||
size_t buflen)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct hs300x_dev_s *priv = inode->i_private;
|
||||
int ret;
|
||||
|
||||
ret = hs300x_i2c_write(priv, buffer, buflen);
|
||||
if (ret < 0)
|
||||
{
|
||||
snerr("ERROR: i2c_write failed: %d\n", ret);
|
||||
return (ssize_t)ret;;
|
||||
}
|
||||
|
||||
return buflen;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Name: hs300x_register
|
||||
*
|
||||
* Description:
|
||||
* Register the HS300x character device as 'devpath'
|
||||
*
|
||||
* Input Parameters:
|
||||
* devpath - The full path to the driver to register. E.g., "/dev/i2c1"
|
||||
* i2c - An instance of the I2C interface to use to communicate with HS300X
|
||||
* addr - The I2C address of the HS300x. The base I2C address of the HS300X
|
||||
* is 0x44.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int hs300x_register(FAR const char *devpath, FAR struct i2c_master_s *i2c,
|
||||
uint8_t addr)
|
||||
{
|
||||
FAR struct hs300x_dev_s *priv;
|
||||
int ret;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
DEBUGASSERT(i2c != NULL);
|
||||
DEBUGASSERT(addr == CONFIG_SENSOR_DEVICE_HS300X_I2C_ADDR);
|
||||
|
||||
/* Initialize the HS300x device structure */
|
||||
priv = (FAR struct hs300x_dev_s *)kmm_malloc(sizeof(struct hs300x_dev_s));
|
||||
if (priv == NULL)
|
||||
{
|
||||
snerr("ERROR: Failed to allocate instance\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->i2c = i2c;
|
||||
priv->addr = addr;
|
||||
|
||||
/* Register the character driver */
|
||||
ret = register_driver(devpath, &g_hs300xfops, 0666, priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
snerr("ERROR: Failed to register driver: %d\n", ret);
|
||||
kmm_free(priv);
|
||||
}
|
||||
|
||||
sninfo("HS300X driver loaded successfully!\n");
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_I2C && CONFIG_HS300X_I2C */
|
||||
@@ -0,0 +1,88 @@
|
||||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
if DRIVERS_LPWAN
|
||||
|
||||
config LPWAN_SX127X
|
||||
bool "SX127X Low Power Long Range transceiver support"
|
||||
default n
|
||||
select SPI
|
||||
select SCHED_HPWORK
|
||||
---help---
|
||||
This options adds driver support for the Samtech SX127X chip.
|
||||
|
||||
if LPWAN_SX127X
|
||||
|
||||
config LPWAN_SX127X_RFFREQ_DEFAULT
|
||||
int "SX127X default RF frequency"
|
||||
default 433000000
|
||||
|
||||
config LPWAN_SX127X_SPIFREQ
|
||||
int "SX127X SPI frequency"
|
||||
default 1000000
|
||||
---help---
|
||||
SX127X SPI frequency up to 10MHz
|
||||
|
||||
config LPWAN_SX127X_TXPOWER_DEFAULT
|
||||
int "SX127X default TX power"
|
||||
default 20
|
||||
|
||||
config LPWAN_SX127X_PREAMBLE_DEFAULT
|
||||
int "SX127X default preamble length"
|
||||
default 8
|
||||
|
||||
config LPWAN_SX127X_MODULATION_DEFAULT
|
||||
int "SX127X default modulation scheme"
|
||||
default 3 if LPWAN_SX127X_LORA
|
||||
default 1 if LPWAN_SX127X_FSKOOK
|
||||
range 1 3
|
||||
---help---
|
||||
1 - FSK, 2 - OOK, 3 - LORA
|
||||
|
||||
config LPWAN_SX127X_CRCON
|
||||
int "SX127X CRC ON"
|
||||
range 0 1
|
||||
default 1
|
||||
|
||||
config LPWAN_SX127X_RXSUPPORT
|
||||
bool "SX127X RX support"
|
||||
default y
|
||||
|
||||
if LPWAN_SX127X_RXSUPPORT
|
||||
|
||||
config LPWAN_SX127X_RXFIFO_LEN
|
||||
int "SX127X RX FIFO length"
|
||||
default 5
|
||||
|
||||
config LPWAN_SX127X_RXFIFO_DATA_LEN
|
||||
int "SX127X RX FIFO data length"
|
||||
default 256
|
||||
|
||||
endif #LPWAN_SX127X_RXSUPPORT
|
||||
|
||||
config LPWAN_SX127X_TXSUPPORT
|
||||
bool "SX127X TX support"
|
||||
default y
|
||||
|
||||
config LPWAN_SX127X_LORA
|
||||
bool "SX127X LORA support"
|
||||
default y
|
||||
|
||||
if LPWAN_SX127X_LORA
|
||||
|
||||
config LPWAN_SX127X_LORA_IMPHEADER
|
||||
int "SX127X LORA implicit header ON"
|
||||
range 0 1
|
||||
default 0
|
||||
|
||||
endif # LPWAN_SX127X_LORA
|
||||
|
||||
config LPWAN_SX127X_FSKOOK
|
||||
bool "SX127X FSK/OOK support"
|
||||
default n
|
||||
|
||||
endif # WL_SX127X
|
||||
|
||||
endif # DRIVERS_LPWAN
|
||||
+4772
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file hs300x.h
|
||||
* @brief hs300x sensor driver
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.03.17
|
||||
*/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_SENSORS_HS300X_H
|
||||
#define __INCLUDE_NUTTX_SENSORS_HS300X_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/sensors/ioctl.h>
|
||||
|
||||
#if defined(CONFIG_I2C) && defined(CONFIG_HS300X_I2C)
|
||||
|
||||
/* HS300X Registers frequency and addresses*/
|
||||
|
||||
#ifndef CONFIG_HS300X_I2C_FREQUENCY
|
||||
# define CONFIG_HS300X_I2C_FREQUENCY 400000
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SENSOR_DEVICE_HS300X_I2C_ADDR
|
||||
# define CONFIG_SENSOR_DEVICE_HS300X_I2C_ADDR 0x44
|
||||
#endif
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
struct i2c_master_s;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: hs300x_register
|
||||
*
|
||||
* Description:
|
||||
* Register the HS300x character device as 'devpath'
|
||||
*
|
||||
* Input Parameters:
|
||||
* devpath - The full path to the driver to register. E.g., "/dev/i2c1"
|
||||
* i2c - An instance of the I2C interface to use to communicate with HS300X
|
||||
* addr - The I2C address of the HS300x. The base I2C address of the HS300X
|
||||
* is 0x44.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int hs300x_register(FAR const char *devpath, FAR struct i2c_master_s *i2c,
|
||||
uint8_t addr);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_I2C && CONFIG_HS300X_I2C */
|
||||
#endif /* __INCLUDE_NUTTX_SENSORS_HS300X_H */
|
||||
@@ -0,0 +1,643 @@
|
||||
############################################################################
|
||||
# tools/Makefile.unix
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
export TOPDIR := ${shell echo $(CURDIR) | sed -e 's/ /\\ /g'}
|
||||
include $(TOPDIR)/Make.defs
|
||||
|
||||
# GIT directory present
|
||||
|
||||
GIT_DIR = $(if $(wildcard $(TOPDIR)$(DELIM).git),y,)
|
||||
|
||||
ifeq ($(GIT_DIR),y)
|
||||
GIT_PRESENT = `git rev-parse --git-dir 2> /dev/null`
|
||||
endif
|
||||
|
||||
# In case we cannot get version information from GIT
|
||||
|
||||
ifeq ($(GIT_PRESENT),)
|
||||
-include $(TOPDIR)/.version
|
||||
|
||||
# In case the version file does not exist
|
||||
|
||||
CONFIG_VERSION_STRING ?= "0.0.0"
|
||||
CONFIG_VERSION_BUILD ?= "0"
|
||||
|
||||
VERSION_ARG = -v $(CONFIG_VERSION_STRING) -b $(CONFIG_VERSION_BUILD)
|
||||
else
|
||||
|
||||
# Generate .version every time from GIT history
|
||||
|
||||
.PHONY: $(TOPDIR)/.version
|
||||
endif
|
||||
|
||||
# Process architecture specific directories
|
||||
|
||||
ARCH_DIR = arch/$(CONFIG_ARCH)
|
||||
ARCH_SRC = $(ARCH_DIR)/src
|
||||
ARCH_INC = $(ARCH_DIR)/include
|
||||
|
||||
export APPPATHS = -I$(APPDIR)/../../../APP_Framework/Framework/sensor
|
||||
APPPATHS += -I$(APPDIR)/../../../APP_Framework/Framework/connection
|
||||
APPPATHS += -I$(APPDIR)/../../../APP_Framework/Framework/connection/zigbee
|
||||
APPPATHS += -I$(APPDIR)/../../../APP_Framework/Framework/connection/zigbee/e18
|
||||
APPPATHS += -I$(APPDIR)/../../../APP_Framework/Applications/general_functions/list
|
||||
APPPATHS += -I$(APPDIR)/../../../APP_Framework/Framework/transform_layer/nuttx
|
||||
|
||||
export SRC_APP_DIR = ../../../APP_Framework
|
||||
|
||||
# CONFIG_APPS_DIR can be over-ridden from the command line or in the .config file.
|
||||
# The default value of CONFIG_APPS_DIR is ../apps. Ultimately, the application
|
||||
# will be built if APPDIR is defined. APPDIR will be defined if a directory containing
|
||||
# a Makefile is found at the path provided by CONFIG_APPS_DIR
|
||||
|
||||
ifeq ($(CONFIG_APPS_DIR),)
|
||||
CONFIG_APPS_DIR = ../apps
|
||||
endif
|
||||
APPDIR := $(realpath ${shell if [ -r $(CONFIG_APPS_DIR)/Makefile ]; then echo "$(CONFIG_APPS_DIR)"; fi})
|
||||
|
||||
# External code support
|
||||
# If external/ contains a Kconfig, we define the EXTERNALDIR variable to 'external'
|
||||
# so that main Kconfig can find it. Otherwise, we redirect it to a dummy Kconfig
|
||||
# This is due to kconfig inability to do conditional inclusion.
|
||||
|
||||
EXTERNALDIR := $(shell if [ -r $(TOPDIR)/external/Kconfig ]; then echo 'external'; else echo 'dummy'; fi)
|
||||
|
||||
# CONTEXTDIRS include directories that have special, one-time pre-build
|
||||
# requirements. Normally this includes things like auto-generation of
|
||||
# configuration specific files or creation of configurable symbolic links
|
||||
# CLEANDIRS are the directories that the clean target will executed in.
|
||||
# These are all directories that we know about.
|
||||
# CCLEANDIRS are directories that the clean_context target will execute in.
|
||||
# The clean_context target "undoes" the actions of the context target.
|
||||
# Only directories known to require cleaning are included.
|
||||
# KERNDEPDIRS are the directories in which we will build target dependencies.
|
||||
# If NuttX and applications are built separately (CONFIG_BUILD_PROTECTED or
|
||||
# CONFIG_BUILD_KERNEL), then this holds only the directories containing
|
||||
# kernel files.
|
||||
# USERDEPDIRS. If NuttX and applications are built separately (CONFIG_BUILD_PROTECTED),
|
||||
# then this holds only the directories containing user files. If
|
||||
# CONFIG_BUILD_KERNEL is selected, then applications are not build at all.
|
||||
|
||||
include tools/Directories.mk
|
||||
|
||||
#
|
||||
# Extra objects used in the final link.
|
||||
#
|
||||
# Pass 1 Incremental (relative) link objects should be put into the
|
||||
# processor-specific source directory (where other link objects will
|
||||
# be created). If the pass1 object is an archive, it could go anywhere.
|
||||
|
||||
ifeq ($(CONFIG_BUILD_2PASS),y)
|
||||
EXTRA_OBJS += $(CONFIG_PASS1_OBJECT)
|
||||
endif
|
||||
|
||||
# Library build selections
|
||||
#
|
||||
# NUTTXLIBS is the list of NuttX libraries that is passed to the
|
||||
# processor-specific Makefile to build the final NuttX target.
|
||||
# USERLIBS is the list of libraries used to build the final user-space
|
||||
# application
|
||||
# EXPORTLIBS is the list of libraries that should be exported by
|
||||
# 'make export' is
|
||||
|
||||
ifeq ($(CONFIG_BUILD_PROTECTED),y)
|
||||
include tools/ProtectedLibs.mk
|
||||
else ifeq ($(CONFIG_BUILD_KERNEL),y)
|
||||
include tools/KernelLibs.mk
|
||||
else
|
||||
include tools/FlatLibs.mk
|
||||
endif
|
||||
|
||||
# LINKLIBS derives from NUTTXLIBS and is simply the same list with the
|
||||
# subdirectory removed
|
||||
|
||||
LINKLIBS = $(patsubst staging/%,%,$(NUTTXLIBS))
|
||||
|
||||
# Export tool definitions
|
||||
|
||||
MKEXPORT= tools/mkexport.sh
|
||||
MKEXPORT_ARGS = -t "$(TOPDIR)" -b "$(BOARD_DIR)"
|
||||
|
||||
ifneq ($(CONFIG_BUILD_FLAT),y)
|
||||
MKEXPORT_ARGS += -u
|
||||
endif
|
||||
|
||||
ifneq ($(APPDIR),)
|
||||
ifneq ($(shell [ -e $(APPDIR)/Makefile ] && echo yes),)
|
||||
MKEXPORT_ARGS += -a "$(APPDIR)"
|
||||
MKEXPORT_ARGS += -m "$(MAKE)"
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(V),2)
|
||||
MKEXPORT_ARGS += -d
|
||||
endif
|
||||
|
||||
# This is the name of the final target (relative to the top level directory)
|
||||
|
||||
BIN = nuttx$(EXEEXT)
|
||||
|
||||
all: $(BIN)
|
||||
.PHONY: dirlinks context clean_context config oldconfig menuconfig nconfig qconfig gconfig export subdir_clean clean subdir_distclean distclean apps_clean apps_distclean
|
||||
.PHONY: pass1 pass1dep
|
||||
.PHONY: pass2 pass2dep
|
||||
|
||||
# Target used to copy include/nuttx/lib/math.h. If CONFIG_ARCH_MATH_H is
|
||||
# defined, then there is an architecture specific math.h header file
|
||||
# that will be included indirectly from include/math.h. But first, we
|
||||
# have to copy math.h from include/nuttx/. to include/. Logic within
|
||||
# include/nuttx/lib/math.h will hand the redirection to the architecture-
|
||||
# specific math.h header file.
|
||||
#
|
||||
# If the CONFIG_LIBM is defined, the Rhombus libm will be built at libc/math.
|
||||
# Definitions and prototypes for the Rhombus libm are also contained in
|
||||
# include/nuttx/lib/math.h and so the file must also be copied in that case.
|
||||
#
|
||||
# If neither CONFIG_ARCH_MATH_H nor CONFIG_LIBM is defined, then no math.h
|
||||
# header file will be provided. You would want that behavior if (1) you
|
||||
# don't use libm, or (2) you want to use the math.h and libm provided
|
||||
# within your toolchain.
|
||||
|
||||
ifeq ($(CONFIG_ARCH_MATH_H),y)
|
||||
NEED_MATH_H = y
|
||||
else ifeq ($(CONFIG_LIBM),y)
|
||||
NEED_MATH_H = y
|
||||
endif
|
||||
|
||||
ifeq ($(NEED_MATH_H),y)
|
||||
include/math.h: include/nuttx/lib/math.h .clean_context
|
||||
$(Q) cp -f include/nuttx/lib/math.h include/math.h
|
||||
else
|
||||
include/math.h:
|
||||
endif
|
||||
|
||||
# The float.h header file defines the properties of your floating point
|
||||
# implementation. It would always be best to use your toolchain's float.h
|
||||
# header file but if none is available, a default float.h header file will
|
||||
# provided if this option is selected. However there is no assurance that
|
||||
# the settings in this float.h are actually correct for your platform!
|
||||
|
||||
ifeq ($(CONFIG_ARCH_FLOAT_H),y)
|
||||
include/float.h: include/nuttx/lib/float.h .clean_context
|
||||
$(Q) cp -f include/nuttx/lib/float.h include/float.h
|
||||
else
|
||||
include/float.h:
|
||||
endif
|
||||
|
||||
# Target used to copy include/nuttx/lib/stdarg.h. If CONFIG_ARCH_STDARG_H is
|
||||
# defined, then there is an architecture specific stdarg.h header file
|
||||
# that will be included indirectly from include/lib/stdarg.h. But first, we
|
||||
# have to copy stdarg.h from include/nuttx/. to include/.
|
||||
|
||||
ifeq ($(CONFIG_ARCH_STDARG_H),y)
|
||||
include/stdarg.h: include/nuttx/lib/stdarg.h .clean_context
|
||||
$(Q) cp -f include/nuttx/lib/stdarg.h include/stdarg.h
|
||||
else
|
||||
include/stdarg.h:
|
||||
endif
|
||||
|
||||
# Target used to copy include/nuttx/lib/setjmp.h. If CONFIG_ARCH_SETJMP_H is
|
||||
# defined, then there is an architecture specific setjmp.h header file
|
||||
# that will be included indirectly from include/lib/setjmp.h. But first, we
|
||||
# have to copy setjmp.h from include/nuttx/. to include/.
|
||||
|
||||
ifeq ($(CONFIG_ARCH_SETJMP_H),y)
|
||||
include/setjmp.h: include/nuttx/lib/setjmp.h .clean_context
|
||||
$(Q) cp -f include/nuttx/lib/setjmp.h include/setjmp.h
|
||||
else
|
||||
include/setjmp.h:
|
||||
endif
|
||||
|
||||
# Targets used to build include/nuttx/version.h. Creation of version.h is
|
||||
# part of the overall NuttX configuration sequence. Notice that the
|
||||
# tools/mkversion tool is built and used to create include/nuttx/version.h
|
||||
|
||||
tools/mkversion$(HOSTEXEEXT):
|
||||
$(Q) $(MAKE) -C tools -f Makefile.host mkversion$(HOSTEXEEXT)
|
||||
|
||||
# [Re-]create .version if it doesn't already exist.
|
||||
|
||||
$(TOPDIR)/.version:
|
||||
$(Q) echo "Create .version"
|
||||
$(Q) tools/version.sh $(VERSION_ARG) .version
|
||||
$(Q) chmod 755 .version
|
||||
|
||||
include/nuttx/version.h: $(TOPDIR)/.version tools/mkversion$(HOSTEXEEXT) .clean_context
|
||||
$(Q) echo "Create version.h"
|
||||
$(Q) tools/mkversion $(TOPDIR) > $@.tmp
|
||||
$(Q) $(call TESTANDREPLACEFILE, $@.tmp, $@)
|
||||
|
||||
# Targets used to build include/nuttx/config.h. Creation of config.h is
|
||||
# part of the overall NuttX configuration sequence. Notice that the
|
||||
# tools/mkconfig tool is built and used to create include/nuttx/config.h
|
||||
|
||||
tools/mkconfig$(HOSTEXEEXT):
|
||||
$(Q) $(MAKE) -C tools -f Makefile.host mkconfig$(HOSTEXEEXT)
|
||||
|
||||
include/nuttx/config.h: $(TOPDIR)/.config tools/mkconfig$(HOSTEXEEXT) .clean_context
|
||||
$(Q) tools/mkconfig $(TOPDIR) > $@.tmp
|
||||
$(Q) $(call TESTANDREPLACEFILE, $@.tmp, $@)
|
||||
|
||||
# Targets used to create dependencies
|
||||
|
||||
tools/mkdeps$(HOSTEXEEXT):
|
||||
$(Q) $(MAKE) -C tools -f Makefile.host mkdeps$(HOSTEXEEXT)
|
||||
|
||||
tools/cnvwindeps$(HOSTEXEEXT):
|
||||
$(Q) $(MAKE) -C tools -f Makefile.host cnvwindeps$(HOSTEXEEXT)
|
||||
|
||||
# dirlinks, and helpers
|
||||
#
|
||||
# Directories links. Most of establishing the NuttX configuration involves
|
||||
# setting up symbolic links with 'generic' directory names to specific,
|
||||
# configured directories.
|
||||
|
||||
# Link the arch/<arch-name>/include directory to include/arch
|
||||
|
||||
include/arch: .clean_context
|
||||
@echo "LN: include/arch to $(ARCH_DIR)/include"
|
||||
$(Q) $(DIRLINK) $(TOPDIR)/$(ARCH_DIR)/include include/arch
|
||||
$(Q) touch $@
|
||||
|
||||
# Link the boards/<arch>/<chip>/<board>/include directory to include/arch/board
|
||||
|
||||
include/arch/board: include/arch
|
||||
@echo "LN: include/arch/board to $(BOARD_DIR)/include"
|
||||
$(Q) $(DIRLINK) $(BOARD_DIR)/include include/arch/board
|
||||
$(Q) touch $@
|
||||
|
||||
ifneq ($(BOARD_COMMON_DIR),)
|
||||
# Link the boards/<arch>/<chip>/common dir to arch/<arch-name>/src/board
|
||||
# Link the boards/<arch>/<chip>/<board>/src dir to arch/<arch-name>/src/board/board
|
||||
|
||||
$(ARCH_SRC)/board: .clean_context
|
||||
@echo "LN: $(ARCH_SRC)/board to $(BOARD_COMMON_DIR)"
|
||||
$(Q) $(DIRLINK) $(BOARD_COMMON_DIR) $(ARCH_SRC)/board
|
||||
@echo "LN: $(ARCH_SRC)/board/board to $(BOARD_DIR)/src"
|
||||
$(Q) $(DIRLINK) $(BOARD_DIR)/src $(ARCH_SRC)/board/board
|
||||
$(Q) touch $@
|
||||
else
|
||||
# Link the boards/<arch>/<chip>/<board>/src dir to arch/<arch-name>/src/board
|
||||
|
||||
$(ARCH_SRC)/board: .clean_context
|
||||
@echo "LN: $(ARCH_SRC)/board to $(BOARD_DIR)/src"
|
||||
$(Q) $(DIRLINK) $(BOARD_DIR)/src $(ARCH_SRC)/board
|
||||
$(Q) touch $@
|
||||
endif
|
||||
|
||||
# Link the boards/<arch>/<chip>/drivers dir to drivers/platform
|
||||
|
||||
drivers/platform: .clean_context
|
||||
@echo "LN: $(TOPDIR)/drivers/platform to $(BOARD_DRIVERS_DIR)"
|
||||
$(Q) $(DIRLINK) $(BOARD_DRIVERS_DIR) $(TOPDIR)/drivers/platform
|
||||
$(Q) touch $@
|
||||
|
||||
# Link arch/<arch-name>/src/<chip-name> to arch/<arch-name>/src/chip
|
||||
|
||||
$(ARCH_SRC)/chip: .clean_context
|
||||
ifeq ($(CONFIG_ARCH_CHIP_CUSTOM),y)
|
||||
@echo "LN: $(ARCH_SRC)/chip to $(CHIP_DIR)"
|
||||
$(Q) $(DIRLINK) $(CHIP_DIR) $(ARCH_SRC)/chip
|
||||
else ifneq ($(CONFIG_ARCH_CHIP),)
|
||||
@echo "LN: $(ARCH_SRC)/chip to $(ARCH_SRC)/$(CONFIG_ARCH_CHIP)"
|
||||
$(Q) $(DIRLINK) $(TOPDIR)/$(ARCH_SRC)/$(CONFIG_ARCH_CHIP) $(ARCH_SRC)/chip
|
||||
endif
|
||||
$(Q) cp -f $(CHIP_KCONFIG) $(TOPDIR)/arch/dummy/Kconfig
|
||||
$(Q) touch $@
|
||||
|
||||
# Link arch/<arch-name>/include/<chip-name> to include/arch/chip
|
||||
|
||||
include/arch/chip: include/arch
|
||||
ifeq ($(CONFIG_ARCH_CHIP_CUSTOM),y)
|
||||
@echo "LN: include/arch/chip to $(CHIP_DIR)/include"
|
||||
$(Q) $(DIRLINK) $(CHIP_DIR)/include include/arch/chip
|
||||
else ifneq ($(CONFIG_ARCH_CHIP),)
|
||||
@echo "LN: include/arch/chip to $(ARCH_INC)/$(CONFIG_ARCH_CHIP)"
|
||||
$(Q) $(DIRLINK) $(TOPDIR)/$(ARCH_INC)/$(CONFIG_ARCH_CHIP) include/arch/chip
|
||||
endif
|
||||
$(Q) touch $@
|
||||
|
||||
dirlinks: include/arch include/arch/board include/arch/chip $(ARCH_SRC)/board $(ARCH_SRC)/chip drivers/platform
|
||||
$(Q) $(MAKE) -C boards dirlinks
|
||||
$(Q) $(MAKE) -C $(CONFIG_APPS_DIR) dirlinks
|
||||
|
||||
# context
|
||||
#
|
||||
# The context target is invoked on each target build to assure that NuttX is
|
||||
# properly configured. The basic configuration steps include creation of the
|
||||
# the config.h and version.h header files in the include/nuttx directory and
|
||||
# the establishment of symbolic links to configured directories.
|
||||
|
||||
context: include/nuttx/config.h include/nuttx/version.h include/math.h include/float.h include/stdarg.h include/setjmp.h dirlinks
|
||||
$(Q) mkdir -p staging
|
||||
$(Q) for dir in $(CONTEXTDIRS) ; do \
|
||||
$(MAKE) -C $$dir context || exit; \
|
||||
done
|
||||
|
||||
# clean_context
|
||||
#
|
||||
# This is part of the distclean target. It removes all of the header files
|
||||
# and symbolic links created by the context target.
|
||||
|
||||
clean_context:
|
||||
$(Q) for dir in $(CCLEANDIRS) ; do \
|
||||
if [ -e $$dir/Makefile ]; then \
|
||||
$(MAKE) -C $$dir clean_context ; \
|
||||
fi \
|
||||
done
|
||||
$(call DELFILE, include/nuttx/config.h)
|
||||
$(call DELFILE, include/nuttx/version.h)
|
||||
$(call DELFILE, include/float.h)
|
||||
$(call DELFILE, include/math.h)
|
||||
$(call DELFILE, include/stdarg.h)
|
||||
$(call DELFILE, include/setjmp.h)
|
||||
$(call DELFILE, arch/dummy/Kconfig)
|
||||
$(Q) $(DIRUNLINK) include/arch/board
|
||||
$(Q) $(DIRUNLINK) include/arch/chip
|
||||
$(Q) $(DIRUNLINK) include/arch
|
||||
$(Q) $(DIRUNLINK) $(ARCH_SRC)/board/board
|
||||
$(Q) $(DIRUNLINK) $(ARCH_SRC)/board
|
||||
$(Q) $(DIRUNLINK) $(ARCH_SRC)/chip
|
||||
$(Q) $(DIRUNLINK) $(TOPDIR)/drivers/platform
|
||||
|
||||
.clean_context: .config
|
||||
+$(Q) $(MAKE) clean_context
|
||||
$(Q) touch $@
|
||||
|
||||
# Archive targets. The target build sequence will first create a series of
|
||||
# libraries, one per configured source file directory. The final NuttX
|
||||
# execution will then be built from those libraries. The following targets
|
||||
# build those libraries.
|
||||
|
||||
include tools/LibTargets.mk
|
||||
|
||||
# pass1 and pass2
|
||||
#
|
||||
# If the 2 pass build option is selected, then this pass1 target is
|
||||
# configured to be built before the pass2 target. This pass1 target may, as an
|
||||
# example, build an extra link object (CONFIG_PASS1_OBJECT) which may be an
|
||||
# incremental (relative) link object, but could be a static library (archive);
|
||||
# some modification to this Makefile would be required if CONFIG_PASS1_OBJECT
|
||||
# is an archive. Exactly what is performed during pass1 or what it generates
|
||||
# is unknown to this makefile unless CONFIG_PASS1_OBJECT is defined.
|
||||
|
||||
pass1: $(USERLIBS)
|
||||
|
||||
pass2: $(NUTTXLIBS)
|
||||
|
||||
# $(BIN)
|
||||
#
|
||||
# Create the final NuttX executable in a two pass build process. In the
|
||||
# normal case, all pass1 and pass2 dependencies are created then pass1
|
||||
# and pass2 targets are built. However, in some cases, you may need to build
|
||||
# pass1 dependencies and pass1 first, then build pass2 dependencies and pass2.
|
||||
# in that case, execute 'make pass1 pass2' from the command line.
|
||||
|
||||
$(BIN): pass1 pass2
|
||||
ifeq ($(CONFIG_BUILD_2PASS),y)
|
||||
$(Q) if [ -z "$(CONFIG_PASS1_BUILDIR)" ]; then \
|
||||
echo "ERROR: CONFIG_PASS1_BUILDIR not defined"; \
|
||||
exit 1; \
|
||||
fi
|
||||
$(Q) if [ ! -d "$(CONFIG_PASS1_BUILDIR)" ]; then \
|
||||
echo "ERROR: CONFIG_PASS1_BUILDIR does not exist"; \
|
||||
exit 1; \
|
||||
fi
|
||||
$(Q) if [ ! -f "$(CONFIG_PASS1_BUILDIR)/Makefile" ]; then \
|
||||
echo "ERROR: No Makefile in CONFIG_PASS1_BUILDIR"; \
|
||||
exit 1; \
|
||||
fi
|
||||
$(Q) $(MAKE) -C $(CONFIG_PASS1_BUILDIR) LINKLIBS="$(LINKLIBS)" USERLIBS="$(USERLIBS)" "$(CONFIG_PASS1_TARGET)"
|
||||
endif
|
||||
$(Q) $(MAKE) -C $(ARCH_SRC) EXTRA_OBJS="$(EXTRA_OBJS)" LINKLIBS="$(LINKLIBS)" EXTRAFLAGS="$(KDEFINE) $(EXTRAFLAGS)" $(BIN)
|
||||
$(Q) if [ -w /tftpboot ] ; then \
|
||||
cp -f $(BIN) /tftpboot/$(BIN).${CONFIG_ARCH}; \
|
||||
fi
|
||||
$(Q) echo $(BIN) > nuttx.manifest
|
||||
$(Q) printf "%s\n" *.map >> nuttx.manifest
|
||||
ifeq ($(CONFIG_INTELHEX_BINARY),y)
|
||||
@echo "CP: nuttx.hex"
|
||||
$(Q) $(OBJCOPY) $(OBJCOPYARGS) -O ihex $(BIN) nuttx.hex
|
||||
$(Q) echo nuttx.hex >> nuttx.manifest
|
||||
endif
|
||||
ifeq ($(CONFIG_MOTOROLA_SREC),y)
|
||||
@echo "CP: nuttx.srec"
|
||||
$(Q) $(OBJCOPY) $(OBJCOPYARGS) -O srec $(BIN) nuttx.srec
|
||||
$(Q) echo nuttx.srec >> nuttx.manifest
|
||||
endif
|
||||
ifeq ($(CONFIG_RAW_BINARY),y)
|
||||
@echo "CP: nuttx.bin"
|
||||
$(Q) $(OBJCOPY) $(OBJCOPYARGS) -O binary $(BIN) nuttx.bin
|
||||
$(Q) echo nuttx.bin >> nuttx.manifest
|
||||
endif
|
||||
ifeq ($(CONFIG_UBOOT_UIMAGE),y)
|
||||
@echo "MKIMAGE: uImage"
|
||||
$(Q) mkimage -A $(CONFIG_ARCH) -O linux -C none -T kernel -a $(CONFIG_UIMAGE_LOAD_ADDRESS) \
|
||||
-e $(CONFIG_UIMAGE_ENTRY_POINT) -n $(BIN) -d nuttx.bin uImage
|
||||
$(Q) if [ -w /tftpboot ] ; then \
|
||||
cp -f uImage /tftpboot/uImage; \
|
||||
fi
|
||||
$(Q) echo "uImage" >> nuttx.manifest
|
||||
endif
|
||||
$(call POSTBUILD, $(TOPDIR))
|
||||
|
||||
# download
|
||||
#
|
||||
# This is a helper target that will rebuild NuttX and download it to the target
|
||||
# system in one step. The operation of this target depends completely upon
|
||||
# implementation of the DOWNLOAD command in the user Make.defs file. It will
|
||||
# generate an error if the DOWNLOAD command is not defined.
|
||||
|
||||
download: $(BIN)
|
||||
$(call DOWNLOAD, $<)
|
||||
|
||||
# bootloader
|
||||
#
|
||||
# Some architectures require the provisioning of a bootloader or other
|
||||
# functions required for properly executing the NuttX binary.
|
||||
# Make.defs files for those architectures should define a bootloader target
|
||||
# with the correct operations for that platform. It will generate an error
|
||||
# if the bootloader target is not defined.
|
||||
|
||||
bootloader:
|
||||
$(Q) $(MAKE) -C $(ARCH_SRC) bootloader
|
||||
|
||||
# clean_bootloader
|
||||
#
|
||||
# Removes all of the files and directories created by the bootloader target.
|
||||
# It will generate an error if the clean_bootloader target is not defined on
|
||||
# the architecture-specific Makefile.
|
||||
|
||||
clean_bootloader:
|
||||
$(Q) $(MAKE) -C $(ARCH_SRC) clean_bootloader
|
||||
|
||||
# pass1dep: Create pass1 build dependencies
|
||||
# pass2dep: Create pass2 build dependencies
|
||||
|
||||
pass1dep: context tools/mkdeps$(HOSTEXEEXT) tools/cnvwindeps$(HOSTEXEEXT)
|
||||
$(Q) for dir in $(USERDEPDIRS) ; do \
|
||||
$(MAKE) -C $$dir depend || exit; \
|
||||
done
|
||||
|
||||
pass2dep: context tools/mkdeps$(HOSTEXEEXT) tools/cnvwindeps$(HOSTEXEEXT)
|
||||
$(Q) for dir in $(KERNDEPDIRS) ; do \
|
||||
$(MAKE) -C $$dir EXTRAFLAGS="$(KDEFINE) $(EXTRAFLAGS)" depend || exit; \
|
||||
done
|
||||
|
||||
# Configuration targets
|
||||
#
|
||||
# These targets depend on the kconfig-frontends packages. To use these, you
|
||||
# must first download and install the kconfig-frontends package from this
|
||||
# location: https://bitbucket.org/nuttx/tools/downloads/. See README.txt
|
||||
# file in the NuttX tools GIT repository for additional information.
|
||||
|
||||
config: apps_preconfig
|
||||
$(Q) APPSDIR=${CONFIG_APPS_DIR} EXTERNALDIR=$(EXTERNALDIR) kconfig-conf Kconfig
|
||||
|
||||
oldconfig: apps_preconfig
|
||||
$(Q) APPSDIR=${CONFIG_APPS_DIR} EXTERNALDIR=$(EXTERNALDIR) kconfig-conf --oldconfig Kconfig
|
||||
|
||||
olddefconfig: apps_preconfig
|
||||
$(Q) APPSDIR=${CONFIG_APPS_DIR} EXTERNALDIR=$(EXTERNALDIR) kconfig-conf --olddefconfig Kconfig
|
||||
|
||||
menuconfig: apps_preconfig
|
||||
$(Q) APPSDIR=${CONFIG_APPS_DIR} EXTERNALDIR=$(EXTERNALDIR) kconfig-mconf Kconfig
|
||||
|
||||
nconfig: apps_preconfig
|
||||
$(Q) APPSDIR=${CONFIG_APPS_DIR} EXTERNALDIR=$(EXTERNALDIR) kconfig-nconf Kconfig
|
||||
|
||||
qconfig: apps_preconfig
|
||||
$(Q) APPSDIR=${CONFIG_APPS_DIR} EXTERNALDIR=$(EXTERNALDIR) kconfig-qconf Kconfig
|
||||
|
||||
gconfig: apps_preconfig
|
||||
$(Q) APPSDIR=${CONFIG_APPS_DIR} EXTERNALDIR=$(EXTERNALDIR) kconfig-gconf Kconfig
|
||||
|
||||
savedefconfig: apps_preconfig
|
||||
$(Q) APPSDIR=${CONFIG_APPS_DIR} EXTERNALDIR=$(EXTERNALDIR) kconfig-conf --savedefconfig defconfig.tmp Kconfig
|
||||
$(Q) kconfig-tweak --file defconfig.tmp -u CONFIG_APPS_DIR
|
||||
$(Q) grep "CONFIG_ARCH=" .config >> defconfig.tmp
|
||||
$(Q) grep "^CONFIG_ARCH_CHIP_" .config >> defconfig.tmp; true
|
||||
$(Q) grep "CONFIG_ARCH_CHIP=" .config >> defconfig.tmp; true
|
||||
$(Q) grep "CONFIG_ARCH_BOARD=" .config >> defconfig.tmp; true
|
||||
$(Q) grep "^CONFIG_ARCH_CUSTOM" .config >> defconfig.tmp; true
|
||||
$(Q) grep "^CONFIG_ARCH_BOARD_CUSTOM" .config >> defconfig.tmp; true
|
||||
$(Q) export LC_ALL=C; cat defconfig.tmp | sort | uniq > sortedconfig.tmp
|
||||
$(Q) echo "#" > warning.tmp
|
||||
$(Q) echo "# This file is autogenerated: PLEASE DO NOT EDIT IT." >> warning.tmp
|
||||
$(Q) echo "#" >> warning.tmp
|
||||
$(Q) echo "# You can use \"make menuconfig\" to make any modifications to the installed .config file." >> warning.tmp
|
||||
$(Q) echo "# You can then do \"make savedefconfig\" to generate a new defconfig file that includes your" >> warning.tmp
|
||||
$(Q) echo "# modifications." >> warning.tmp
|
||||
$(Q) echo "#" >> warning.tmp
|
||||
$(Q) cat warning.tmp sortedconfig.tmp > defconfig
|
||||
$(Q) rm -f warning.tmp
|
||||
$(Q) rm -f defconfig.tmp
|
||||
$(Q) rm -f sortedconfig.tmp
|
||||
|
||||
# export
|
||||
#
|
||||
# The export target will package the NuttX libraries and header files into
|
||||
# an exportable package. Caveats: (1) These needs some extension for the KERNEL
|
||||
# build; it needs to receive USERLIBS and create a libuser.a). (2) The logic
|
||||
# in tools/mkexport.sh only supports GCC and, for example, explicitly assumes
|
||||
# that the archiver is 'ar'
|
||||
|
||||
export: $(NUTTXLIBS)
|
||||
$(Q) MAKE=${MAKE} $(MKEXPORT) $(MKEXPORT_ARGS) -l "$(EXPORTLIBS)"
|
||||
|
||||
# General housekeeping targets: dependencies, cleaning, etc.
|
||||
#
|
||||
# depend: Create both PASS1 and PASS2 dependencies
|
||||
# clean: Removes derived object files, archives, executables, and
|
||||
# temporary files, but retains the configuration and context
|
||||
# files and directories.
|
||||
# distclean: Does 'clean' then also removes all configuration and context
|
||||
# files. This essentially restores the directory structure
|
||||
# to its original, unconfigured stated.
|
||||
|
||||
depend: pass1dep pass2dep
|
||||
|
||||
$(foreach SDIR, $(CLEANDIRS), $(eval $(call SDIR_template,$(SDIR),clean)))
|
||||
|
||||
subdir_clean: $(foreach SDIR, $(CLEANDIRS), $(SDIR)_clean)
|
||||
ifeq ($(CONFIG_BUILD_2PASS),y)
|
||||
$(Q) $(MAKE) -C $(CONFIG_PASS1_BUILDIR) clean
|
||||
endif
|
||||
|
||||
clean: subdir_clean
|
||||
$(call DELFILE, $(BIN))
|
||||
$(call DELFILE, nuttx.*)
|
||||
$(call DELFILE, *.map)
|
||||
$(call DELFILE, _SAVED_APPS_config)
|
||||
$(call DELFILE, nuttx-export*.zip)
|
||||
$(call DELDIR, nuttx-export*)
|
||||
$(call DELFILE, nuttx_user*)
|
||||
$(call DELDIR, staging)
|
||||
$(call DELFILE, uImage)
|
||||
$(call CLEAN)
|
||||
|
||||
$(foreach SDIR, $(CLEANDIRS), $(eval $(call SDIR_template,$(SDIR),distclean)))
|
||||
|
||||
subdir_distclean: $(foreach SDIR, $(CLEANDIRS), $(SDIR)_distclean)
|
||||
|
||||
distclean: clean subdir_distclean
|
||||
ifeq ($(CONFIG_BUILD_2PASS),y)
|
||||
$(Q) $(MAKE) -C $(CONFIG_PASS1_BUILDIR) distclean
|
||||
endif
|
||||
ifeq ($(CONFIG_ARCH_HAVE_BOOTLOADER),y)
|
||||
$(Q) $(MAKE) clean_bootloader
|
||||
endif
|
||||
$(Q) $(MAKE) clean_context
|
||||
$(call DELFILE, Make.defs)
|
||||
$(call DELFILE, defconfig)
|
||||
$(call DELFILE, .config)
|
||||
$(call DELFILE, .config.old)
|
||||
$(call DELFILE, .gdbinit)
|
||||
$(call DELFILE, .clean_context)
|
||||
$(Q) $(MAKE) -C tools -f Makefile.host clean
|
||||
|
||||
# Application housekeeping targets. The APPDIR variable refers to the user
|
||||
# application directory. A sample apps/ directory is included with NuttX,
|
||||
# however, this is not treated as part of NuttX and may be replaced with a
|
||||
# different application directory. For the most part, the application
|
||||
# directory is treated like any other build directory in this script. However,
|
||||
# as a convenience, the following targets are included to support housekeeping
|
||||
# functions in the user application directory from the NuttX build directory.
|
||||
#
|
||||
# apps_preconfig: Prepare applications to be configured
|
||||
# apps_clean: Perform the clean operation only in the user application
|
||||
# directory
|
||||
# apps_distclean: Perform the distclean operation only in the user application
|
||||
# directory.
|
||||
|
||||
apps_preconfig: dirlinks
|
||||
ifneq ($(APPDIR),)
|
||||
$(Q) $(MAKE) -C $(APPDIR) preconfig
|
||||
endif
|
||||
|
||||
apps_clean:
|
||||
ifneq ($(APPDIR),)
|
||||
$(Q) $(MAKE) -C $(APPDIR) clean
|
||||
endif
|
||||
|
||||
apps_distclean:
|
||||
ifneq ($(APPDIR),)
|
||||
$(Q) $(MAKE) -C $(APPDIR) distclean
|
||||
endif
|
||||
@@ -0,0 +1,368 @@
|
||||
/****************************************************************************
|
||||
* tools/cfgdefine.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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file cfgdefine.c
|
||||
* @brief nuttx source code
|
||||
* https://github.com/apache/incubator-nuttx-apps
|
||||
* @version 10.2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "cfgdefine.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
char line[LINESIZE + 1];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* These are configuration variable name that are quoted by configuration
|
||||
* tool but which must be unquoted when used in C code.
|
||||
*/
|
||||
|
||||
static const char *dequote_list[] =
|
||||
{
|
||||
/* NuttX */
|
||||
|
||||
"CONFIG_DEBUG_OPTLEVEL", /* Custom debug level */
|
||||
"CONFIG_EXECFUNCS_NSYMBOLS_VAR", /* Variable holding number of symbols in the table */
|
||||
"CONFIG_EXECFUNCS_SYMTAB_ARRAY", /* Symbol table array used by exec[l|v] */
|
||||
"CONFIG_INIT_ARGS", /* Argument list of entry point */
|
||||
"CONFIG_INIT_SYMTAB", /* Global symbol table */
|
||||
"CONFIG_INIT_NEXPORTS", /* Global symbol table size */
|
||||
"CONFIG_MODLIB_SYMTAB_ARRAY", /* Symbol table array used by modlib functions */
|
||||
"CONFIG_MODLIB_NSYMBOLS_VAR", /* Variable holding number of symbols in the table */
|
||||
"CONFIG_PASS1_BUILDIR", /* Pass1 build directory */
|
||||
"CONFIG_PASS1_TARGET", /* Pass1 build target */
|
||||
"CONFIG_PASS1_OBJECT", /* Pass1 build object */
|
||||
"CONFIG_USER_ENTRYPOINT", /* Name of entry point function */
|
||||
|
||||
/* NxWidgets/NxWM */
|
||||
|
||||
"CONFIG_NXWM_BACKGROUND_IMAGE", /* Name of bitmap image class */
|
||||
"CONFIG_NXWM_CALIBRATION_ICON", /* Name of bitmap image class */
|
||||
"CONFIG_NXWM_HEXCALCULATOR_ICON", /* Name of bitmap image class */
|
||||
"CONFIG_NXWM_MINIMIZE_BITMAP", /* Name of bitmap image class */
|
||||
"CONFIG_NXWM_NXTERM_ICON", /* Name of bitmap image class */
|
||||
"CONFIG_NXWM_STARTWINDOW_ICON", /* Name of bitmap image class */
|
||||
"CONFIG_NXWM_STOP_BITMAP", /* Name of bitmap image class */
|
||||
|
||||
/* apps/ definitions */
|
||||
|
||||
"CONFIG_SYSTEM_NSH_SYMTAB_ARRAYNAME", /* Symbol table array name */
|
||||
"CONFIG_SYSTEM_NSH_SYMTAB_COUNTNAME", /* Name of the variable holding the number of symbols */
|
||||
NULL /* Marks the end of the list */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Skip over any spaces */
|
||||
|
||||
static char *skip_space(char *ptr)
|
||||
{
|
||||
while (*ptr && isspace((int)*ptr)) ptr++;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Find the end of a variable string */
|
||||
|
||||
static char *find_name_end(char *ptr)
|
||||
{
|
||||
while (*ptr && (isalnum((int)*ptr) || *ptr == '_')) ptr++;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Find the end of a value string */
|
||||
|
||||
static char *find_value_end(char *ptr)
|
||||
{
|
||||
while (*ptr && !isspace((int)*ptr))
|
||||
{
|
||||
if (*ptr == '"')
|
||||
{
|
||||
do ptr++; while (*ptr && *ptr != '"');
|
||||
if (*ptr) ptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
do ptr++; while (*ptr && !isspace((int)*ptr) && *ptr != '"');
|
||||
}
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Read the next line from the configuration file */
|
||||
|
||||
static char *read_line(FILE *stream)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
line[LINESIZE] = '\0';
|
||||
if (!fgets(line, LINESIZE, stream))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = skip_space(line);
|
||||
if (*ptr && *ptr != '#' && *ptr != '\n')
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the line from the configuration file into a variable name
|
||||
* string and a value string.
|
||||
*/
|
||||
|
||||
static void parse_line(char *ptr, char **varname, char **varval)
|
||||
{
|
||||
/* Skip over any leading spaces */
|
||||
|
||||
ptr = skip_space(ptr);
|
||||
|
||||
/* The first no-space is the beginning of the variable name */
|
||||
|
||||
*varname = skip_space(ptr);
|
||||
*varval = NULL;
|
||||
|
||||
/* Parse to the end of the variable name */
|
||||
|
||||
ptr = find_name_end(ptr);
|
||||
|
||||
/* An equal sign is expected next, perhaps after some white space */
|
||||
|
||||
if (*ptr && *ptr != '=')
|
||||
{
|
||||
/* Some else follows the variable name. Terminate the variable
|
||||
* name and skip over any spaces.
|
||||
*/
|
||||
|
||||
*ptr = '\0';
|
||||
ptr = skip_space(ptr + 1);
|
||||
}
|
||||
|
||||
/* Verify that the equal sign is present */
|
||||
|
||||
if (*ptr == '=')
|
||||
{
|
||||
/* Make sure that the variable name is terminated (this was already
|
||||
* done if the name was followed by white space.
|
||||
*/
|
||||
|
||||
*ptr = '\0';
|
||||
|
||||
/* The variable value should follow =, perhaps separated by some
|
||||
* white space.
|
||||
*/
|
||||
|
||||
ptr = skip_space(ptr + 1);
|
||||
if (*ptr)
|
||||
{
|
||||
/* Yes.. a variable follows. Save the pointer to the start
|
||||
* of the variable string.
|
||||
*/
|
||||
|
||||
*varval = ptr;
|
||||
|
||||
/* Find the end of the variable string and make sure that it
|
||||
* is terminated.
|
||||
*/
|
||||
|
||||
ptr = find_value_end(ptr);
|
||||
*ptr = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *dequote_value(const char *varname, char *varval)
|
||||
{
|
||||
const char **dqnam;
|
||||
char *dqval = varval;
|
||||
char *ptr;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
if (dqval)
|
||||
{
|
||||
/* Check if the variable name is in the dequoted list of strings */
|
||||
|
||||
for (dqnam = dequote_list; *dqnam; dqnam++)
|
||||
{
|
||||
if (strcmp(*dqnam, varname) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Did we find the variable name in the list of configuration variables
|
||||
* to be dequoted?
|
||||
*/
|
||||
|
||||
if (*dqnam)
|
||||
{
|
||||
/* Yes... Check if there is a trailing quote */
|
||||
|
||||
len = strlen(dqval);
|
||||
if (dqval[len - 1] == '"')
|
||||
{
|
||||
/* Yes... replace it with a terminator */
|
||||
|
||||
dqval[len - 1] = '\0';
|
||||
len--;
|
||||
}
|
||||
|
||||
/* Is there a leading quote? */
|
||||
|
||||
if (dqval[0] == '"')
|
||||
{
|
||||
/* Yes.. skip over the leading quote */
|
||||
|
||||
dqval++;
|
||||
len--;
|
||||
}
|
||||
|
||||
/* A special case is a quoted list of quoted strings. In that case
|
||||
* we will need to remove the backspaces from the internally quoted
|
||||
* strings. NOTE: this will not handle nested quoted quotes.
|
||||
*/
|
||||
|
||||
for (ptr = dqval; *ptr; ptr++)
|
||||
{
|
||||
/* Check for a quoted quote */
|
||||
|
||||
if (ptr[0] == '\\' && ptr[1] == '"')
|
||||
{
|
||||
/* Delete the backslash by moving the rest of the string */
|
||||
|
||||
for (i = 0; ptr[i]; i++)
|
||||
{
|
||||
ptr[i] = ptr[i + 1];
|
||||
}
|
||||
|
||||
len--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle the case where nothing is left after dequoting */
|
||||
|
||||
if (len <= 0)
|
||||
{
|
||||
dqval = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dqval;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
void generate_definitions(FILE *stream)
|
||||
{
|
||||
char *varname;
|
||||
char *varval;
|
||||
char *ptr;
|
||||
|
||||
/* Loop until the entire file has been parsed. */
|
||||
|
||||
do
|
||||
{
|
||||
/* Read the next line from the file */
|
||||
|
||||
ptr = read_line(stream);
|
||||
if (ptr)
|
||||
{
|
||||
/* Parse the line into a variable and a value field */
|
||||
|
||||
parse_line(ptr, &varname, &varval);
|
||||
|
||||
/* Was a variable name found? */
|
||||
|
||||
if (varname)
|
||||
{
|
||||
/* Yes.. dequote the value if necessary */
|
||||
|
||||
varval = dequote_value(varname, varval);
|
||||
|
||||
/* If no value was provided or if the special value 'n' was
|
||||
* provided, then undefine the configuration variable.
|
||||
*/
|
||||
|
||||
if (!varval || strcmp(varval, "n") == 0)
|
||||
{
|
||||
printf("#undef %s\n", varname);
|
||||
}
|
||||
|
||||
/* Simply define the configuration variable to '1' if it has
|
||||
* the special value "y"
|
||||
*/
|
||||
|
||||
else if (strcmp(varval, "y") == 0)
|
||||
{
|
||||
printf("#define %s 1\n", varname);
|
||||
printf("#define %s 1\n", &varname[7]);
|
||||
}
|
||||
|
||||
/* Or to '2' if it has the special value 'm' */
|
||||
|
||||
else if (strcmp(varval, "m") == 0)
|
||||
{
|
||||
printf("#define %s 2\n", varname);
|
||||
printf("#define %s 2\n", &varname[7]);
|
||||
}
|
||||
|
||||
/* Otherwise, use the value as provided */
|
||||
|
||||
else
|
||||
{
|
||||
printf("#define %s %s\n", varname, varval);
|
||||
printf("#define %s %s\n", &varname[7], varval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (ptr);
|
||||
}
|
||||
Reference in New Issue
Block a user