diff --git a/configs/stm32f103-minimum/mcp2515/Make.defs b/configs/stm32f103-minimum/mcp2515/Make.defs new file mode 100644 index 0000000000..8d3d478305 --- /dev/null +++ b/configs/stm32f103-minimum/mcp2515/Make.defs @@ -0,0 +1,113 @@ +############################################################################ +# configs/stm32f103-minimum/nsh/Make.defs +# +# Copyright (C) 2016 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# 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. +# +############################################################################ + +include ${TOPDIR}/.config +include ${TOPDIR}/tools/Config.mk +include ${TOPDIR}/arch/arm/src/armv7-m/Toolchain.defs + +LDSCRIPT = ld.script + +ifeq ($(WINTOOL),y) + # Windows-native toolchains + DIRLINK = $(TOPDIR)/tools/copydir.sh + DIRUNLINK = $(TOPDIR)/tools/unlink.sh + MKDEP = $(TOPDIR)/tools/mkwindeps.sh + ARCHINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" + ARCHXXINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" -isystem "${shell cygpath -w $(TOPDIR)/include/cxx}" + ARCHSCRIPT = -T "${shell cygpath -w $(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/scripts/$(LDSCRIPT)}" +else + # Linux/Cygwin-native toolchain + MKDEP = $(TOPDIR)/tools/mkdeps$(HOSTEXEEXT) + ARCHINCLUDES = -I. -isystem $(TOPDIR)/include + ARCHXXINCLUDES = -I. -isystem $(TOPDIR)/include -isystem $(TOPDIR)/include/cxx + ARCHSCRIPT = -T$(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/scripts/$(LDSCRIPT) +endif + +CC = $(CROSSDEV)gcc +CXX = $(CROSSDEV)g++ +CPP = $(CROSSDEV)gcc -E +LD = $(CROSSDEV)ld +AR = $(CROSSDEV)ar rcs +NM = $(CROSSDEV)nm +OBJCOPY = $(CROSSDEV)objcopy +OBJDUMP = $(CROSSDEV)objdump + +ARCHCCVERSION = ${shell $(CC) -v 2>&1 | sed -n '/^gcc version/p' | sed -e 's/^gcc version \([0-9\.]\)/\1/g' -e 's/[-\ ].*//g' -e '1q'} +ARCHCCMAJOR = ${shell echo $(ARCHCCVERSION) | cut -d'.' -f1} + +ifeq ($(CONFIG_DEBUG_SYMBOLS),y) + ARCHOPTIMIZATION = -g +endif + +ifneq ($(CONFIG_DEBUG_NOOPT),y) + ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointer +endif + +ARCHCFLAGS = -fno-builtin +ARCHCXXFLAGS = -fno-builtin -fno-exceptions -fcheck-new +ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef +ARCHWARNINGSXX = -Wall -Wshadow -Wundef +ARCHDEFINES = +ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10 + +CFLAGS = $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) +CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS = $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) +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 + +ASMEXT = .S +OBJEXT = .o +LIBEXT = .a +EXEEXT = + +ifneq ($(CROSSDEV),arm-nuttx-elf-) + LDFLAGS += -nostartfiles -nodefaultlibs +endif +ifeq ($(CONFIG_DEBUG_SYMBOLS),y) + LDFLAGS += -g +endif + + +HOSTCC = gcc +HOSTINCLUDES = -I. +HOSTCFLAGS = -Wall -Wstrict-prototypes -Wshadow -Wundef -g -pipe +HOSTLDFLAGS = + diff --git a/configs/stm32f103-minimum/mcp2515/defconfig b/configs/stm32f103-minimum/mcp2515/defconfig new file mode 100644 index 0000000000..eaada4d3dc --- /dev/null +++ b/configs/stm32f103-minimum/mcp2515/defconfig @@ -0,0 +1,1345 @@ +# +# Automatically generated file; DO NOT EDIT. +# Nuttx/ Configuration +# + +# +# Build Setup +# +# CONFIG_EXPERIMENTAL is not set +CONFIG_DEFAULT_SMALL=y +CONFIG_HOST_LINUX=y +# CONFIG_HOST_OSX is not set +# CONFIG_HOST_WINDOWS is not set +# CONFIG_HOST_OTHER is not set + +# +# Build Configuration +# +# CONFIG_APPS_DIR="../apps" +CONFIG_BUILD_FLAT=y +# CONFIG_BUILD_2PASS is not set + +# +# Binary Output Formats +# +# CONFIG_RRLOAD_BINARY is not set +# CONFIG_INTELHEX_BINARY is not set +# CONFIG_MOTOROLA_SREC is not set +CONFIG_RAW_BINARY=y +# CONFIG_UBOOT_UIMAGE is not set +# CONFIG_DFU_BINARY is not set + +# +# Customize Header Files +# +# CONFIG_ARCH_STDINT_H is not set +# CONFIG_ARCH_STDBOOL_H is not set +# CONFIG_ARCH_MATH_H is not set +# CONFIG_ARCH_FLOAT_H is not set +# CONFIG_ARCH_STDARG_H is not set +# CONFIG_ARCH_DEBUG_H is not set + +# +# Debug Options +# +CONFIG_DEBUG_ALERT=y +CONFIG_DEBUG_FEATURES=y + +# +# Debug SYSLOG Output Controls +# +CONFIG_DEBUG_ERROR=y +CONFIG_DEBUG_WARN=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_ASSERTIONS is not set + +# +# Subsystem Debug Options +# +# CONFIG_DEBUG_BINFMT is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_GRAPHICS is not set +# CONFIG_DEBUG_LIB is not set +# CONFIG_DEBUG_MM is not set +# CONFIG_DEBUG_SCHED is not set + +# +# OS Function Debug Options +# +# CONFIG_DEBUG_IRQ is not set + +# +# Driver Debug Options +# +# CONFIG_DEBUG_LEDS is not set +CONFIG_DEBUG_CAN=y +CONFIG_DEBUG_CAN_ERROR=y +CONFIG_DEBUG_CAN_WARN=y +CONFIG_DEBUG_CAN_INFO=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_DEBUG_SPI is not set +# CONFIG_DEBUG_TIMER is not set +CONFIG_ARCH_HAVE_STACKCHECK=y +# CONFIG_STACK_COLORATION is not set +CONFIG_ARCH_HAVE_HEAPCHECK=y +# CONFIG_HEAP_COLORATION is not set +# CONFIG_DEBUG_SYMBOLS is not set +CONFIG_ARCH_HAVE_CUSTOMOPT=y +# CONFIG_DEBUG_NOOPT is not set +# CONFIG_DEBUG_CUSTOMOPT is not set +CONFIG_DEBUG_FULLOPT=y + +# +# System Type +# +CONFIG_ARCH_ARM=y +# CONFIG_ARCH_AVR is not set +# CONFIG_ARCH_HC is not set +# CONFIG_ARCH_MIPS is not set +# CONFIG_ARCH_MISOC is not set +# CONFIG_ARCH_RENESAS is not set +# CONFIG_ARCH_RISCV is not set +# CONFIG_ARCH_SIM is not set +# CONFIG_ARCH_X86 is not set +# CONFIG_ARCH_XTENSA is not set +# CONFIG_ARCH_Z16 is not set +# CONFIG_ARCH_Z80 is not set +CONFIG_ARCH="arm" + +# +# ARM Options +# +# CONFIG_ARCH_CHIP_A1X is not set +# CONFIG_ARCH_CHIP_C5471 is not set +# CONFIG_ARCH_CHIP_DM320 is not set +# CONFIG_ARCH_CHIP_EFM32 is not set +# CONFIG_ARCH_CHIP_IMX1 is not set +# CONFIG_ARCH_CHIP_IMX6 is not set +# CONFIG_ARCH_CHIP_KINETIS is not set +# CONFIG_ARCH_CHIP_KL is not set +# CONFIG_ARCH_CHIP_LM is not set +# CONFIG_ARCH_CHIP_TIVA is not set +# CONFIG_ARCH_CHIP_LPC11XX is not set +# CONFIG_ARCH_CHIP_LPC17XX is not set +# CONFIG_ARCH_CHIP_LPC214X is not set +# CONFIG_ARCH_CHIP_LPC2378 is not set +# CONFIG_ARCH_CHIP_LPC31XX is not set +# CONFIG_ARCH_CHIP_LPC43XX is not set +# CONFIG_ARCH_CHIP_MOXART is not set +# CONFIG_ARCH_CHIP_NUC1XX is not set +# CONFIG_ARCH_CHIP_SAMA5 is not set +# CONFIG_ARCH_CHIP_SAMD is not set +# CONFIG_ARCH_CHIP_SAML is not set +# CONFIG_ARCH_CHIP_SAM34 is not set +# CONFIG_ARCH_CHIP_SAMV7 is not set +CONFIG_ARCH_CHIP_STM32=y +# CONFIG_ARCH_CHIP_STM32F0 is not set +# CONFIG_ARCH_CHIP_STM32F7 is not set +# CONFIG_ARCH_CHIP_STM32L4 is not set +# CONFIG_ARCH_CHIP_STR71X is not set +# CONFIG_ARCH_CHIP_TMS570 is not set +# CONFIG_ARCH_CHIP_XMC4 is not set +# CONFIG_ARCH_ARM7TDMI is not set +# CONFIG_ARCH_ARM926EJS is not set +# CONFIG_ARCH_ARM920T is not set +# CONFIG_ARCH_CORTEXM0 is not set +# CONFIG_ARCH_CORTEXM23 is not set +CONFIG_ARCH_CORTEXM3=y +# CONFIG_ARCH_CORTEXM33 is not set +# CONFIG_ARCH_CORTEXM4 is not set +# CONFIG_ARCH_CORTEXM7 is not set +# CONFIG_ARCH_CORTEXA5 is not set +# CONFIG_ARCH_CORTEXA8 is not set +# CONFIG_ARCH_CORTEXA9 is not set +# CONFIG_ARCH_CORTEXR4 is not set +# CONFIG_ARCH_CORTEXR4F is not set +# CONFIG_ARCH_CORTEXR5 is not set +# CONFIG_ARCH_CORTEX5F is not set +# CONFIG_ARCH_CORTEXR7 is not set +# CONFIG_ARCH_CORTEXR7F is not set +CONFIG_ARCH_FAMILY="armv7-m" +CONFIG_ARCH_CHIP="stm32" +# CONFIG_ARM_TOOLCHAIN_IAR is not set +CONFIG_ARM_TOOLCHAIN_GNU=y +# CONFIG_ARMV7M_USEBASEPRI is not set +CONFIG_ARCH_HAVE_CMNVECTOR=y +# CONFIG_ARMV7M_CMNVECTOR is not set +# CONFIG_ARMV7M_LAZYFPU is not set +# CONFIG_ARCH_HAVE_FPU is not set +# CONFIG_ARCH_HAVE_DPFPU is not set +# CONFIG_ARCH_HAVE_TRUSTZONE is not set +CONFIG_ARM_HAVE_MPU_UNIFIED=y +# CONFIG_ARM_MPU is not set +# CONFIG_DEBUG_HARDFAULT is not set + +# +# ARMV7M Configuration Options +# +# CONFIG_ARMV7M_HAVE_ICACHE is not set +# CONFIG_ARMV7M_HAVE_DCACHE is not set +# CONFIG_ARMV7M_HAVE_ITCM is not set +# CONFIG_ARMV7M_HAVE_DTCM is not set +# CONFIG_ARMV7M_TOOLCHAIN_IARL is not set +# CONFIG_ARMV7M_TOOLCHAIN_BUILDROOT is not set +# CONFIG_ARMV7M_TOOLCHAIN_CODEREDL is not set +# CONFIG_ARMV7M_TOOLCHAIN_CODESOURCERYL is not set +CONFIG_ARMV7M_TOOLCHAIN_GNU_EABIL=y +CONFIG_ARMV7M_HAVE_STACKCHECK=y +# CONFIG_ARMV7M_STACKCHECK is not set +# CONFIG_ARMV7M_ITMSYSLOG is not set +CONFIG_SERIAL_TERMIOS=y +# CONFIG_CAN_EXTID is not set +# CONFIG_CAN_LOOPBACK is not set + +# +# STM32 Configuration Options +# +# CONFIG_ARCH_CHIP_STM32L151C6 is not set +# CONFIG_ARCH_CHIP_STM32L151C8 is not set +# CONFIG_ARCH_CHIP_STM32L151CB is not set +# CONFIG_ARCH_CHIP_STM32L151R6 is not set +# CONFIG_ARCH_CHIP_STM32L151R8 is not set +# CONFIG_ARCH_CHIP_STM32L151RB is not set +# CONFIG_ARCH_CHIP_STM32L151V6 is not set +# CONFIG_ARCH_CHIP_STM32L151V8 is not set +# CONFIG_ARCH_CHIP_STM32L151VB is not set +# CONFIG_ARCH_CHIP_STM32L152C6 is not set +# CONFIG_ARCH_CHIP_STM32L152C8 is not set +# CONFIG_ARCH_CHIP_STM32L152CB is not set +# CONFIG_ARCH_CHIP_STM32L152R6 is not set +# CONFIG_ARCH_CHIP_STM32L152R8 is not set +# CONFIG_ARCH_CHIP_STM32L152RB is not set +# CONFIG_ARCH_CHIP_STM32L152V6 is not set +# CONFIG_ARCH_CHIP_STM32L152V8 is not set +# CONFIG_ARCH_CHIP_STM32L152VB is not set +# CONFIG_ARCH_CHIP_STM32L152CC is not set +# CONFIG_ARCH_CHIP_STM32L152RC is not set +# CONFIG_ARCH_CHIP_STM32L152VC is not set +# CONFIG_ARCH_CHIP_STM32L162ZD is not set +# CONFIG_ARCH_CHIP_STM32L162VE is not set +# CONFIG_ARCH_CHIP_STM32F100C8 is not set +# CONFIG_ARCH_CHIP_STM32F100CB is not set +# CONFIG_ARCH_CHIP_STM32F100R8 is not set +# CONFIG_ARCH_CHIP_STM32F100RB is not set +# CONFIG_ARCH_CHIP_STM32F100RC is not set +# CONFIG_ARCH_CHIP_STM32F100RD is not set +# CONFIG_ARCH_CHIP_STM32F100RE is not set +# CONFIG_ARCH_CHIP_STM32F100V8 is not set +# CONFIG_ARCH_CHIP_STM32F100VB is not set +# CONFIG_ARCH_CHIP_STM32F100VC is not set +# CONFIG_ARCH_CHIP_STM32F100VD is not set +# CONFIG_ARCH_CHIP_STM32F100VE is not set +# CONFIG_ARCH_CHIP_STM32F102CB is not set +# CONFIG_ARCH_CHIP_STM32F103T8 is not set +# CONFIG_ARCH_CHIP_STM32F103TB is not set +# CONFIG_ARCH_CHIP_STM32F103C4 is not set +CONFIG_ARCH_CHIP_STM32F103C8=y +# CONFIG_ARCH_CHIP_STM32F103CB is not set +# CONFIG_ARCH_CHIP_STM32F103R8 is not set +# CONFIG_ARCH_CHIP_STM32F103RB is not set +# CONFIG_ARCH_CHIP_STM32F103RC is not set +# CONFIG_ARCH_CHIP_STM32F103RD is not set +# CONFIG_ARCH_CHIP_STM32F103RE is not set +# CONFIG_ARCH_CHIP_STM32F103RG is not set +# CONFIG_ARCH_CHIP_STM32F103V8 is not set +# CONFIG_ARCH_CHIP_STM32F103VB is not set +# CONFIG_ARCH_CHIP_STM32F103VC is not set +# CONFIG_ARCH_CHIP_STM32F103VE is not set +# CONFIG_ARCH_CHIP_STM32F103ZE is not set +# CONFIG_ARCH_CHIP_STM32F105VB is not set +# CONFIG_ARCH_CHIP_STM32F105RB is not set +# CONFIG_ARCH_CHIP_STM32F107VC is not set +# CONFIG_ARCH_CHIP_STM32F205RG is not set +# CONFIG_ARCH_CHIP_STM32F207IG is not set +# CONFIG_ARCH_CHIP_STM32F207ZE is not set +# CONFIG_ARCH_CHIP_STM32F302K6 is not set +# CONFIG_ARCH_CHIP_STM32F302K8 is not set +# CONFIG_ARCH_CHIP_STM32F302CB is not set +# CONFIG_ARCH_CHIP_STM32F302CC is not set +# CONFIG_ARCH_CHIP_STM32F302RB is not set +# CONFIG_ARCH_CHIP_STM32F302RC is not set +# CONFIG_ARCH_CHIP_STM32F302VB is not set +# CONFIG_ARCH_CHIP_STM32F302VC is not set +# CONFIG_ARCH_CHIP_STM32F303K6 is not set +# CONFIG_ARCH_CHIP_STM32F303K8 is not set +# CONFIG_ARCH_CHIP_STM32F303C6 is not set +# CONFIG_ARCH_CHIP_STM32F303C8 is not set +# CONFIG_ARCH_CHIP_STM32F303CB is not set +# CONFIG_ARCH_CHIP_STM32F303CC is not set +# CONFIG_ARCH_CHIP_STM32F303RB is not set +# CONFIG_ARCH_CHIP_STM32F303RC is not set +# CONFIG_ARCH_CHIP_STM32F303RD is not set +# CONFIG_ARCH_CHIP_STM32F303RE is not set +# CONFIG_ARCH_CHIP_STM32F303VB is not set +# CONFIG_ARCH_CHIP_STM32F303VC is not set +# CONFIG_ARCH_CHIP_STM32F334K4 is not set +# CONFIG_ARCH_CHIP_STM32F334K6 is not set +# CONFIG_ARCH_CHIP_STM32F334K8 is not set +# CONFIG_ARCH_CHIP_STM32F334C4 is not set +# CONFIG_ARCH_CHIP_STM32F334C6 is not set +# CONFIG_ARCH_CHIP_STM32F334C8 is not set +# CONFIG_ARCH_CHIP_STM32F334R4 is not set +# CONFIG_ARCH_CHIP_STM32F334R6 is not set +# CONFIG_ARCH_CHIP_STM32F334R8 is not set +# CONFIG_ARCH_CHIP_STM32F372C8 is not set +# CONFIG_ARCH_CHIP_STM32F372R8 is not set +# CONFIG_ARCH_CHIP_STM32F372V8 is not set +# CONFIG_ARCH_CHIP_STM32F372CB is not set +# CONFIG_ARCH_CHIP_STM32F372RB is not set +# CONFIG_ARCH_CHIP_STM32F372VB is not set +# CONFIG_ARCH_CHIP_STM32F372CC is not set +# CONFIG_ARCH_CHIP_STM32F372RC is not set +# CONFIG_ARCH_CHIP_STM32F372VC is not set +# CONFIG_ARCH_CHIP_STM32F373C8 is not set +# CONFIG_ARCH_CHIP_STM32F373R8 is not set +# CONFIG_ARCH_CHIP_STM32F373V8 is not set +# CONFIG_ARCH_CHIP_STM32F373CB is not set +# CONFIG_ARCH_CHIP_STM32F373RB is not set +# CONFIG_ARCH_CHIP_STM32F373VB is not set +# CONFIG_ARCH_CHIP_STM32F373CC is not set +# CONFIG_ARCH_CHIP_STM32F373RC is not set +# CONFIG_ARCH_CHIP_STM32F373VC is not set +# CONFIG_ARCH_CHIP_STM32F401RE is not set +# CONFIG_ARCH_CHIP_STM32F411RE is not set +# CONFIG_ARCH_CHIP_STM32F411VE is not set +# CONFIG_ARCH_CHIP_STM32F405RG is not set +# CONFIG_ARCH_CHIP_STM32F405VG is not set +# CONFIG_ARCH_CHIP_STM32F405ZG is not set +# CONFIG_ARCH_CHIP_STM32F407VE is not set +# CONFIG_ARCH_CHIP_STM32F407VG is not set +# CONFIG_ARCH_CHIP_STM32F407ZE is not set +# CONFIG_ARCH_CHIP_STM32F407ZG is not set +# CONFIG_ARCH_CHIP_STM32F407IE is not set +# CONFIG_ARCH_CHIP_STM32F407IG is not set +# CONFIG_ARCH_CHIP_STM32F427V is not set +# CONFIG_ARCH_CHIP_STM32F427Z is not set +# CONFIG_ARCH_CHIP_STM32F427I is not set +# CONFIG_ARCH_CHIP_STM32F429V is not set +# CONFIG_ARCH_CHIP_STM32F429Z is not set +# CONFIG_ARCH_CHIP_STM32F429I is not set +# CONFIG_ARCH_CHIP_STM32F429B is not set +# CONFIG_ARCH_CHIP_STM32F429N is not set +# CONFIG_ARCH_CHIP_STM32F446M is not set +# CONFIG_ARCH_CHIP_STM32F446R is not set +# CONFIG_ARCH_CHIP_STM32F446V is not set +# CONFIG_ARCH_CHIP_STM32F446Z is not set +# CONFIG_ARCH_CHIP_STM32F469A is not set +# CONFIG_ARCH_CHIP_STM32F469I is not set +# CONFIG_ARCH_CHIP_STM32F469B is not set +# CONFIG_ARCH_CHIP_STM32F469N is not set +CONFIG_STM32_FLASH_CONFIG_DEFAULT=y +# CONFIG_STM32_FLASH_CONFIG_4 is not set +# CONFIG_STM32_FLASH_CONFIG_6 is not set +# CONFIG_STM32_FLASH_CONFIG_8 is not set +# CONFIG_STM32_FLASH_CONFIG_B is not set +# CONFIG_STM32_FLASH_CONFIG_C is not set +# CONFIG_STM32_FLASH_CONFIG_D is not set +# CONFIG_STM32_FLASH_CONFIG_E is not set +# CONFIG_STM32_FLASH_CONFIG_F is not set +# CONFIG_STM32_FLASH_CONFIG_G is not set +# CONFIG_STM32_FLASH_CONFIG_I is not set +# CONFIG_STM32_STM32L15XX is not set +# CONFIG_STM32_ENERGYLITE is not set +CONFIG_STM32_STM32F10XX=y +# CONFIG_STM32_VALUELINE is not set +# CONFIG_STM32_CONNECTIVITYLINE is not set +CONFIG_STM32_PERFORMANCELINE=y +# CONFIG_STM32_USBACCESSLINE is not set +# CONFIG_STM32_HIGHDENSITY is not set +CONFIG_STM32_MEDIUMDENSITY=y +# CONFIG_STM32_LOWDENSITY is not set +# CONFIG_STM32_STM32F20XX is not set +# CONFIG_STM32_STM32F205 is not set +# CONFIG_STM32_STM32F207 is not set +# CONFIG_STM32_STM32F30XX is not set +# CONFIG_STM32_STM32F302 is not set +# CONFIG_STM32_STM32F303 is not set +# CONFIG_STM32_STM32F33XX is not set +# CONFIG_STM32_STM32F37XX is not set +# CONFIG_STM32_STM32F40XX is not set +# CONFIG_STM32_STM32F401 is not set +# CONFIG_STM32_STM32F411 is not set +# CONFIG_STM32_STM32F405 is not set +# CONFIG_STM32_STM32F407 is not set +# CONFIG_STM32_STM32F427 is not set +# CONFIG_STM32_STM32F429 is not set +# CONFIG_STM32_STM32F446 is not set +# CONFIG_STM32_STM32F469 is not set +# CONFIG_STM32_DFU is not set + +# +# STM32 Peripheral Support +# +# CONFIG_STM32_HAVE_CCM is not set +CONFIG_STM32_HAVE_USBDEV=y +# CONFIG_STM32_HAVE_OTGFS is not set +# CONFIG_STM32_HAVE_FSMC is not set +# CONFIG_STM32_HAVE_HRTIM1 is not set +# CONFIG_STM32_HAVE_LTDC is not set +CONFIG_STM32_HAVE_USART3=y +CONFIG_STM32_HAVE_UART4=y +CONFIG_STM32_HAVE_UART5=y +# CONFIG_STM32_HAVE_USART6 is not set +# CONFIG_STM32_HAVE_UART7 is not set +# CONFIG_STM32_HAVE_UART8 is not set +CONFIG_STM32_HAVE_TIM1=y +# CONFIG_STM32_HAVE_TIM2 is not set +CONFIG_STM32_HAVE_TIM3=y +CONFIG_STM32_HAVE_TIM4=y +CONFIG_STM32_HAVE_TIM5=y +CONFIG_STM32_HAVE_TIM6=y +CONFIG_STM32_HAVE_TIM7=y +CONFIG_STM32_HAVE_TIM8=y +# CONFIG_STM32_HAVE_TIM9 is not set +# CONFIG_STM32_HAVE_TIM10 is not set +# CONFIG_STM32_HAVE_TIM11 is not set +# CONFIG_STM32_HAVE_TIM12 is not set +# CONFIG_STM32_HAVE_TIM13 is not set +# CONFIG_STM32_HAVE_TIM14 is not set +# CONFIG_STM32_HAVE_TIM15 is not set +# CONFIG_STM32_HAVE_TIM16 is not set +# CONFIG_STM32_HAVE_TIM17 is not set +CONFIG_STM32_HAVE_ADC2=y +CONFIG_STM32_HAVE_ADC3=y +# CONFIG_STM32_HAVE_ADC4 is not set +# CONFIG_STM32_HAVE_ADC1_DMA is not set +# CONFIG_STM32_HAVE_ADC2_DMA is not set +# CONFIG_STM32_HAVE_ADC3_DMA is not set +# CONFIG_STM32_HAVE_ADC4_DMA is not set +# CONFIG_STM32_HAVE_SDADC1 is not set +# CONFIG_STM32_HAVE_SDADC2 is not set +# CONFIG_STM32_HAVE_SDADC3 is not set +# CONFIG_STM32_HAVE_SDADC1_DMA is not set +# CONFIG_STM32_HAVE_SDADC2_DMA is not set +# CONFIG_STM32_HAVE_SDADC3_DMA is not set +CONFIG_STM32_HAVE_CAN1=y +# CONFIG_STM32_HAVE_CAN2 is not set +# CONFIG_STM32_HAVE_COMP1 is not set +# CONFIG_STM32_HAVE_COMP2 is not set +# CONFIG_STM32_HAVE_COMP3 is not set +# CONFIG_STM32_HAVE_COMP4 is not set +# CONFIG_STM32_HAVE_COMP5 is not set +# CONFIG_STM32_HAVE_COMP6 is not set +# CONFIG_STM32_HAVE_COMP7 is not set +# CONFIG_STM32_HAVE_DAC1 is not set +# CONFIG_STM32_HAVE_DAC2 is not set +# CONFIG_STM32_HAVE_RNG is not set +# CONFIG_STM32_HAVE_ETHMAC is not set +CONFIG_STM32_HAVE_I2C2=y +# CONFIG_STM32_HAVE_I2C3 is not set +CONFIG_STM32_HAVE_SPI2=y +CONFIG_STM32_HAVE_SPI3=y +# CONFIG_STM32_HAVE_SPI4 is not set +# CONFIG_STM32_HAVE_SPI5 is not set +# CONFIG_STM32_HAVE_SPI6 is not set +# CONFIG_STM32_HAVE_SAIPLL is not set +# CONFIG_STM32_HAVE_I2SPLL is not set +# CONFIG_STM32_HAVE_OPAMP1 is not set +# CONFIG_STM32_HAVE_OPAMP2 is not set +# CONFIG_STM32_HAVE_OPAMP3 is not set +# CONFIG_STM32_HAVE_OPAMP4 is not set +# CONFIG_STM32_ADC1 is not set +# CONFIG_STM32_ADC2 is not set +# CONFIG_STM32_ADC3 is not set +# CONFIG_STM32_BKP is not set +# CONFIG_STM32_CAN1 is not set +# CONFIG_STM32_CRC is not set +# CONFIG_STM32_DMA1 is not set +# CONFIG_STM32_DMA2 is not set +# CONFIG_STM32_I2C1 is not set +# CONFIG_STM32_I2C2 is not set +# CONFIG_STM32_OPAMP is not set +# CONFIG_STM32_PWR is not set +# CONFIG_STM32_SDIO is not set +CONFIG_STM32_SPI1=y +# CONFIG_STM32_SPI2 is not set +# CONFIG_STM32_SPI3 is not set +# CONFIG_STM32_TIM1 is not set +# CONFIG_STM32_TIM2 is not set +# CONFIG_STM32_TIM3 is not set +# CONFIG_STM32_TIM4 is not set +# CONFIG_STM32_TIM5 is not set +# CONFIG_STM32_TIM6 is not set +# CONFIG_STM32_TIM7 is not set +# CONFIG_STM32_TIM8 is not set +CONFIG_STM32_USART1=y +# CONFIG_STM32_USART2 is not set +# CONFIG_STM32_USART3 is not set +# CONFIG_STM32_UART4 is not set +# CONFIG_STM32_UART5 is not set +# CONFIG_STM32_USB is not set +# CONFIG_STM32_IWDG is not set +# CONFIG_STM32_WWDG is not set +CONFIG_STM32_SPI=y +# CONFIG_STM32_NOEXT_VECTORS is not set + +# +# Alternate Pin Mapping +# +# CONFIG_STM32_SPI1_REMAP is not set +# CONFIG_STM32_USART1_REMAP is not set +# CONFIG_STM32_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW is not set +# CONFIG_STM32_JTAG_DISABLE is not set +CONFIG_STM32_JTAG_FULL_ENABLE=y +# CONFIG_STM32_JTAG_NOJNTRST_ENABLE is not set +# CONFIG_STM32_JTAG_SW_ENABLE is not set +CONFIG_STM32_DISABLE_IDLE_SLEEP_DURING_DEBUG=y +# CONFIG_STM32_FORCEPOWER is not set +# CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG is not set + +# +# Timer Configuration +# +# CONFIG_STM32_ONESHOT is not set +# CONFIG_STM32_FREERUN is not set +# CONFIG_STM32_TIM1_CAP is not set +# CONFIG_STM32_TIM3_CAP is not set +# CONFIG_STM32_TIM4_CAP is not set +# CONFIG_STM32_TIM5_CAP is not set +# CONFIG_STM32_TIM8_CAP is not set +CONFIG_STM32_USART=y +CONFIG_STM32_SERIALDRIVER=y + +# +# U[S]ART Configuration +# + +# +# U[S]ART Device Configuration +# +CONFIG_STM32_USART1_SERIALDRIVER=y +# CONFIG_STM32_USART1_1WIREDRIVER is not set +# CONFIG_USART1_RS485 is not set + +# +# Serial Driver Configuration +# +# CONFIG_SERIAL_DISABLE_REORDERING is not set +# CONFIG_STM32_FLOWCONTROL_BROKEN is not set +# CONFIG_STM32_USART_BREAKS is not set +# CONFIG_STM32_USART_SINGLEWIRE is not set + +# +# SPI Configuration +# +# CONFIG_STM32_SPI_INTERRUPTS is not set +# CONFIG_STM32_SPI_DMA is not set +CONFIG_STM32_HAVE_RTC_COUNTER=y +# CONFIG_STM32_HAVE_RTC_SUBSECONDS is not set + +# +# USB FS Host Configuration +# + +# +# USB HS Host Configuration +# + +# +# USB Host Debug Configuration +# + +# +# USB Device Configuration +# + +# +# Architecture Options +# +# CONFIG_ARCH_NOINTC is not set +# CONFIG_ARCH_VECNOTIRQ is not set +# CONFIG_ARCH_DMA is not set +CONFIG_ARCH_HAVE_IRQPRIO=y +# CONFIG_ARCH_L2CACHE is not set +# CONFIG_ARCH_HAVE_COHERENT_DCACHE is not set +# CONFIG_ARCH_HAVE_ADDRENV is not set +# CONFIG_ARCH_NEED_ADDRENV_MAPPING is not set +# CONFIG_ARCH_HAVE_MULTICPU is not set +CONFIG_ARCH_HAVE_VFORK=y +# CONFIG_ARCH_HAVE_MMU is not set +CONFIG_ARCH_HAVE_MPU=y +# CONFIG_ARCH_NAND_HWECC is not set +# CONFIG_ARCH_HAVE_EXTCLK is not set +# CONFIG_ARCH_HAVE_POWEROFF is not set +CONFIG_ARCH_HAVE_RESET=y +# CONFIG_ARCH_HAVE_RTC_SUBSECONDS is not set +# CONFIG_ARCH_USE_MPU is not set +# CONFIG_ARCH_IRQPRIO is not set +CONFIG_ARCH_STACKDUMP=y +# CONFIG_ENDIAN_BIG is not set +# CONFIG_ARCH_IDLE_CUSTOM is not set +# CONFIG_ARCH_HAVE_RAMFUNCS is not set +CONFIG_ARCH_HAVE_RAMVECTORS=y +# CONFIG_ARCH_RAMVECTORS is not set +# CONFIG_ARCH_MINIMAL_VECTORTABLE is not set + +# +# Board Settings +# +CONFIG_BOARD_LOOPSPERMSEC=5483 +# CONFIG_ARCH_CALIBRATION is not set + +# +# Interrupt options +# +CONFIG_ARCH_HAVE_INTERRUPTSTACK=y +CONFIG_ARCH_INTERRUPTSTACK=0 +CONFIG_ARCH_HAVE_HIPRI_INTERRUPT=y +# CONFIG_ARCH_HIPRI_INTERRUPT is not set + +# +# Boot options +# +# CONFIG_BOOT_RUNFROMEXTSRAM is not set +CONFIG_BOOT_RUNFROMFLASH=y +# CONFIG_BOOT_RUNFROMISRAM is not set +# CONFIG_BOOT_RUNFROMSDRAM is not set +# CONFIG_BOOT_COPYTORAM is not set + +# +# Boot Memory Configuration +# +CONFIG_RAM_START=0x20000000 +CONFIG_RAM_SIZE=20480 +# CONFIG_ARCH_HAVE_SDRAM is not set + +# +# Board Selection +# +# CONFIG_ARCH_BOARD_STM32_TINY is not set +CONFIG_ARCH_BOARD_STM32F103_MINIMUM=y +# CONFIG_ARCH_BOARD_CUSTOM is not set +CONFIG_ARCH_BOARD="stm32f103-minimum" + +# +# Common Board Options +# +CONFIG_ARCH_HAVE_LEDS=y +CONFIG_ARCH_LEDS=y +CONFIG_ARCH_HAVE_BUTTONS=y +# CONFIG_ARCH_BUTTONS is not set +CONFIG_ARCH_HAVE_IRQBUTTONS=y + +# +# Board-Specific Options +# +# CONFIG_BOARD_CRASHDUMP is not set +CONFIG_LIB_BOARDCTL=y +# CONFIG_BOARDCTL_RESET is not set +# CONFIG_BOARDCTL_UNIQUEID is not set +# CONFIG_BOARDCTL_TSCTEST is not set +# CONFIG_BOARDCTL_GRAPHICS is not set +# CONFIG_BOARDCTL_IOCTL is not set + +# +# RTOS Features +# +# CONFIG_DISABLE_OS_API is not set + +# +# Clocks and Timers +# +CONFIG_ARCH_HAVE_TICKLESS=y +# CONFIG_SCHED_TICKLESS is not set +CONFIG_USEC_PER_TICK=10000 +# CONFIG_SYSTEM_TIME64 is not set +# CONFIG_CLOCK_MONOTONIC is not set +CONFIG_ARCH_HAVE_TIMEKEEPING=y +# CONFIG_JULIAN_TIME is not set +CONFIG_START_YEAR=2011 +CONFIG_START_MONTH=7 +CONFIG_START_DAY=5 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_PREALLOC_WDOGS=4 +CONFIG_WDOG_INTRESERVE=0 +CONFIG_PREALLOC_TIMERS=4 + +# +# Tasks and Scheduling +# +# CONFIG_SPINLOCK is not set +# CONFIG_INIT_NONE is not set +CONFIG_INIT_ENTRYPOINT=y +# CONFIG_INIT_FILEPATH is not set +CONFIG_USER_ENTRYPOINT="nsh_main" +CONFIG_RR_INTERVAL=200 +# CONFIG_SCHED_SPORADIC is not set +CONFIG_TASK_NAME_SIZE=0 +CONFIG_MAX_TASKS=16 +# CONFIG_SCHED_HAVE_PARENT is not set +CONFIG_SCHED_WAITPID=y + +# +# Pthread Options +# +# CONFIG_PTHREAD_MUTEX_TYPES is not set +CONFIG_PTHREAD_MUTEX_ROBUST=y +# CONFIG_PTHREAD_MUTEX_UNSAFE is not set +# CONFIG_PTHREAD_MUTEX_BOTH is not set +CONFIG_NPTHREAD_KEYS=4 +# CONFIG_PTHREAD_CLEANUP is not set +# CONFIG_CANCELLATION_POINTS is not set + +# +# Performance Monitoring +# +# CONFIG_SCHED_CPULOAD is not set +# CONFIG_SCHED_INSTRUMENTATION is not set + +# +# Files and I/O +# +CONFIG_DEV_CONSOLE=y +# CONFIG_FDCLONE_DISABLE is not set +# CONFIG_FDCLONE_STDIO is not set +CONFIG_SDCLONE_DISABLE=y +CONFIG_NFILE_DESCRIPTORS=8 +CONFIG_NFILE_STREAMS=8 +CONFIG_NAME_MAX=32 +# CONFIG_PRIORITY_INHERITANCE is not set + +# +# RTOS hooks +# +# CONFIG_BOARD_INITIALIZE is not set +# CONFIG_SCHED_STARTHOOK is not set +# CONFIG_SCHED_ATEXIT is not set +# CONFIG_SCHED_ONEXIT is not set +# CONFIG_SIG_EVTHREAD is not set + +# +# Signal Numbers +# +CONFIG_SIG_SIGUSR1=1 +CONFIG_SIG_SIGUSR2=2 +CONFIG_SIG_SIGALARM=3 +CONFIG_SIG_SIGCONDTIMEDOUT=16 +CONFIG_SIG_SIGWORK=17 + +# +# POSIX Message Queue Options +# +CONFIG_PREALLOC_MQ_MSGS=4 +CONFIG_MQ_MAXMSGSIZE=32 +# CONFIG_MODULE is not set + +# +# Work queue support +# +CONFIG_SCHED_WORKQUEUE=y +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=192 +CONFIG_SCHED_HPWORKPERIOD=50000 +CONFIG_SCHED_HPWORKSTACKSIZE=2048 +# CONFIG_SCHED_LPWORK is not set + +# +# Stack and heap information +# +CONFIG_IDLETHREAD_STACKSIZE=1024 +CONFIG_USERMAIN_STACKSIZE=2048 +CONFIG_PTHREAD_STACK_MIN=256 +CONFIG_PTHREAD_STACK_DEFAULT=2048 +# CONFIG_LIB_SYSCALL is not set + +# +# Device Drivers +# +CONFIG_DISABLE_POLL=y +CONFIG_DEV_NULL=y +# CONFIG_DEV_ZERO is not set +# CONFIG_DEV_URANDOM is not set +# CONFIG_DEV_LOOP is not set + +# +# Buffering +# +# CONFIG_DRVR_WRITEBUFFER is not set +# CONFIG_DRVR_READAHEAD is not set +# CONFIG_RAMDISK is not set +CONFIG_CAN=y +# CONFIG_ARCH_HAVE_CAN_ERRORS is not set +# CONFIG_CAN_FD is not set +CONFIG_CAN_FIFOSIZE=8 +CONFIG_CAN_NPENDINGRTR=4 +# CONFIG_CAN_TXREADY is not set + +# +# CAN Bus Controllers: +# +CONFIG_CAN_MCP2515=y +CONFIG_MCP2515_BITRATE=500000 +CONFIG_MCP2515_PROPSEG=1 +CONFIG_MCP2515_PHASESEG1=3 +CONFIG_MCP2515_PHASESEG2=3 +CONFIG_MCP2515_SJW=1 +# CONFIG_ARCH_HAVE_PWM_PULSECOUNT is not set +# CONFIG_ARCH_HAVE_PWM_MULTICHAN is not set +# CONFIG_PWM is not set +CONFIG_ARCH_HAVE_I2CRESET=y +# CONFIG_I2C is not set +# CONFIG_ARCH_HAVE_SPI_CRCGENERATION is not set +# CONFIG_ARCH_HAVE_SPI_CS_CONTROL is not set +CONFIG_ARCH_HAVE_SPI_BITORDER=y +CONFIG_SPI=y +# CONFIG_SPI_SLAVE is not set +CONFIG_SPI_EXCHANGE=y +# CONFIG_SPI_CMDDATA is not set +# CONFIG_SPI_CALLBACK is not set +# CONFIG_SPI_HWFEATURES is not set +# CONFIG_SPI_BITORDER is not set +# CONFIG_SPI_CS_DELAY_CONTROL is not set +# CONFIG_SPI_DRIVER is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_I2S is not set + +# +# Timer Driver Support +# +# CONFIG_TIMER is not set +# CONFIG_ONESHOT is not set +# CONFIG_RTC is not set +# CONFIG_WATCHDOG is not set +# CONFIG_ANALOG is not set +# CONFIG_AUDIO_DEVICES is not set +# CONFIG_VIDEO_DEVICES is not set +# CONFIG_BCH is not set +# CONFIG_INPUT is not set + +# +# IO Expander/GPIO Support +# +# CONFIG_IOEXPANDER is not set +# CONFIG_DEV_GPIO is not set + +# +# LCD Driver Support +# +# CONFIG_LCD is not set +# CONFIG_SLCD is not set + +# +# LED Support +# +# CONFIG_USERLED is not set +# CONFIG_RGBLED is not set +# CONFIG_PCA9635PW is not set +# CONFIG_NCP5623C is not set +# CONFIG_MMCSD is not set +# CONFIG_MODEM is not set +# CONFIG_MTD is not set +# CONFIG_EEPROM is not set +# CONFIG_PIPES is not set +# CONFIG_PM is not set +# CONFIG_POWER is not set +# CONFIG_SENSORS is not set +CONFIG_SERIAL=y +# CONFIG_DEV_LOWCONSOLE is not set +# CONFIG_SERIAL_REMOVABLE is not set +CONFIG_SERIAL_CONSOLE=y +# CONFIG_16550_UART is not set +# CONFIG_UART_SERIALDRIVER is not set +# CONFIG_UART0_SERIALDRIVER is not set +# CONFIG_UART1_SERIALDRIVER is not set +# CONFIG_UART2_SERIALDRIVER is not set +# CONFIG_UART3_SERIALDRIVER is not set +# CONFIG_UART4_SERIALDRIVER is not set +# CONFIG_UART5_SERIALDRIVER is not set +# CONFIG_UART6_SERIALDRIVER is not set +# CONFIG_UART7_SERIALDRIVER is not set +# CONFIG_UART8_SERIALDRIVER is not set +# CONFIG_SCI0_SERIALDRIVER is not set +# CONFIG_SCI1_SERIALDRIVER is not set +# CONFIG_USART0_SERIALDRIVER is not set +CONFIG_USART1_SERIALDRIVER=y +# CONFIG_USART2_SERIALDRIVER is not set +# CONFIG_USART3_SERIALDRIVER is not set +# CONFIG_USART4_SERIALDRIVER is not set +# CONFIG_USART5_SERIALDRIVER is not set +# CONFIG_USART6_SERIALDRIVER is not set +# CONFIG_USART7_SERIALDRIVER is not set +# CONFIG_USART8_SERIALDRIVER is not set +# CONFIG_OTHER_UART_SERIALDRIVER is not set +CONFIG_MCU_SERIAL=y +CONFIG_STANDARD_SERIAL=y +# CONFIG_SERIAL_IFLOWCONTROL is not set +# CONFIG_SERIAL_OFLOWCONTROL is not set +# CONFIG_SERIAL_DMA is not set +# CONFIG_SERIAL_TIOCSERGSTRUCT is not set +CONFIG_ARCH_HAVE_SERIAL_TERMIOS=y +CONFIG_USART1_SERIAL_CONSOLE=y +# CONFIG_OTHER_SERIAL_CONSOLE is not set +# CONFIG_NO_SERIAL_CONSOLE is not set + +# +# USART1 Configuration +# +CONFIG_USART1_RXBUFSIZE=256 +CONFIG_USART1_TXBUFSIZE=256 +CONFIG_USART1_BAUD=115200 +CONFIG_USART1_BITS=8 +CONFIG_USART1_PARITY=0 +CONFIG_USART1_2STOP=0 +# CONFIG_USART1_IFLOWCONTROL is not set +# CONFIG_USART1_OFLOWCONTROL is not set +# CONFIG_USART1_DMA is not set +# CONFIG_PSEUDOTERM is not set +# CONFIG_USBDEV is not set +# CONFIG_USBHOST is not set +# CONFIG_USBMISC is not set +# CONFIG_HAVE_USBTRACE is not set +# CONFIG_DRIVERS_WIRELESS is not set +# CONFIG_DRIVERS_CONTACTLESS is not set + +# +# System Logging +# +# CONFIG_ARCH_SYSLOG is not set +CONFIG_SYSLOG_WRITE=y +# CONFIG_RAMLOG is not set +# CONFIG_SYSLOG_BUFFER is not set +# CONFIG_SYSLOG_INTBUFFER is not set +# CONFIG_SYSLOG_TIMESTAMP is not set +CONFIG_SYSLOG_SERIAL_CONSOLE=y +# CONFIG_SYSLOG_CHAR is not set +CONFIG_SYSLOG_CONSOLE=y +# CONFIG_SYSLOG_NONE is not set +# CONFIG_SYSLOG_FILE is not set +# CONFIG_SYSLOG_CHARDEV is not set + +# +# Networking Support +# +# CONFIG_ARCH_HAVE_NET is not set +# CONFIG_ARCH_HAVE_PHY is not set +# CONFIG_NET is not set + +# +# Crypto API +# +# CONFIG_CRYPTO is not set + +# +# File Systems +# + +# +# File system configuration +# +# CONFIG_DISABLE_MOUNTPOINT is not set +# CONFIG_FS_AUTOMOUNTER is not set +CONFIG_DISABLE_PSEUDOFS_OPERATIONS=y +# CONFIG_FS_READABLE is not set +# CONFIG_FS_WRITABLE is not set +# CONFIG_FS_NAMED_SEMAPHORES is not set +CONFIG_FS_MQUEUE_MPATH="/var/mqueue" +# CONFIG_FS_RAMMAP is not set +# CONFIG_FS_FAT is not set +# CONFIG_FS_NXFFS is not set +# CONFIG_FS_ROMFS is not set +# CONFIG_FS_TMPFS is not set +# CONFIG_FS_SMARTFS is not set +# CONFIG_FS_BINFS is not set +# CONFIG_FS_PROCFS is not set +# CONFIG_FS_UNIONFS is not set + +# +# Graphics Support +# +# CONFIG_NX is not set + +# +# Memory Management +# +# CONFIG_MM_SMALL is not set +CONFIG_MM_REGIONS=1 +# CONFIG_ARCH_HAVE_HEAP2 is not set +# CONFIG_GRAN is not set + +# +# Common I/O Buffer Support +# +# CONFIG_MM_IOB is not set + +# +# Audio Support +# +# CONFIG_AUDIO is not set + +# +# Wireless Support +# +# CONFIG_WIRELESS is not set + +# +# Binary Loader +# +# CONFIG_BINFMT_DISABLE is not set +# CONFIG_BINFMT_EXEPATH is not set +# CONFIG_NXFLAT is not set +# CONFIG_ELF is not set +CONFIG_BUILTIN=y +# CONFIG_PIC is not set +CONFIG_SYMTAB_ORDEREDBYNAME=y + +# +# Library Routines +# + +# +# Standard C Library Options +# + +# +# Standard C I/O +# +# CONFIG_STDIO_DISABLE_BUFFERING is not set +CONFIG_STDIO_BUFFER_SIZE=64 +CONFIG_STDIO_LINEBUFFER=y +CONFIG_NUNGET_CHARS=2 +# CONFIG_NOPRINTF_FIELDWIDTH is not set +# CONFIG_LIBC_FLOATINGPOINT is not set +# CONFIG_LIBC_LONG_LONG is not set +# CONFIG_LIBC_SCANSET is not set +# CONFIG_EOL_IS_CR is not set +# CONFIG_EOL_IS_LF is not set +# CONFIG_EOL_IS_BOTH_CRLF is not set +CONFIG_EOL_IS_EITHER_CRLF=y +# CONFIG_MEMCPY_VIK is not set +# CONFIG_LIBM is not set + +# +# Architecture-Specific Support +# +CONFIG_ARCH_LOWPUTC=y +# CONFIG_ARCH_ROMGETC is not set +# CONFIG_LIBC_ARCH_MEMCPY is not set +# CONFIG_LIBC_ARCH_MEMCMP is not set +# CONFIG_LIBC_ARCH_MEMMOVE is not set +# CONFIG_LIBC_ARCH_MEMSET is not set +# CONFIG_LIBC_ARCH_STRCHR is not set +# CONFIG_LIBC_ARCH_STRCMP is not set +# CONFIG_LIBC_ARCH_STRCPY is not set +# CONFIG_LIBC_ARCH_STRNCPY is not set +# CONFIG_LIBC_ARCH_STRLEN is not set +# CONFIG_LIBC_ARCH_STRNLEN is not set +# CONFIG_LIBC_ARCH_ELF is not set +# CONFIG_ARMV7M_MEMCPY is not set + +# +# stdlib Options +# +CONFIG_LIB_RAND_ORDER=1 +CONFIG_LIB_HOMEDIR="/" + +# +# Program Execution Options +# +# CONFIG_LIBC_EXECFUNCS is not set +CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=1024 +CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048 + +# +# errno Decode Support +# +# CONFIG_LIBC_STRERROR is not set +# CONFIG_LIBC_PERROR_STDOUT is not set + +# +# memcpy/memset Options +# +# CONFIG_MEMSET_OPTSPEED is not set +# CONFIG_LIBC_DLLFCN is not set +# CONFIG_LIBC_MODLIB is not set +# CONFIG_LIBC_WCHAR is not set +# CONFIG_LIBC_LOCALE is not set + +# +# Time/Time Zone Support +# +# CONFIG_LIBC_LOCALTIME is not set +# CONFIG_TIME_EXTENDED is not set +CONFIG_ARCH_HAVE_TLS=y + +# +# Thread Local Storage (TLS) +# +# CONFIG_TLS is not set + +# +# Network-Related Options +# +# CONFIG_LIBC_IPv4_ADDRCONV is not set +# CONFIG_LIBC_IPv6_ADDRCONV is not set +# CONFIG_LIBC_NETDB is not set + +# +# NETDB Support +# +# CONFIG_LIBC_IOCTL_VARIADIC is not set +CONFIG_LIB_SENDFILE_BUFSIZE=512 + +# +# Non-standard Library Support +# +# CONFIG_LIB_CRC64_FAST is not set +# CONFIG_LIB_KBDCODEC is not set +# CONFIG_LIB_SLCDCODEC is not set +# CONFIG_LIB_HEX2BIN is not set + +# +# Basic CXX Support +# +# CONFIG_C99_BOOL8 is not set +# CONFIG_HAVE_CXX is not set + +# +# Application Configuration +# + +# +# Built-In Applications +# +CONFIG_BUILTIN_PROXY_STACKSIZE=1024 + +# +# CAN Utilities +# +CONFIG_CANUTILS_CANLIB=y + +# +# Examples +# +# CONFIG_EXAMPLES_BUTTONS is not set +CONFIG_EXAMPLES_CAN=y +CONFIG_EXAMPLES_CAN_DEVPATH="/dev/can0" +CONFIG_EXAMPLES_CAN_NMSGS=32 +CONFIG_EXAMPLES_CAN_READ=y +# CONFIG_EXAMPLES_CAN_WRITE is not set +# CONFIG_EXAMPLES_CAN_READWRITE is not set +# CONFIG_EXAMPLES_CCTYPE is not set +# CONFIG_EXAMPLES_CHAT is not set +# CONFIG_EXAMPLES_CONFIGDATA is not set +# CONFIG_EXAMPLES_DHCPD is not set +# CONFIG_EXAMPLES_ELF is not set +# CONFIG_EXAMPLES_FTPC is not set +# CONFIG_EXAMPLES_FTPD is not set +# CONFIG_EXAMPLES_HELLO is not set +# CONFIG_EXAMPLES_HIDKBD is not set +# CONFIG_EXAMPLES_IGMP is not set +# CONFIG_EXAMPLES_JSON is not set +# CONFIG_EXAMPLES_KEYPADTEST is not set +# CONFIG_EXAMPLES_MEDIA is not set +# CONFIG_EXAMPLES_MM is not set +# CONFIG_EXAMPLES_MODBUS is not set +# CONFIG_EXAMPLES_MOUNT is not set +CONFIG_EXAMPLES_NSH=y +# CONFIG_EXAMPLES_NULL is not set +# CONFIG_EXAMPLES_NXFFS is not set +# CONFIG_EXAMPLES_NXHELLO is not set +# CONFIG_EXAMPLES_NXIMAGE is not set +# CONFIG_EXAMPLES_NX is not set +# CONFIG_EXAMPLES_NXLINES is not set +# CONFIG_EXAMPLES_NXTERM is not set +# CONFIG_EXAMPLES_NXTEXT is not set +# CONFIG_EXAMPLES_OSTEST is not set +# CONFIG_EXAMPLES_PCA9635 is not set +# CONFIG_EXAMPLES_POSIXSPAWN is not set +# CONFIG_EXAMPLES_PPPD is not set +# CONFIG_EXAMPLES_RFID_READUID is not set +# CONFIG_EXAMPLES_RGBLED is not set +# CONFIG_EXAMPLES_SENDMAIL is not set +# CONFIG_EXAMPLES_SERIALBLASTER is not set +# CONFIG_EXAMPLES_SERIALRX is not set +# CONFIG_EXAMPLES_SERLOOP is not set +# CONFIG_EXAMPLES_SLCD is not set +# CONFIG_EXAMPLES_SMART is not set +# CONFIG_EXAMPLES_SMART_TEST is not set +# CONFIG_EXAMPLES_SMP is not set +# CONFIG_EXAMPLES_STAT is not set +# CONFIG_EXAMPLES_TCPECHO is not set +# CONFIG_EXAMPLES_TELNETD is not set +# CONFIG_EXAMPLES_TIFF is not set +# CONFIG_EXAMPLES_TOUCHSCREEN is not set +# CONFIG_EXAMPLES_USBSERIAL is not set +# CONFIG_EXAMPLES_WATCHDOG is not set +# CONFIG_EXAMPLES_WEBSERVER is not set +# CONFIG_EXAMPLES_XBC_TEST is not set + +# +# File System Utilities +# +# CONFIG_FSUTILS_INIFILE is not set + +# +# GPS Utilities +# +# CONFIG_GPSUTILS_MINMEA_LIB is not set + +# +# Graphics Support +# +# CONFIG_TIFF is not set +# CONFIG_GRAPHICS_TRAVELER is not set + +# +# Interpreters +# +# CONFIG_INTERPRETERS_FICL is not set +# CONFIG_INTERPRETERS_MICROPYTHON is not set +# CONFIG_INTERPRETERS_MINIBASIC is not set +# CONFIG_INTERPRETERS_PCODE is not set + +# +# FreeModBus +# +# CONFIG_MODBUS is not set + +# +# Network Utilities +# +# CONFIG_NETUTILS_CODECS is not set +# CONFIG_NETUTILS_ESP8266 is not set +# CONFIG_NETUTILS_FTPC is not set +# CONFIG_NETUTILS_JSON is not set +# CONFIG_NETUTILS_SMTP is not set + +# +# NSH Library +# +CONFIG_NSH_LIBRARY=y +# CONFIG_NSH_MOTD is not set + +# +# Command Line Configuration +# +CONFIG_NSH_READLINE=y +# CONFIG_NSH_CLE is not set +CONFIG_NSH_LINELEN=80 +CONFIG_NSH_DISABLE_SEMICOLON=y +# CONFIG_NSH_CMDPARMS is not set +CONFIG_NSH_MAXARGUMENTS=6 +# CONFIG_NSH_ARGCAT is not set +CONFIG_NSH_NESTDEPTH=3 +CONFIG_NSH_DISABLEBG=y +CONFIG_NSH_BUILTIN_APPS=y + +# +# Disable Individual commands +# +CONFIG_NSH_DISABLE_ADDROUTE=y +CONFIG_NSH_DISABLE_BASENAME=y +# CONFIG_NSH_DISABLE_CAT is not set +# CONFIG_NSH_DISABLE_CD is not set +# CONFIG_NSH_DISABLE_CP is not set +CONFIG_NSH_DISABLE_CMP=y +CONFIG_NSH_DISABLE_DATE=y +# CONFIG_NSH_DISABLE_DD is not set +CONFIG_NSH_DISABLE_DF=y +CONFIG_NSH_DISABLE_DELROUTE=y +CONFIG_NSH_DISABLE_DIRNAME=y +# CONFIG_NSH_DISABLE_ECHO is not set +# CONFIG_NSH_DISABLE_EXEC is not set +# CONFIG_NSH_DISABLE_EXIT is not set +# CONFIG_NSH_DISABLE_FREE is not set +# CONFIG_NSH_DISABLE_GET is not set +# CONFIG_NSH_DISABLE_HELP is not set +# CONFIG_NSH_DISABLE_HEXDUMP is not set +CONFIG_NSH_DISABLE_IFCONFIG=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +# CONFIG_NSH_DISABLE_KILL is not set +CONFIG_NSH_DISABLE_LOSETUP=y +CONFIG_NSH_DISABLE_LOSMART=y +# CONFIG_NSH_DISABLE_LS is not set +# CONFIG_NSH_DISABLE_MB is not set +# CONFIG_NSH_DISABLE_MKDIR is not set +# CONFIG_NSH_DISABLE_MKRD is not set +# CONFIG_NSH_DISABLE_MH is not set +# CONFIG_NSH_DISABLE_MOUNT is not set +# CONFIG_NSH_DISABLE_MV is not set +# CONFIG_NSH_DISABLE_MW is not set +CONFIG_NSH_DISABLE_PRINTF=y +# CONFIG_NSH_DISABLE_PS is not set +# CONFIG_NSH_DISABLE_PUT is not set +# CONFIG_NSH_DISABLE_PWD is not set +# CONFIG_NSH_DISABLE_RM is not set +# CONFIG_NSH_DISABLE_RMDIR is not set +# CONFIG_NSH_DISABLE_SET is not set +# CONFIG_NSH_DISABLE_SH is not set +# CONFIG_NSH_DISABLE_SLEEP is not set +CONFIG_NSH_DISABLE_TIME=y +# CONFIG_NSH_DISABLE_TEST is not set +# CONFIG_NSH_DISABLE_UMOUNT is not set +CONFIG_NSH_DISABLE_UNAME=y +# CONFIG_NSH_DISABLE_UNSET is not set +# CONFIG_NSH_DISABLE_USLEEP is not set +# CONFIG_NSH_DISABLE_WGET is not set +# CONFIG_NSH_DISABLE_XD is not set +CONFIG_NSH_MMCSDMINOR=0 + +# +# Configure Command Options +# +# CONFIG_NSH_CMDOPT_DD_STATS is not set +CONFIG_NSH_CODECS_BUFSIZE=128 +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_NSH_FILEIOSIZE=1024 + +# +# Scripting Support +# +# CONFIG_NSH_DISABLESCRIPT is not set +CONFIG_NSH_DISABLE_ITEF=y +CONFIG_NSH_DISABLE_LOOPS=y + +# +# Console Configuration +# +CONFIG_NSH_CONSOLE=y +# CONFIG_NSH_ALTCONDEV is not set +CONFIG_NSH_ARCHINIT=y +# CONFIG_NSH_LOGIN is not set +# CONFIG_NSH_CONSOLE_LOGIN is not set + +# +# NxWidgets/NxWM +# + +# +# Platform-specific Support +# +# CONFIG_PLATFORM_CONFIGDATA is not set + +# +# System Libraries and NSH Add-Ons +# +# CONFIG_SYSTEM_CLE is not set +# CONFIG_SYSTEM_CUTERM is not set +# CONFIG_SYSTEM_FREE is not set +# CONFIG_SYSTEM_HEX2BIN is not set +# CONFIG_SYSTEM_HEXED is not set +# CONFIG_SYSTEM_INSTALL is not set +# CONFIG_SYSTEM_RAMTEST is not set +CONFIG_READLINE_HAVE_EXTMATCH=y +CONFIG_SYSTEM_READLINE=y +CONFIG_READLINE_ECHO=y +# CONFIG_READLINE_TABCOMPLETION is not set +# CONFIG_READLINE_CMD_HISTORY is not set +# CONFIG_SYSTEM_SUDOKU is not set +# CONFIG_SYSTEM_SYSTEM is not set +# CONFIG_SYSTEM_TEE is not set +# CONFIG_SYSTEM_UBLOXMODEM is not set +# CONFIG_SYSTEM_VI is not set +# CONFIG_SYSTEM_ZMODEM is not set + +# +# Wireless Libraries and NSH Add-Ons +# + +# +# IEEE 802.15.4 applications +# +# CONFIG_IEEE802154_LIBMAC is not set +# CONFIG_IEEE802154_LIBUTILS is not set +# CONFIG_IEEE802154_I8SAK is not set diff --git a/configs/stm32f103-minimum/src/Makefile b/configs/stm32f103-minimum/src/Makefile index 8402e553ea..760ac752c7 100644 --- a/configs/stm32f103-minimum/src/Makefile +++ b/configs/stm32f103-minimum/src/Makefile @@ -69,6 +69,10 @@ ifeq ($(CONFIG_AUDIO_TONE),y) CSRCS += stm32_tone.c endif +ifeq ($(CONFIG_CAN_MCP2515),y) +CSRCS += stm32_mcp2515.c +endif + ifeq ($(CONFIG_CL_MFRC522),y) CSRCS += stm32_mfrc522.c endif diff --git a/configs/stm32f103-minimum/src/stm32_bringup.c b/configs/stm32f103-minimum/src/stm32_bringup.c index 2e76db5b8c..14745c88d1 100644 --- a/configs/stm32f103-minimum/src/stm32_bringup.c +++ b/configs/stm32f103-minimum/src/stm32_bringup.c @@ -151,6 +151,13 @@ int stm32_bringup(void) } #endif +#ifdef CONFIG_CAN_MCP2515 + ret = stm32_mcp2515initialize("/dev/can0"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_mcp2515initialize() failed: %d\n", ret); + } +#endif #ifdef CONFIG_CL_MFRC522 ret = stm32_mfrc522initialize("/dev/rfid0"); diff --git a/configs/stm32f103-minimum/src/stm32_mcp2515.c b/configs/stm32f103-minimum/src/stm32_mcp2515.c new file mode 100644 index 0000000000..00d73bd35e --- /dev/null +++ b/configs/stm32f103-minimum/src/stm32_mcp2515.c @@ -0,0 +1,240 @@ +/************************************************************************************ + * configs/stm32f4discovery/src/stm32_mcp2515.c + * + * Copyright (C) 2015 Alan Carvalho de Assis. All rights reserved. + * Author: Alan Carvalho de Assis + * + * 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 + +#include +#include + +#include +#include + +#include "stm32.h" +#include "stm32_spi.h" +#include "stm32f103_minimum.h" + +#if defined(CONFIG_SPI) && defined(CONFIG_STM32_SPI1) && defined(CONFIG_CAN_MCP2515) + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#define MCP2515_SPI_PORTNO 1 /* On SPI1 */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct stm32_mcp2515config_s +{ + /* Configuration structure as seen by the MCP2515 driver */ + + struct mcp2515_config_s config; + + /* Additional private definitions only known to this driver */ + + MCP2515_HANDLE handle; /* The MCP2515 driver handle */ + mcp2515_handler_t handler; /* The MCP2515 interrupt handler */ + FAR void *arg; /* Argument to pass to the interrupt handler */ +}; + +/**************************************************************************** + * Static Function Prototypes + ****************************************************************************/ + +/* IRQ/GPIO access callbacks. These operations all hidden behind callbacks + * to isolate the MCP2515 driver from differences in GPIO interrupt handling + * by varying boards and MCUs. + * + * attach - Attach the MCP2515 interrupt handler to the GPIO interrupt + */ + +static int mcp2515_attach(FAR struct mcp2515_config_s *state, + mcp2515_handler_t handler, FAR void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* A reference to a structure of this type must be passed to the MCP2515 + * driver. This structure provides information about the configuration + * of the MCP2515 and provides some board-specific hooks. + * + * Memory for this structure is provided by the caller. It is not copied + * by the driver and is presumed to persist while the driver is active. The + * memory must be writable because, under certain circumstances, the driver + * may modify frequency or X plate resistance values. + */ + +static struct stm32_mcp2515config_s g_mcp2515config = +{ + .config = + { + .devid = 0, + .nfilters = 6, + .ntxbuffers = 3, + .attach = mcp2515_attach, + }, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* This is the MCP2515 Interupt handler */ + +int mcp2515_interrupt(int irq, FAR void *context) +{ + /* Verify that we have a handler attached */ + + if (g_mcp2515config.handler) + { + /* Yes.. forward with interrupt along with its argument */ + + g_mcp2515config.handler(&g_mcp2515config.config, g_mcp2515config.arg); + } + + return OK; +} + +static int mcp2515_attach(FAR struct mcp2515_config_s *state, + mcp2515_handler_t handler, FAR void *arg) +{ + FAR struct stm32_mcp2515config_s *priv = + (FAR struct stm32_mcp2515config_s *) state; + irqstate_t flags; + + caninfo("Saving handle %p\n", handler); + + flags = enter_critical_section(); + + priv->handler = handler; + priv->arg = arg; + + /* Configure the interrupt for falling edge*/ + + (void)stm32_gpiosetevent(GPIO_MCP2515_IRQ, false, true, false, mcp2515_interrupt, NULL); + + leave_critical_section(flags); + + return OK; +} + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_mcp2515initialize + * + * Description: + * Initialize and register the MCP2515 RFID driver. + * + * Input parameters: + * devpath - The full path to the driver to register. E.g., "/dev/rfid0" + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ************************************************************************************/ + +int stm32_mcp2515initialize(FAR const char *devpath) +{ + FAR struct spi_dev_s *spi; + FAR struct can_dev_s *can; + FAR struct mcp2515_can_s *mcp2515; + int ret; + + /* Check if we are already initialized */ + + if (!g_mcp2515config.handle) + { + sninfo("Initializing\n"); + + /* Configure the MCP2515 interrupt pin as an input */ + + (void)stm32_configgpio(GPIO_MCP2515_IRQ); + + spi = stm32_spibus_initialize(MCP2515_SPI_PORTNO); + + if (!spi) + { + return -ENODEV; + } + + /* Save the SPI instance in the mcp2515_config_s structure */ + + g_mcp2515config.config.spi = spi; + + /* Instantiate the MCP2515 CAN Driver */ + + mcp2515 = mcp2515_instantiate(&g_mcp2515config.config); + if (mcp2515 == NULL) + { + canerr("ERROR: Failed to get MCP2515 Driver Loaded\n"); + return -ENODEV; + } + + /* Save the opaque structure */ + + g_mcp2515config.handle = (MCP2515_HANDLE) mcp2515; + + /* Initialize the CAN Device with the MCP2515 operations */ + + can = mcp2515_initialize(mcp2515); + if (can == NULL) + { + canerr("ERROR: Failed to get CAN interface\n"); + return -ENODEV; + } + + /* Register the CAN driver at "/dev/can0" */ + + ret = can_register(devpath, can); + if (ret < 0) + { + canerr("ERROR: can_register failed: %d\n", ret); + return ret; + } + } + + return OK; +} + +#endif /* CONFIG_SPI && CONFIG_CAN_MCP2515 */ diff --git a/configs/stm32f103-minimum/src/stm32_spi.c b/configs/stm32f103-minimum/src/stm32_spi.c index 0ba7df49d3..ceab4e14d6 100644 --- a/configs/stm32f103-minimum/src/stm32_spi.c +++ b/configs/stm32f103-minimum/src/stm32_spi.c @@ -74,6 +74,10 @@ void stm32_spidev_initialize(void) * architecture. */ +#ifdef CONFIG_CAN_MCP2515 + (void)stm32_configgpio(GPIO_MCP2515_CS); /* MCP2515 chip select */ +#endif + #ifdef CONFIG_CL_MFRC522 (void)stm32_configgpio(GPIO_CS_MFRC522); /* MFRC522 chip select */ #endif @@ -120,6 +124,13 @@ void stm32_spidev_initialize(void) void stm32_spi1select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected) { +#if defined(CONFIG_CAN_MCP2515) + if (devid == SPIDEV_CANBUS(0)) + { + stm32_gpiowrite(GPIO_MCP2515_CS, !selected); + } +#endif + #if defined(CONFIG_CL_MFRC522) if (devid == SPIDEV_WIRELESS(0)) { diff --git a/configs/stm32f103-minimum/src/stm32f103_minimum.h b/configs/stm32f103-minimum/src/stm32f103_minimum.h index 5495596a0b..adabdbc3b0 100644 --- a/configs/stm32f103-minimum/src/stm32f103_minimum.h +++ b/configs/stm32f103-minimum/src/stm32f103_minimum.h @@ -86,6 +86,9 @@ #define STM32_LCD_CS (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN4) +#define GPIO_MCP2515_CS (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ + GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN4) + #define GPIO_NRF24L01_CS (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN4) @@ -114,6 +117,10 @@ #define GPIO_NRF24L01_IRQ (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_PORTA|GPIO_PIN0) +/* MCP2515 IRQ line: PB.0 */ + +#define GPIO_MCP2515_IRQ (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_PORTB|GPIO_PIN0) + /* USB Soft Connect Pullup: PC.13 */ #define GPIO_USB_PULLUP (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ diff --git a/drivers/can/Kconfig b/drivers/can/Kconfig index 577dbea8d1..69b044d274 100644 --- a/drivers/can/Kconfig +++ b/drivers/can/Kconfig @@ -124,4 +124,52 @@ config CAN_NPOLLWAITERS The maximum number of threads that may be waiting on the poll method. +comment "CAN Bus Controllers:" + +config CAN_MCP2515 + bool "Microchip MCP2515 CAN Bus Controller over SPI" + default n + depends on SPI + select ARCH_HAVE_CAN_ERRORS + ---help--- + Enable driver support for Microchip MCP2515. + +if CAN_MCP2515 + +config MCP2515_BITRATE + int "MCP2515 bitrate" + default 500000 + ---help--- + MCP2515 bitrate in bits per second. + +config MCP2515_PROPSEG + int "MCP2515 Propagation Segment TQ" + default 2 + range 1 8 + ---help--- + The length of the bit time is Tquanta * (SyncSeg + PropSeg + PhaseSeg1 + PhaseSeg2). + +config MCP2515_PHASESEG1 + int "MCP2515 Phase Segment 1" + default 2 + range 1 8 + ---help--- + The length of the bit time is Tquanta * (SyncSeg + PropSeg + PhaseSeg1 + PhaseSeg2). + +config MCP2515_PHASESEG2 + int "MCP2515 Phase Segment 2" + default 3 + range 2 8 + ---help--- + The length of the bit time is Tquanta * (SyncSeg + PropSeg + PhaseSeg1 + PhaseSeg2). + +config MCP2515_SJW + int "MCP2515 Synchronization Jump Width" + default 1 + range 1 4 + ---help--- + The duration of a synchronization jump is SJW. + +endif # CAN_MCP2515 + endif # CAN diff --git a/drivers/can/mcp2515.c b/drivers/can/mcp2515.c new file mode 100644 index 0000000000..5a514e48e8 --- /dev/null +++ b/drivers/can/mcp2515.c @@ -0,0 +1,2581 @@ +/**************************************************************************** + * drivers/can/mcp2515.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017 Alan Carvalho de Assis. All rights reserved. + * Author: Alan Carvalho de Assis + * + * 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, Atmel, 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "mcp2515.h" + +#if defined(CONFIG_CAN) && defined(CONFIG_CAN_MCP2515) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Common definitions *******************************************************/ + +/* General Configuration ****************************************************/ + +#ifndef CONFIG_CAN_TXREADY +# warning WARNING!!! CONFIG_CAN_TXREADY is required by this driver +#endif + +/* MCP2515 Configuration ****************************************************/ + +/* Bit timing */ + +#define MCP2515_PROPSEG CONFIG_MCP2515_PROPSEG +#define MCP2515_PHSEG1 CONFIG_MCP2515_PHASESEG1 +#define MCP2515_PHSEG2 CONFIG_MCP2515_PHASESEG2 +#define MCP2515_TSEG1 (MCP2515_PROPSEG + MCP2515_PHSEG1) +#define MCP2515_TSEG2 MCP2515_PHSEG2 +#define MCP2515_BRP ((uint8_t)(((float) MCP2515_CANCLK_FREQUENCY / \ + ((float)(MCP2515_TSEG1 + MCP2515_TSEG2 + 1) * \ + (float)CONFIG_MCP2515_BITRATE)) - 1)) +#define MCP2515_SJW CONFIG_MCP2515_SJW + +#if MCP2515_TSEG1 > 16 +# error Invalid MCP2515 TSEG1 +#endif +#if MCP2515_TSEG2 < 2 +# error Invalid TSEG2. It cannot be lower than 2 +#endif +#if MCP2515_TSEG2 > 8 +# error Invalid TSEG2. It cannot be greater than 8 +#endif +#if MCP2515_SJW > 4 +# error Invalid SJW. It cannot be greater than 4 +#endif + +/* MCP2515 RXB0 element size */ + +/* MCP2515 RXB1 element size */ + +/* MCP2515 Filters */ + +# ifndef CONFIG_MCP2515_NSTDFILTERS +# define CONFIG_MCP2515_NSTDFILTERS 0 +# endif + +# if (CONFIG_MCP2515_NSTDFILTERS > 128) +# error Invalid MCP25150 number of Standard Filters +# endif + +# ifndef CONFIG_MCP2515_NEXTFILTERS +# define CONFIG_MCP2515_NEXTFILTERS 0 +# endif + +# if (CONFIG_MCP2515_NEXTFILTERS > 64) +# error Invalid MCP25150 number of Extended Filters +# endif + +# define MCP2515_STDFILTER_BYTES \ + MCP2515_ALIGN_UP(CONFIG_MCP2515_NSTDFILTERS << 2) +# define MCP2515_STDFILTER_WORDS (MCP2515_STDFILTER_BYTES >> 2) + +# define MCP2515_EXTFILTER_BYTES \ + MCP2515_ALIGN_UP(CONFIG_MCP2515_NEXTFILTERS << 3) +# define MCP2515_EXTFILTER_WORDS (MCP2515_EXTFILTER_BYTES >> 2) + +/* MCP25150 TX buffer element size */ + +/* MCP25150 TX FIFOs */ + +/* Loopback mode */ + +#undef MCP2515_LOOPBACK +#if defined(CONFIG_MCP2515_LOOPBACK) +# define MCP2515_LOOPBACK 1 +#endif + +/* Interrupts ***************************************************************/ +/* Interrupts Errors + * + * MCP2515_INT_MERR - Message Error Interrupt Flag bit + * MCP2515_INT_ERR - Error Interrupt Flag bit (mult src in EFLG register) + */ + +#define MCP2515_ERROR_INTS (MCP2515_INT_MERR | MCP2515_INT_ERR) + +/* RXn buffer interrupts + * + * MCP2515_INT_RX0 - Receive Buffer 0 New Message + * MCP2515_INT_RX1 - Receive Buffer 1 New Message + */ + +#define MCP2515_RXBUFFER_INTS (MCP2515_INT_RX0 | MCP2515_INT_RX1) + +/* TXn buffer interrupts + * + * MCP2515_INT_TX0 - Transmmit Buffer 0 Empty Interrupt + * MCP2515_INT_TX1 - Transmmit Buffer 1 Empty Interrupt + * MCP2515_INT_TX2 - Transmmit Buffer 2 Empty Interrupt + */ + +#define MCP2515_TXBUFFER_INTS (MCP2515_INT_TX0 | MCP2515_INT_TX1 | MCP2515_INT_TX2) + +/* Debug ********************************************************************/ +/* Debug configurations that may be enabled just for testing MCP2515 */ + +#ifndef CONFIG_DEBUG_CAN_INFO +# undef CONFIG_MCP2515_REGDEBUG +#endif + +#ifdef CONFIG_MCP2515_REGDEBUG +# define reginfo caninfo +#else +# define reginfo(x...) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* CAN driver state */ + +enum can_state_s +{ + MCP2515_STATE_UNINIT = 0, /* Not yet initialized */ + MCP2515_STATE_RESET, /* Initialized, reset state */ + MCP2515_STATE_SETUP, /* can_setup() has been called */ +}; + +/* This structure provides the current state of a CAN peripheral */ + +struct mcp2515_can_s +{ + struct mcp2515_config_s *config; /* The constant configuration */ + uint8_t state; /* See enum can_state_s */ + uint8_t nalloc; /* Number of allocated filters */ + sem_t locksem; /* Enforces mutually exclusive access */ + sem_t txfsem; /* Used to wait for TX FIFO availability */ + uint32_t btp; /* Current bit timing */ + uint8_t rxints; /* Configured RX interrupts */ + uint8_t txints; /* Configured TX interrupts */ +#ifdef CONFIG_CAN_ERRORS + uint32_t olderrors; /* Used to detect the changes in error states */ +#endif + uint8_t filters; /* Standard/Extende filter bit allocator. */ + uint8_t ntxbufs; /* Number of allocated TX Buffers */ + uint8_t txbuffers; /* TX Buffers bit allocator. */ + +#ifdef CONFIG_MCP2515_REGDEBUG + uintptr_t regaddr; /* Last register address read */ + uint32_t regval; /* Last value read from the register */ + unsigned int count; /* Number of times that the value was read */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* MCP2515 Register access */ + +static void mcp2515_readregs(FAR struct mcp2515_can_s *priv, uint8_t regaddr, + uint8_t *buffer, uint8_t len); +static void mcp2515_writeregs(FAR struct mcp2515_can_s *priv, uint8_t regaddr, + uint8_t *buffer, uint8_t len); +static void mcp2515_modifyreg(FAR struct mcp2515_can_s *priv, uint8_t regaddr, + uint8_t mask, uint8_t value); +#ifdef CONFIG_MCP2515_REGDEBUG +static void mcp2515_dumpregs(FAR struct mcp2515_can_s *priv, FAR const char *msg); +#else +# define mcp2515_dumpregs(priv,msg) +#endif + +/* Semaphore helpers */ + +static void mcp2515_dev_lock(FAR struct mcp2515_can_s *priv); +#define mcp2515_dev_unlock(priv) sem_post(&priv->locksem) + +/* MCP2515 helpers */ + +#ifdef CONFIG_CAN_EXTID +static int mcp2515_add_extfilter(FAR struct mcp2515_can_s *priv, + FAR struct canioc_extfilter_s *extconfig); +static int mcp2515_del_extfilter(FAR struct mcp2515_can_s *priv, int ndx); +#endif +static int mcp2515_add_stdfilter(FAR struct mcp2515_can_s *priv, + FAR struct canioc_stdfilter_s *stdconfig); +static int mcp2515_del_stdfilter(FAR struct mcp2515_can_s *priv, int ndx); + +/* CAN driver methods */ + +static void mcp2515_reset(FAR struct can_dev_s *dev); +static int mcp2515_setup(FAR struct can_dev_s *dev); +static void mcp2515_shutdown(FAR struct can_dev_s *dev); +static void mcp2515_rxint(FAR struct can_dev_s *dev, bool enable); +static void mcp2515_txint(FAR struct can_dev_s *dev, bool enable); +static int mcp2515_ioctl(FAR struct can_dev_s *dev, int cmd, + unsigned long arg); +static int mcp2515_remoterequest(FAR struct can_dev_s *dev, uint16_t id); +static int mcp2515_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg); +static bool mcp2515_txready(FAR struct can_dev_s *dev); +static bool mcp2515_txempty(FAR struct can_dev_s *dev); + +/* MCP2515 interrupt handling */ + +#ifdef CONFIG_CAN_ERRORS +static void mcp2515_error(FAR struct can_dev_s *dev, uint8_t status, + uint8_t oldstatus); +#endif +static void mcp2515_receive(FAR struct can_dev_s *dev, uint8_t offset); +static int mcp2515_interrupt(FAR struct mcp2515_config_s *config, FAR void *arg); + +/* Hardware initialization */ + +static int mcp2515_hw_initialize(FAR struct mcp2515_can_s *priv); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct can_ops_s g_mcp2515ops = +{ + .co_reset = mcp2515_reset, + .co_setup = mcp2515_setup, + .co_shutdown = mcp2515_shutdown, + .co_rxint = mcp2515_rxint, + .co_txint = mcp2515_txint, + .co_ioctl = mcp2515_ioctl, + .co_remoterequest = mcp2515_remoterequest, + .co_send = mcp2515_send, + .co_txready = mcp2515_txready, + .co_txempty = mcp2515_txempty, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mcp2515_readregs + * + * Description: + * Read value(s) of MCP2515 register(s). + * + * Input Parameters: + * priv - A reference to the MCP2515 peripheral state + * offset - The offset to the register to read + * + * Returned Value: + * + ****************************************************************************/ + +static void mcp2515_readregs(FAR struct mcp2515_can_s *priv, uint8_t regaddr, + uint8_t *buffer, uint8_t len) +{ + FAR struct mcp2515_config_s *config = priv->config; +#ifdef CONFIG_CANBUS_REGDEBUG + int i; +#endif + + (void)SPI_LOCK(config->spi, true); + + /* Select the MCP2515 */ + + SPI_SELECT(config->spi, SPIDEV_CANBUS(0), true); + + /* Send the READ command */ + + (void)SPI_SEND(config->spi, MCP2515_READ); + + /* Send register to read and get the next bytes read back */ + + (void)SPI_SEND(config->spi, regaddr); + SPI_RECVBLOCK(config->spi, buffer, len); + + /* Deselect the MCP2515 */ + + SPI_SELECT(config->spi, SPIDEV_CANBUS(0), false); + + /* Unlock bus */ + + (void)SPI_LOCK(config->spi, false); + +#ifdef CONFIG_CANBUS_REGDEBUG + for (i = 0; i < len; i++) + { + caninfo("%02x->%02x\n", regaddr, buffer[i]); + } +#endif +} + +/**************************************************************************** + * Name: mcp2515_writeregs + * + * Description: + * Set the value of a MCP2515 register. + * + * Input Parameters: + * priv - A reference to the MCP2515 peripheral state + * offset - The offset to the register to write + * regval - The value to write to the register + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void mcp2515_writeregs(FAR struct mcp2515_can_s *priv, uint8_t regaddr, + uint8_t *buffer, uint8_t len) +{ + FAR struct mcp2515_config_s *config = priv->config; +#ifdef CONFIG_CANBUS_REGDEBUG + int i; + + for (i = 0; i < len; i++) + { + caninfo("%02x<-%02x\n", regaddr+i, buffer[i]); + } +#endif + + (void)SPI_LOCK(config->spi, true); + + /* Select the MCP2515 */ + + SPI_SELECT(config->spi, SPIDEV_CANBUS(0), true); + + /* Send the READ command */ + + (void)SPI_SEND(config->spi, MCP2515_WRITE); + + /* Send initial register to be written */ + + (void)SPI_SEND(config->spi, regaddr); + SPI_SNDBLOCK(config->spi, buffer, len); + + /* Deselect the MCP2515 */ + + SPI_SELECT(config->spi, SPIDEV_CANBUS(0), false); + + /* Unlock bus */ + + (void)SPI_LOCK(config->spi, false); + +} + +/**************************************************************************** + * Name: mcp2515_modifyreg + * + * Description: + * Modify individuals bits of MCP2515 register + * + * Input Parameters: + * priv - A reference to the MCP2515 peripheral state + * offset - The offset to the register to write + * regval - The value to write to the register + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void mcp2515_modifyreg(FAR struct mcp2515_can_s *priv, uint8_t regaddr, + uint8_t mask, uint8_t value) +{ + FAR struct mcp2515_config_s *config = priv->config; + + (void)SPI_LOCK(config->spi, true); + + /* Select the MCP2515 */ + + SPI_SELECT(config->spi, SPIDEV_CANBUS(0), true); + + /* Send the Modify command */ + + (void)SPI_SEND(config->spi, MCP2515_BITMOD); + + /* Send the register address */ + + (void)SPI_SEND(config->spi, regaddr); + + /* Send the mask */ + + (void)SPI_SEND(config->spi, mask); + + /* Send the value */ + + (void)SPI_SEND(config->spi, value); + + /* Deselect the MCP2515 */ + + SPI_SELECT(config->spi, SPIDEV_CANBUS(0), false); + + /* Unlock bus */ + + (void)SPI_LOCK(config->spi, false); + +} + +/**************************************************************************** + * Name: mcp2515_dumpregs + * + * Description: + * Dump the contents of all MCP2515 control registers + * + * Input Parameters: + * priv - A reference to the MCP2515 peripheral state + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_MCP2515_REGDEBUG +static void mcp2515_dumpregs(FAR struct mcp2515_can_s *priv, FAR const char *msg) +{ + FAR struct mcp2515_config_s *config = priv->config; +} +#endif + +/**************************************************************************** + * Name: mcp2515_dev_lock + * + * Description: + * Take the semaphore that enforces mutually exclusive access to device + * structures, handling any exceptional conditions + * + * Input Parameters: + * priv - A reference to the MCP2515 peripheral state + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void mcp2515_dev_lock(FAR struct mcp2515_can_s *priv) +{ + int ret; + + /* Wait until we successfully get the semaphore. EINTR is the only + * expected 'failure' (meaning that the wait for the semaphore was + * interrupted by a signal. + */ + + do + { + ret = sem_wait(&priv->locksem); + DEBUGASSERT(ret == 0 || errno == EINTR); + } + while (ret < 0); +} + +/**************************************************************************** + * Name: mcp2515_add_extfilter + * + * Description: + * Add an address filter for a extended 29 bit address. + * + * Input Parameters: + * priv - An instance of the MCP2515 driver state structure. + * extconfig - The configuration of the extended filter + * + * Returned Value: + * A non-negative filter ID is returned on success. Otherwise a negated + * errno value is returned to indicate the nature of the error. + * + ****************************************************************************/ + +#ifdef CONFIG_CAN_EXTID +static int mcp2515_add_extfilter(FAR struct mcp2515_can_s *priv, + FAR struct canioc_extfilter_s *extconfig) +{ + FAR struct mcp2515_config_s *config; + uint8_t regval; + uint8_t offset; + uint8_t mode = CAN_FILTER_MASK; + int ndx; + + DEBUGASSERT(priv != NULL && priv->config != NULL); + config = priv->config; + + /* Get exclusive excess to the MCP2515 hardware */ + + mcp2515_dev_lock(priv); + + /* Find an unused standard filter */ + + for (ndx = 0; ndx < config->nfilters; ndx++) + { + /* Is this filter assigned? */ + + if ((priv->filters & (1 << ndx)) == 0) + { + /* No, assign the filter */ + + DEBUGASSERT(priv->nalloc < priv->config->nfilters); + priv->filters |= (1 << ndx); + priv->nalloc++; + + /* Format and write filter */ + + DEBUGASSERT(extconfig->sf_id1 <= CAN_MAX_STDMSGID); + + DEBUGASSERT(extconfig->sf_id2 <= CAN_MAX_STDMSGID); + + /* We can reach all RXFn registers (RXFnSIDH, RXFnSIDL, + * RXFnEID8 and RXFnEID0) using this formula: + * + * filterN = RXF0reg + offset + ((priv->nalloc - 1) * 4) ; + * maskN = RXM0reg + offset + */ + + if (priv->nalloc <= 3) + { + offset = 0; + } + else + { + offset = 4; + } + +#if 0 + /* N.B. Buffer 0 is higher priority than Buffer 1 + * but to separate these messages we will make this + * driver more complex. So let to consider that the + * first 2 IDs inserted in the filter will have more + * priority than the latest 4 IDs*/ + + if (extconfig->sf_prio == CAN_MSGPRIO_LOW) + { + /* Use RXB1 filters */ + } + else + { + /* Use RXB0 filters */ + } +#endif + + switch (extconfig->xf_type) + { + default: + case CAN_FILTER_DUAL: + mode = CAN_FILTER_DUAL; + break; + + case CAN_FILTER_MASK: + mode = CAN_FILTER_MASK; + break; + + case CAN_FILTER_RANGE: + /* not supported */ + break; + } + + /* Setup the CONFIG Mode */ + + mcp2515_readregs(priv, MCP2515_CANCTRL, ®val, 1); + regval = (regval & ~CANCTRL_REQOP_MASK) | (CANCTRL_REQOP_CONFIG); + mcp2515_writeregs(priv, MCP2515_CANCTRL, ®val, 1); + + if (mode == CAN_FILTER_DUAL) + { + /* The MSD IDs will be filtered by separated Mask and Filter */ + + /* Setup the Filter */ + + /* EID0 - EID7 */ + + regval = (uint8_t) (extconfig->xf_id1 & 0xff); + mcp2515_writeregs(priv, MCP2515_RXF0EID0 + offset + + ((priv->nalloc - 1) * 4), ®val, 1); + + /* EID8 - EID15 */ + + regval = (uint8_t) ((extconfig->xf_id1 & 0xff00) >> 8); + mcp2515_writeregs(priv, MCP2515_RXF0EID8 + offset + + ((priv->nalloc - 1) * 4), ®val, 1); + + /* EID16 - EID17 */ + + regval = (uint8_t) ((extconfig->xf_id1 & 0x30000) >> 16); + + /* STD0 - STD2*/ + + regval = (regval) | (uint8_t) (((extconfig->xf_id1 & 0x1C0000) >> 16) << 3); + mcp2515_writeregs(priv, MCP2515_RXF0SIDL + offset + + ((priv->nalloc - 1) * 4), ®val, 1); + + /* STD3 - STD10 */ + + regval = (uint8_t) ((extconfig->xf_id1 & 0x1fe00000 ) >> 21); + regval |= RXFSIDL_EXIDE; + mcp2515_writeregs(priv, MCP2515_RXF0SIDL + offset + + ((priv->nalloc - 1) * 4), ®val, 1); + + /* Setup the Mask */ + + /* EID0 - EID7 */ + + regval = (uint8_t) (extconfig->xf_id2 & 0xff); + mcp2515_writeregs(priv, MCP2515_RXM0EID0 + offset, ®val, 1); + + /* EID8 - EID15 */ + + regval = (uint8_t) ((extconfig->xf_id2 & 0xff00) >> 8); + mcp2515_writeregs(priv, MCP2515_RXM0EID8 + offset, ®val, 1); + + /* EID16 - EID17 */ + + regval = (uint8_t) ((extconfig->xf_id2 & 0x30000) >> 16); + + /* STD0 - STD2*/ + + regval = (regval) | (uint8_t) (((extconfig->xf_id2 & 0x1c0000) >> 16) << 3); + mcp2515_writeregs(priv, MCP2515_RXM0SIDL + offset, ®val, 1); + + /* STD3 - STD10 */ + + regval = (uint8_t) ((extconfig->xf_id2 & 0x1fe00000 ) >> 21); + mcp2515_writeregs(priv, MCP2515_RXM0SIDL + offset, ®val, 1); + } + else + { + /* The IDs will be filtered only by the Filter register (Mask == Filter) */ + + /* Setup the Filter */ + + /* EID0 - EID7 */ + + regval = (uint8_t) (extconfig->xf_id1 & 0xff); + mcp2515_writeregs(priv, MCP2515_RXF0EID0 + offset + + ((priv->nalloc - 1) * 4), ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXM0EID0 + offset, ®val, 1); + + /* EID8 - EID15 */ + + regval = (uint8_t) ((extconfig->xf_id1 & 0xff00) >> 8); + mcp2515_writeregs(priv, MCP2515_RXF0EID8 + offset + + ((priv->nalloc - 1) * 4), ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXM0EID8 + offset, ®val, 1); + + /* EID16 - EID17 */ + + regval = (uint8_t) ((extconfig->xf_id1 & 0x30000) >> 16); + + /* STD0 - STD2 */ + + regval = (regval) | (uint8_t) (((extconfig->xf_id1 & + 0x1c0000) >> 16) << 3) | RXFSIDL_EXIDE; + mcp2515_writeregs(priv, MCP2515_RXF0SIDL + offset + + ((priv->nalloc - 1) * 4), ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXM0SIDL + offset, ®val, 1); + + /* STD3 - STD10 */ + + regval = (uint8_t) ((extconfig->xf_id1 & 0x1fe00000 ) >> 21); + mcp2515_writeregs(priv, MCP2515_RXF0SIDL + offset + + ((priv->nalloc - 1) * 4), ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXF0SIDL + offset, ®val, 1); + } + + /* Leave the Configuration mode, Move to Normal mode */ + + mcp2515_readregs(priv, MCP2515_CANCTRL, ®val, 1); + regval = (regval & ~CANCTRL_REQOP_MASK) | (CANCTRL_REQOP_NORMAL); + mcp2515_writeregs(priv, MCP2515_CANCTRL, ®val, 1); + + mcp2515_dev_unlock(priv); + return ndx; + } + } + + DEBUGASSERT(priv->nstdalloc == priv->config->nstdfilters); + mcp2515_dev_unlock(priv); + return -EAGAIN; +} +#endif + +/**************************************************************************** + * Name: mcp2515_del_extfilter + * + * Description: + * Remove an address filter for a standard 29 bit address. + * + * Input Parameters: + * priv - An instance of the MCP2515 driver state structure. + * ndx - The filter index previously returned by the mcp2515_add_extfilter(). + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise a negated errno value is + * returned to indicate the nature of the error. + * + ****************************************************************************/ + +#ifdef CONFIG_CAN_EXTID +static int mcp2515_del_extfilter(FAR struct mcp2515_can_s *priv, int ndx) +{ + FAR struct mcp2515_config_s *config; + uint8_t regval; + uint8_t offset; + + DEBUGASSERT(priv != NULL && priv->config != NULL); + config = priv->config; + + /* Check Userspace Parameters */ + + DEBUGASSERT(ndx >= 0 || ndx < config->nfilters); + + caninfo("ndx = %d\n", ndx); + + if (ndx < 0 || ndx >= config->nfilters) + { + return -EINVAL; + } + + /* Get exclusive excess to the MCP2515 hardware */ + + mcp2515_dev_lock(priv); + + /* Check if this filter is really assigned */ + + if ((priv->filters & (1 << ndx)) == 0) + { + /* No, error out */ + + mcp2515_dev_unlock(priv); + return -ENOENT; + } + + /* Release the filter */ + + priv->filters &= ~(1 << ndx); + + DEBUGASSERT(priv->nalloc > 0); + priv->nalloc--; + + /* We can reach all RXFn registers (RXFnSIDH, RXFnSIDL, + * RXFnEID8 and RXFnEID0) using this formula: + * + * filterN = RXF0reg + offset + ((priv->nalloc - 1) * 4) ; + * maskN = RXM0reg + offset + */ + + if (ndx < 3) + { + offset = 0; + } + else + { + offset = 4; + } + + /* Setup the CONFIG Mode */ + + mcp2515_readregs(priv, MCP2515_CANCTRL, ®val, 1); + regval = (regval & ~CANCTRL_REQOP_MASK) | (CANCTRL_REQOP_CONFIG); + mcp2515_writeregs(priv, MCP2515_CANCTRL, ®val, 1); + + /* Invalidate this filter, set its ID to 0 */ + + regval = 0; + mcp2515_writeregs(priv, MCP2515_RXF0SIDH + offset + (ndx * 4), ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXF0SIDL + offset + (ndx * 4), ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXF0EID8 + offset + (ndx * 4), ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXF0EID0 + offset + (ndx * 4), ®val, 1); + + /* Leave the Configuration mode, Move to Normal mode */ + + mcp2515_readregs(priv, MCP2515_CANCTRL, ®val, 1); + regval = (regval & ~CANCTRL_REQOP_MASK) | (CANCTRL_REQOP_NORMAL); + mcp2515_writeregs(priv, MCP2515_CANCTRL, ®val, 1); + + mcp2515_dev_unlock(priv); + return OK; +} +#endif + +/**************************************************************************** + * Name: mcp2515_add_stdfilter + * + * Description: + * Add an address filter for a standard 11 bit address. + * + * Input Parameters: + * priv - An instance of the MCP2515 driver state structure. + * stdconfig - The configuration of the standard filter + * + * Returned Value: + * A non-negative filter ID is returned on success. Otherwise a negated + * errno value is returned to indicate the nature of the error. + * + ****************************************************************************/ + +static int mcp2515_add_stdfilter(FAR struct mcp2515_can_s *priv, + FAR struct canioc_stdfilter_s *stdconfig) +{ + FAR struct mcp2515_config_s *config; + uint8_t regval; + uint8_t offset; + uint8_t mode = CAN_FILTER_MASK; + int ndx; + + DEBUGASSERT(priv != NULL && priv->config != NULL); + config = priv->config; + + /* Get exclusive excess to the MCP2515 hardware */ + + mcp2515_dev_lock(priv); + + /* Find an unused standard filter */ + + for (ndx = 0; ndx < config->nfilters; ndx++) + { + /* Is this filter assigned? */ + + if ((priv->filters & (1 << ndx)) == 0) + { + /* No, assign the filter */ + + DEBUGASSERT(priv->nalloc < priv->config->nfilters); + priv->filters |= (1 << ndx); + priv->nalloc++; + + /* Format and write filter */ + + DEBUGASSERT(stdconfig->sf_id1 <= CAN_MAX_STDMSGID); + + DEBUGASSERT(stdconfig->sf_id2 <= CAN_MAX_STDMSGID); + + /* We can reach all RXFn registers (RXFnSIDH, RXFnSIDL, + * RXFnEID8 and RXFnEID0) using this formula: + * + * filterN = RXF0reg + offset + ((priv->nalloc - 1) * 4) ; + * maskN = RXM0reg + offset + */ + + if (priv->nalloc <= 3) + { + offset = 0; + } + else + { + offset = 4; + } + +#if 0 + /* N.B. Buffer 0 is higher priority than Buffer 1 + * but to separate these messages we will make this + * driver more complex. So let to consider that the + * first 2 IDs inserted in the filter will have more + * priority than the latest 4 IDs*/ + + if (stdconfig->sf_prio == CAN_MSGPRIO_LOW) + { + /* Use RXB1 filters */ + } + else + { + /* Use RXB0 filters */ + } +#endif + + switch (stdconfig->sf_type) + { + default: + case CAN_FILTER_DUAL: + mode = CAN_FILTER_DUAL; + break; + + case CAN_FILTER_MASK: + mode = CAN_FILTER_MASK; + break; + + case CAN_FILTER_RANGE: + /* not supported */ + break; + } + + /* Setup the CONFIG Mode */ + + mcp2515_readregs(priv, MCP2515_CANCTRL, ®val, 1); + regval = (regval & ~CANCTRL_REQOP_MASK) | (CANCTRL_REQOP_CONFIG); + mcp2515_writeregs(priv, MCP2515_CANCTRL, ®val, 1); + + if (mode == CAN_FILTER_DUAL) + { + /* The MSD IDs will be filtered by separated Mask and Filter */ + + /* Setup the Filter */ + + regval = (uint8_t) (((stdconfig->sf_id1) & 0x7f8) >> 3); + mcp2515_writeregs(priv, MCP2515_RXF0SIDH + offset + + ((priv->nalloc - 1) * 4), ®val, 1); + + regval = (uint8_t) ((stdconfig->sf_id1 & 0x07 ) << 5); + mcp2515_writeregs(priv, MCP2515_RXF0SIDL + offset + + ((priv->nalloc - 1) * 4), ®val, 1); + + /* Setup the Mask */ + + regval = (uint8_t) (((stdconfig->sf_id2) & 0x7f8) >> 3); + mcp2515_writeregs(priv, MCP2515_RXM0SIDH + offset, ®val, 1); + + regval = (uint8_t) ((stdconfig->sf_id2 & 0x07 ) << 5); + mcp2515_writeregs(priv, MCP2515_RXM0SIDL + offset, ®val, 1); + } + else + { + /* The IDs will be filtered only by the Filter register (Mask == Filter) */ + + /* Setup the Filter */ + + regval = (uint8_t) (((stdconfig->sf_id1) & 0x7f8) >> 3); + mcp2515_writeregs(priv, MCP2515_RXF0SIDH + offset + + ((priv->nalloc - 1) * 4), ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXM0SIDH + offset, ®val, 1); + + regval = (uint8_t) ((stdconfig->sf_id1 & 0x07 ) << 5); + mcp2515_writeregs(priv, MCP2515_RXF0SIDL + offset + + ((priv->nalloc - 1) * 4), ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXM0SIDL + offset, ®val, 1); + } + + /* We need to clear the extended ID bits */ + + regval = 0; + mcp2515_writeregs(priv, MCP2515_RXF0EID0 + offset + + ((priv->nalloc - 1) * 4), ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXF0EID8 + offset + + ((priv->nalloc - 1) * 4), ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXM0EID0 + offset, ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXM0EID8 + offset, ®val, 1); + + /* Leave the Configuration mode, Move to Normal mode */ + + mcp2515_readregs(priv, MCP2515_CANCTRL, ®val, 1); + regval = (regval & ~CANCTRL_REQOP_MASK) | (CANCTRL_REQOP_NORMAL); + mcp2515_writeregs(priv, MCP2515_CANCTRL, ®val, 1); + + mcp2515_dev_unlock(priv); + return ndx; + } + } + + DEBUGASSERT(priv->nstdalloc == priv->config->nstdfilters); + mcp2515_dev_unlock(priv); + return -EAGAIN; +} + +/**************************************************************************** + * Name: mcp2515_del_stdfilter + * + * Description: + * Remove an address filter for a standard 29 bit address. + * + * Input Parameters: + * priv - An instance of the MCP2515 driver state structure. + * ndx - The filter index previously returned by the mcp2515_add_stdfilter(). + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise a negated errno value is + * returned to indicate the nature of the error. + * + ****************************************************************************/ + +static int mcp2515_del_stdfilter(FAR struct mcp2515_can_s *priv, int ndx) +{ + FAR struct mcp2515_config_s *config; + uint8_t regval; + uint8_t offset; + + DEBUGASSERT(priv != NULL && priv->config != NULL); + config = priv->config; + + /* Check Userspace Parameters */ + + DEBUGASSERT(ndx >= 0 || ndx < config->nfilters); + + caninfo("ndx = %d\n", ndx); + + if (ndx < 0 || ndx >= config->nfilters) + { + return -EINVAL; + } + + /* Get exclusive excess to the MCP2515 hardware */ + + mcp2515_dev_lock(priv); + + /* Check if this filter is really assigned */ + + if ((priv->filters & (1 << ndx)) == 0) + { + /* No, error out */ + + mcp2515_dev_unlock(priv); + return -ENOENT; + } + + /* Release the filter */ + + priv->filters &= ~(1 << ndx); + + DEBUGASSERT(priv->nalloc > 0); + priv->nalloc--; + + /* We can reach all RXFn registers (RXFnSIDH, RXFnSIDL, + * RXFnEID8 and RXFnEID0) using this formula: + * + * filterN = RXF0reg + offset + ((priv->nalloc - 1) * 4) ; + * maskN = RXM0reg + offset + */ + + if (ndx < 3) + { + offset = 0; + } + else + { + offset = 4; + } + + /* Setup the CONFIG Mode */ + + mcp2515_readregs(priv, MCP2515_CANCTRL, ®val, 1); + regval = (regval & ~CANCTRL_REQOP_MASK) | (CANCTRL_REQOP_CONFIG); + mcp2515_writeregs(priv, MCP2515_CANCTRL, ®val, 1); + + /* Invalidade this filter, set its ID to 0 */ + + regval = 0; + mcp2515_writeregs(priv, MCP2515_RXF0SIDH + offset + (ndx * 4), ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXF0SIDL + offset + (ndx * 4), ®val, 1); + + /* Leave the Configuration mode, Move to Normal mode */ + + mcp2515_readregs(priv, MCP2515_CANCTRL, ®val, 1); + regval = (regval & ~CANCTRL_REQOP_MASK) | (CANCTRL_REQOP_NORMAL); + mcp2515_writeregs(priv, MCP2515_CANCTRL, ®val, 1); + + mcp2515_dev_unlock(priv); + return OK; +} + +/**************************************************************************** + * Name: mcp2515_reset_lowlevel + * + * Description: + * Reset the MCP2515 device. Called early to initialize the hardware. This + * function is called, before mcp2515_setup() and on error conditions. + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void mcp2515_reset_lowlevel(FAR struct mcp2515_can_s *priv) +{ + FAR struct mcp2515_config_s *config; + + DEBUGASSERT(priv); + config = priv->config; + DEBUGASSERT(config); + + UNUSED(config); + + /* Get exclusive access to the MCP2515 peripheral */ + + mcp2515_dev_lock(priv); + + /* Send SPI reset command to MCP2515 */ + + SPI_LOCK(config->spi, true); + SPI_SELECT(config->spi, SPIDEV_CANBUS(0), true); + SPI_SEND(config->spi, MCP2515_RESET); + SPI_LOCK(config->spi, false); + + /* Wait 1ms to let MCP2515 restart */ + + usleep(1000); + + /* Make sure that all buffers are released. + * + * REVISIT: What if a thread is waiting for a buffer? The following + * will not wake up any waiting threads. + */ + + sem_destroy(&priv->txfsem); + sem_init(&priv->txfsem, 0, config->ntxbuffers); + + /* Define the current state and unlock */ + + priv->state = MCP2515_STATE_RESET; + mcp2515_dev_unlock(priv); +} + +/**************************************************************************** + * Name: mcp2515_reset + * + * Description: + * Reset the MCP2515 device. Called early to initialize the hardware. This + * function is called, before mcp2515_setup() and on error conditions. + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void mcp2515_reset(FAR struct can_dev_s *dev) +{ + FAR struct mcp2515_can_s *priv; + + DEBUGASSERT(dev); + priv = dev->cd_priv; + DEBUGASSERT(priv); + + /* Execute the reset */ + + mcp2515_reset_lowlevel(priv); + +} + +/**************************************************************************** + * Name: mcp2515_setup + * + * Description: + * Configure the MCP2515. This method is called the first time that the MCP2515 + * device is opened. This will occur when the device file is first opened. + * This setup includes configuring and attaching MCP2515 interrupts. + * All MCP2515 interrupts are disabled upon return. + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int mcp2515_setup(FAR struct can_dev_s *dev) +{ + FAR struct mcp2515_can_s *priv; + FAR struct mcp2515_config_s *config; + int ret; + + DEBUGASSERT(dev); + priv = dev->cd_priv; + DEBUGASSERT(priv); + config = priv->config; + DEBUGASSERT(config); + + //caninfo("MCP2515%d pid: %d\n", config->port, config->pid); + + /* Get exclusive access to the MCP2515 peripheral */ + + mcp2515_dev_lock(priv); + + /* MCP2515 hardware initialization */ + + ret = mcp2515_hw_initialize(priv); + if (ret < 0) + { + canerr("ERROR: MCP2515%d H/W initialization failed: %d\n", config->devid, ret); + return ret; + } + + /* Attach the MCP2515 interrupt handler. */ + + ret = config->attach(config, (mcp2515_handler_t)mcp2515_interrupt, (FAR void *)dev); + if (ret < 0) + { + canerr("ERROR: Failed to attach to IRQ Handler!\n"); + return ret; + } + + /* Enable receive interrupts */ + + priv->state = MCP2515_STATE_SETUP; + mcp2515_rxint(dev, true); + + mcp2515_dev_unlock(priv); + return OK; +} + +/**************************************************************************** + * Name: mcp2515_shutdown + * + * Description: + * Disable the MCP2515. This method is called when the MCP2515 device is closed. + * This method reverses the operation the setup method. + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void mcp2515_shutdown(FAR struct can_dev_s *dev) +{ + /* Nothing to do here! */ +} + +/**************************************************************************** + * Name: mcp2515_rxint + * + * Description: + * Call to enable or disable RX interrupts. + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void mcp2515_rxint(FAR struct can_dev_s *dev, bool enable) +{ + FAR struct mcp2515_can_s *priv; + FAR struct mcp2515_config_s *config; + irqstate_t flags; + uint8_t regval; + + DEBUGASSERT(dev); + priv = dev->cd_priv; + DEBUGASSERT(priv); + config = priv->config; + DEBUGASSERT(config); + + caninfo("CAN%d enable: %d\n", config->devid, enable); + + /* Enable/disable the receive interrupts */ + + flags = enter_critical_section(); + + mcp2515_readregs(priv, MCP2515_CANINTE, ®val, 1); + + if (enable) + { + regval |= priv->rxints | MCP2515_ERROR_INTS; + } + else + { + regval &= ~priv->rxints; + } + + mcp2515_writeregs(priv, MCP2515_CANINTE, ®val, 1); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: mcp2515_txint + * + * Description: + * Call to enable or disable TX interrupts. + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void mcp2515_txint(FAR struct can_dev_s *dev, bool enable) +{ + FAR struct mcp2515_can_s *priv = dev->cd_priv; + irqstate_t flags; + uint8_t regval; + + DEBUGASSERT(priv && priv->config); + + caninfo("CAN%d enable: %d\n", priv->config->devid, enable); + + /* Enable/disable the receive interrupts */ + + flags = enter_critical_section(); + mcp2515_readregs(priv, MCP2515_CANINTE, ®val, 1); + + if (enable) + { + regval |= priv->txints | MCP2515_ERROR_INTS; + } + else + { + regval &= ~priv->txints; + } + + mcp2515_writeregs(priv, MCP2515_CANINTE, ®val, 1); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: mcp2515_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int mcp2515_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg) +{ + FAR struct mcp2515_can_s *priv; + int ret = -ENOTTY; + + caninfo("cmd=%04x arg=%lu\n", cmd, arg); + + DEBUGASSERT(dev && dev->cd_priv); + priv = dev->cd_priv; + + /* Handle the command */ + + switch (cmd) + { + /* CANIOC_GET_BITTIMING: + * Description: Return the current bit timing settings + * Argument: A pointer to a write-able instance of struct + * canioc_bittiming_s in which current bit timing values + * will be returned. + * Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR) + * is returned with the errno variable set to indicate the + * nature of the error. + * Dependencies: None + */ + + case CANIOC_GET_BITTIMING: + { + FAR struct canioc_bittiming_s *bt = + (FAR struct canioc_bittiming_s *)arg; + uint8_t regval; + uint8_t brp; + + DEBUGASSERT(bt != NULL); + + mcp2515_readregs(priv, MCP2515_CNF1, ®val, 1); + bt->bt_sjw = ((regval & CNF1_SJW_MASK) >> CNF1_SJW_SHIFT) + 1; + brp = ((regval & CNF1_BRP_MASK) >> CNF1_BRP_SHIFT) + 1; + + mcp2515_readregs(priv, MCP2515_CNF2, ®val, 1); + bt->bt_tseg1 = ((regval & CNF2_PRSEG_MASK) >> CNF2_PRSEG_SHIFT) + 1; + bt->bt_tseg1 += ((regval & CNF2_PHSEG1_MASK) >> CNF2_PHSEG1_SHIFT) + 1; + + mcp2515_readregs(priv, MCP2515_CNF3, ®val, 1); + bt->bt_tseg2 = ((regval & CNF3_PHSEG2_MASK) >> CNF3_PHSEG2_SHIFT) + 1; + + bt->bt_baud = MCP2515_CANCLK_FREQUENCY / brp / + (bt->bt_tseg1 + bt->bt_tseg2 + 1); + ret = OK; + } + break; + + /* CANIOC_SET_BITTIMING: + * Description: Set new current bit timing values + * Argument: A pointer to a read-able instance of struct + * canioc_bittiming_s in which the new bit timing values + * are provided. + * Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR) + * is returned with the errno variable set to indicate the + * nature of the error. + * Dependencies: None + * + * REVISIT: There is probably a limitation here: If there are multiple + * threads trying to send CAN packets, when one of these threads reconfigures + * the bitrate, the MCP2515 hardware will be reset and the context of operation + * will be lost. Hence, this IOCTL can only safely be executed in quiescent + * time periods. + */ + + case CANIOC_SET_BITTIMING: + { + FAR const struct canioc_bittiming_s *bt = + (FAR const struct canioc_bittiming_s *)arg; + irqstate_t flags; + uint8_t brp; + uint8_t sjw; + uint8_t tseg1; + uint8_t tseg2; + uint8_t prseg; + uint8_t phseg1; + uint8_t regval; + + DEBUGASSERT(bt != NULL); + DEBUGASSERT(bt->bt_baud < MCP2515_CANCLK_FREQUENCY); + DEBUGASSERT(bt->bt_sjw > 0 && bt->bt_sjw <= 4); + DEBUGASSERT(bt->bt_tseg1 > 1 && bt->bt_tseg1 <= 16); + DEBUGASSERT(bt->bt_tseg2 > 1 && bt->bt_tseg2 <= 8); + DEBUGASSERT(bt->bt_tseg1 > bt->bt_tseg2); + DEBUGASSERT(bt->bt_tseg2 > bt->bt_sjw); + + /* Extract bit timing data */ + + tseg1 = bt->bt_tseg1 - 1; + tseg2 = bt->bt_tseg2 - 1; + sjw = bt->bt_sjw - 1; + + /* PRSEG = TSEG1 - PHSEG1 + * Because we don't have PHSEG1 then let us to assume: + * PHSEG1 == PHSEG2 (PHSEG2 = TSEG2) + * + * See more at: + * + * http://www.analog.com/en/analog-dialogue/articles/configure-can-bit-timing.html + */ + + phseg1 = tseg2; + prseg = tseg1 - phseg1; + + brp = (uint32_t) + (((float) MCP2515_CANCLK_FREQUENCY / + ((float)(tseg1 + tseg2 + 1) * (float)bt->bt_baud)) - 1); + + /* Save the value of the new bit timing register */ + + flags = enter_critical_section(); + + /* Setup the CONFIG Mode */ + + mcp2515_readregs(priv, MCP2515_CANCTRL, ®val, 1); + regval = (regval & ~CANCTRL_REQOP_MASK) | (CANCTRL_REQOP_CONFIG); + mcp2515_writeregs(priv, MCP2515_CANCTRL, ®val, 1); + + /* Setup CNF1 register */ + + mcp2515_readregs(priv, MCP2515_CNF1, ®val, 1); + regval = (regval & ~CNF1_BRP_MASK) | (brp << CNF1_BRP_SHIFT); + regval = (regval & ~CNF1_SJW_MASK) | ((sjw) << CNF1_SJW_SHIFT); + mcp2515_writeregs(priv, MCP2515_CNF1, ®val, 1); + + /* Setup CNF2 register */ + + mcp2515_readregs(priv, MCP2515_CNF2, ®val, 1); + regval = (regval & ~CNF2_PRSEG_MASK) | ((prseg - 1) << CNF2_PRSEG_SHIFT); + regval = (regval & ~CNF2_PHSEG1_MASK) | (phseg1 << CNF2_PHSEG1_SHIFT); + regval = (regval | CNF2_SAM | CNF2_BTLMODE); + mcp2515_writeregs(priv, MCP2515_CNF2, ®val, 1); + + /* Setup CNF3 register */ + + mcp2515_readregs(priv, MCP2515_CNF3, ®val, 1); + regval = (regval & ~CNF3_PHSEG2_MASK) | (tseg2 << CNF3_PHSEG2_SHIFT); + regval = (regval | CNF3_SOF); + mcp2515_writeregs(priv, MCP2515_CNF3, ®val, 1); + + /* Leave the Configuration mode, Move to Normal mode */ + + mcp2515_readregs(priv, MCP2515_CANCTRL, ®val, 1); + regval = (regval & ~CANCTRL_REQOP_MASK) | (CANCTRL_REQOP_NORMAL); + mcp2515_writeregs(priv, MCP2515_CANCTRL, ®val, 1); + + leave_critical_section(flags); + + ret = OK; + } + break; + +#ifdef CONFIG_CAN_EXTID + /* CANIOC_ADD_EXTFILTER: + * Description: Add an address filter for a extended 29 bit + * address. + * Argument: A reference to struct canioc_extfilter_s + * Returned Value: A non-negative filter ID is returned on success. + * Otherwise -1 (ERROR) is returned with the errno + * variable set to indicate the nature of the error. + */ + + case CANIOC_ADD_EXTFILTER: + { + DEBUGASSERT(arg != 0); + ret = mcp2515_add_extfilter(priv, (FAR struct canioc_extfilter_s *)arg); + } + break; + + /* CANIOC_DEL_EXTFILTER: + * Description: Remove an address filter for a standard 29 bit address. + * Argument: The filter index previously returned by the + * CANIOC_ADD_EXTFILTER command + * Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR) + * is returned with the errno variable set to indicate the + * nature of the error. + */ + + case CANIOC_DEL_EXTFILTER: + { + FAR int *ndx = (FAR int *)((uintptr_t)arg); + + DEBUGASSERT(*ndx <= priv->config->nfilters); + ret = mcp2515_del_extfilter(priv, (int)*ndx); + } + break; +#endif + + /* CANIOC_ADD_STDFILTER: + * Description: Add an address filter for a standard 11 bit + * address. + * Argument: A reference to struct canioc_stdfilter_s + * Returned Value: A non-negative filter ID is returned on success. + * Otherwise -1 (ERROR) is returned with the errno + * variable set to indicate the nature of the error. + */ + + case CANIOC_ADD_STDFILTER: + { + DEBUGASSERT(arg != 0); + ret = mcp2515_add_stdfilter(priv, (FAR struct canioc_stdfilter_s *)arg); + } + break; + + /* CANIOC_DEL_STDFILTER: + * Description: Remove an address filter for a standard 11 bit address. + * Argument: The filter index previously returned by the + * CANIOC_ADD_STDFILTER command + * Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR) + * is returned with the errno variable set to indicate the + * nature of the error. + */ + + case CANIOC_DEL_STDFILTER: + { + FAR int *ndx = (FAR int *)((uintptr_t)arg); + + DEBUGASSERT(*ndx <= priv->config->nfilters); + ret = mcp2515_del_stdfilter(priv, (int)*ndx); + } + break; + + /* Unsupported/unrecognized command */ + + default: + canerr("ERROR: Unrecognized command: %04x\n", cmd); + break; + } + + return ret; +} + +/**************************************************************************** + * Name: mcp2515_remoterequest + * + * Description: + * Send a remote request + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int mcp2515_remoterequest(FAR struct can_dev_s *dev, uint16_t id) +{ + /* REVISIT: Remote request not implemented */ + + return -ENOSYS; +} + +/**************************************************************************** + * Name: mcp2515_send + * + * Description: + * Send one can message. + * + * One CAN-message consists of a maximum of 10 bytes. A message is + * composed of at least the first 2 bytes (when there are no data bytes). + * + * Byte 0: Bits 0-7: Bits 3-10 of the 11-bit CAN identifier + * Byte 1: Bits 5-7: Bits 0-2 of the 11-bit CAN identifier + * Bit 4: Remote Transmission Request (RTR) + * Bits 0-3: Data Length Code (DLC) + * Bytes 2-10: CAN data + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int mcp2515_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg) +{ + FAR struct mcp2515_can_s *priv; + FAR struct mcp2515_config_s *config; + uint8_t regval; + uint8_t offset; + unsigned int nbytes; + unsigned int i; + + DEBUGASSERT(dev); + priv = dev->cd_priv; + DEBUGASSERT(priv && priv->config); + config = priv->config; + + caninfo("CAN%d\n", config->devid); + caninfo("CAN%d ID: %d DLC: %d\n", + config->devid, msg->cm_hdr.ch_id, msg->cm_hdr.ch_dlc); + + /* That that FIFO elements were configured. + * + * REVISIT: Dedicated TX buffers are not used by this driver. + */ + + DEBUGASSERT(config->ntxbuffers > 0); + + /* Select one empty transmit buffer */ + + mcp2515_readregs(priv, MCP2515_TXB0CTRL, ®val, 1); + if ((regval & TXBCTRL_TXREQ) == 0) + { + offset = MCP2515_TX0_OFFSET; + } + else + { + mcp2515_readregs(priv, MCP2515_TXB1CTRL, ®val, 1); + if ((regval & TXBCTRL_TXREQ) == 0) + { + offset = MCP2515_TX1_OFFSET; + } + else + { + mcp2515_readregs(priv, MCP2515_TXB2CTRL, ®val, 1); + if ((regval & TXBCTRL_TXREQ) == 0) + { + offset = MCP2515_TX2_OFFSET; + } + else + { + canerr("ERROR: No available transmit buffer!\n"); + return -EBUSY; + } + } + } + + /* Get exclusive access to the MCP2515 peripheral */ + + mcp2515_dev_lock(priv); + + /* Setup the MCP2515 TX Buffer with the message to send */ + +#ifdef CONFIG_CAN_EXTID + if (msg->cm_hdr.ch_extid) + { + DEBUGASSERT(msg->cm_hdr.ch_id <= CAN_MAX_EXTMSGID); + + /* EID7 - EID0 */ + + regval = (msg->cm_hdr.ch_id & 0xff); + mcp2515_writeregs(priv, MCP2515_TXB0EID0 + offset, ®val, 1); + + /* EID15 - EID8 */ + + regval = (msg->cm_hdr.ch_id & 0xff00) >> 8; + mcp2515_writeregs(priv, MCP2515_TXB0EID8 + offset, ®val, 1); + + /* EID17 and EID16 */ + + regval = (msg->cm_hdr.ch_id & 0x30000) >> 16; + regval |= TXBSIDL_EXIDE; + + /* STD2 - STD0 */ + + regval |= (msg->cm_hdr.ch_id & 0x1c0000) >> 18; + mcp2515_writeregs(priv, MCP2515_TXB0SIDL + offset, ®val, 1); + + /* STD10 - STD3 */ + + regval = (msg->cm_hdr.ch_id & 0x1fe00000) >> 21; + mcp2515_writeregs(priv, MCP2515_TXB0SIDH + offset, ®val, 1); + } + else +#endif + { + DEBUGASSERT(msg->cm_hdr.ch_id <= CAN_MAX_STDMSGID); + + /* Setup the Standard ID of the message to send */ + + /* STD10 - STD3 */ + + regval = (msg->cm_hdr.ch_id & 0x7f8) >> 3; + mcp2515_writeregs(priv, MCP2515_TXB0SIDH + offset, ®val, 1); + + /* STD2 - STD0 */ + + regval = (msg->cm_hdr.ch_id & 0x007) << 5; + mcp2515_writeregs(priv, MCP2515_TXB0SIDL + offset, ®val, 1); + } + + /* Setup the DLC */ + + regval = (msg->cm_hdr.ch_dlc & 0xf); + + if (msg->cm_hdr.ch_rtr) + { + regval |= TXBDLC_RTR; + } + + mcp2515_writeregs(priv, MCP2515_TXB0DLC + offset, ®val, 1); + + /* Fill the data buffer */ + + nbytes = msg->cm_hdr.ch_dlc; + + for (i = 0; i < nbytes; i++) + { + /* Little endian is assumed */ + + regval = msg->cm_data[i]; + mcp2515_writeregs(priv, MCP2515_TXB0D0 + offset + i, ®val, 1); + } + + /* And request to send the message */ + + mcp2515_readregs(priv, MCP2515_TXB0CTRL, ®val, 1); + regval |= TXBCTRL_TXREQ; + mcp2515_writeregs(priv, MCP2515_TXB0CTRL, ®val, 1); + + mcp2515_dev_unlock(priv); + + /* Report that the TX transfer is complete to the upper half logic. Of + * course, the transfer is not complete, but this early notification + * allows the upper half logic to free resources sooner. + * + * REVISIT: Should we disable interrupts? can_txdone() was designed to + * be called from an interrupt handler and, hence, may be unsafe when + * called from the tasking level. + */ + + (void)can_txdone(dev); + return OK; +} + +/**************************************************************************** + * Name: mcp2515_txready + * + * Description: + * Return true if the MCP2515 hardware can accept another TX message. + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * True if the MCP2515 hardware is ready to accept another TX message. + * + ****************************************************************************/ + +static bool mcp2515_txready(FAR struct can_dev_s *dev) +{ + FAR struct mcp2515_can_s *priv; + uint8_t regval; + bool empty; + + DEBUGASSERT(dev); + priv = dev->cd_priv; + DEBUGASSERT(priv); + + /* That that FIFO elements were configured. + * + * REVISIT: Dedicated TX buffers are not used by this driver. + */ + + DEBUGASSERT(config->ntxbuffers > 0); + + /* Get exclusive access to the MCP2515 peripheral */ + + mcp2515_dev_lock(priv); + + /* Select one empty transmit buffer */ + + mcp2515_readregs(priv, MCP2515_TXB0CTRL, ®val, 1); + if ((regval & TXBCTRL_TXREQ) == 0) + { + empty = true; + } + else + { + mcp2515_readregs(priv, MCP2515_TXB1CTRL, ®val, 1); + if ((regval & TXBCTRL_TXREQ) == 0) + { + empty = true; + } + else + { + mcp2515_readregs(priv, MCP2515_TXB2CTRL, ®val, 1); + if ((regval & TXBCTRL_TXREQ) == 0) + { + empty = true; + } + else + { + empty = false; + } + } + } + + mcp2515_dev_unlock(priv); + + return empty; +} + +/**************************************************************************** + * Name: mcp2515_txempty + * + * Description: + * Return true if all message have been sent. If for example, the MCP2515 + * hardware implements FIFOs, then this would mean the transmit FIFO is + * empty. This method is called when the driver needs to make sure that + * all characters are "drained" from the TX hardware before calling + * co_shutdown(). + * + * Input Parameters: + * dev - An instance of the "upper half" can driver state structure. + * + * Returned Value: + * True if there are no pending TX transfers in the MCP2515 hardware. + * + ****************************************************************************/ + +static bool mcp2515_txempty(FAR struct can_dev_s *dev) +{ + FAR struct mcp2515_can_s *priv; + uint8_t regval; + bool empty; + + DEBUGASSERT(dev); + priv = dev->cd_priv; + DEBUGASSERT(priv); + + /* That that FIFO elements were configured. + * + * REVISIT: Dedicated TX buffers are not used by this driver. + */ + + DEBUGASSERT(config->ntxbuffers > 0); + + /* Get exclusive access to the MCP2515 peripheral */ + + mcp2515_dev_lock(priv); + + /* Select one empty transmit buffer */ + + mcp2515_readregs(priv, MCP2515_TXB0CTRL, ®val, 1); + if ((regval & TXBCTRL_TXREQ) != 0) + { + empty = false; + } + else + { + mcp2515_readregs(priv, MCP2515_TXB1CTRL, ®val, 1); + if ((regval & TXBCTRL_TXREQ) != 0) + { + empty = false; + } + else + { + mcp2515_readregs(priv, MCP2515_TXB2CTRL, ®val, 1); + if ((regval & TXBCTRL_TXREQ) != 0) + { + empty = false; + } + else + { + empty = true; + } + } + } + + mcp2515_dev_unlock(priv); + + return empty; +} + +/**************************************************************************** + * Name: mcp2515_error + * + * Description: + * Report a CAN error + * + * Input Parameters: + * dev - CAN-common state data + * status - Interrupt status with error bits set + * oldstatus - Previous Interrupt status with error bits set + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_CAN_ERRORS +static void mcp2515_error(FAR struct can_dev_s *dev, uint8_t status, + uint8_t oldstatus) +{ + FAR struct mcp2515_can_s *priv = dev->cd_priv; + struct can_hdr_s hdr; + uint8_t eflg; + uint8_t txerr; + uint8_t txb0err; + uint8_t txb1err; + uint8_t txb2err; + uint16_t errbits; + uint8_t data[CAN_ERROR_DLC]; + int ret; + + /* Encode error bits */ + + errbits = 0; + memset(data, 0, sizeof(data)); + + /* Please note that MCP2515_CANINTF only reports if an error + * happened. It doesn't report what error it is. + * We need to check EFLG and TXBnCTRL to discover. + */ + + mcp2515_readregs(priv, MCP2515_EFLG, &eflg, 1); + if (eflg & EFLG_TXBO) + { + errbits |= CAN_ERROR_BUSOFF; + } + + if (eflg & EFLG_RXEP) + { + data[1] |= CAN_ERROR1_RXPASSIVE; + } + + if (eflg & EFLG_TXEP) + { + data[1] |= CAN_ERROR1_TXPASSIVE; + } + + if (eflg & EFLG_RXWAR) + { + data[1] |= CAN_ERROR1_RXWARNING; + } + + if (eflg & EFLG_TXWAR) + { + data[1] |= CAN_ERROR1_TXWARNING; + } + + if (eflg & (EFLG_RX0OVR | EFLG_RX1OVR)) + { + data[1] |= CAN_ERROR1_RXOVERFLOW; + } + + /* Verify Message Error */ + + mcp2515_readregs(priv, MCP2515_TXB0CTRL, &txb0err, 1); + mcp2515_readregs(priv, MCP2515_TXB1CTRL, &txb1err, 1); + mcp2515_readregs(priv, MCP2515_TXB2CTRL, &txb2err, 1); + + txerr = txb0err | txb1err | txb2err; + + if (txerr & (TXBCTRL_MLOA)) + { + errbits |= CAN_ERROR_LOSTARB; + } + + if (txerr & (TXBCTRL_ABTF)) + { + errbits |= CAN_ERROR_LOSTARB; + } + + if (txerr & (TXBCTRL_MLOA)) + { + data[0] |= CAN_ERROR0_UNSPEC; + } + + if ((status & (MCP2515_INT_ERR | MCP2515_INT_MERR)) != 0) + { + /* If Message Error or Other error */ + + errbits |= CAN_ERROR_CONTROLLER; + } + else if ((oldstatus & (MCP2515_INT_ERR | MCP2515_INT_MERR)) != 0) + { + errbits |= CAN_ERROR_CONTROLLER; + } + + if (errbits != 0) + { + /* Format the CAN header for the error report. */ + + hdr.ch_id = errbits; + hdr.ch_dlc = CAN_ERROR_DLC; + hdr.ch_rtr = 0; + hdr.ch_error = 1; +#ifdef CONFIG_CAN_EXTID + hdr.ch_extid = 0; +#endif + hdr.ch_unused = 0; + + /* And provide the error report to the upper half logic */ + + ret = can_receive(dev, &hdr, data); + if (ret < 0) + { + canerr("ERROR: can_receive failed: %d\n", ret); + } + } +} +#endif /* CONFIG_CAN_ERRORS */ + +/**************************************************************************** + * Name: mcp2515_receive + * + * Description: + * Receive an MCP2515 messages + * + * Input Parameters: + * dev - CAN-common state data + * rxbuffer - The RX buffer containing the received messages + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void mcp2515_receive(FAR struct can_dev_s *dev, uint8_t offset) +{ + FAR struct mcp2515_can_s *priv; + struct can_hdr_s hdr; + int ret; + uint8_t regval; + uint8_t data[CAN_MAXDATALEN]; + + DEBUGASSERT(dev); + priv = dev->cd_priv; + DEBUGASSERT(priv); + + /* Format the CAN header */ + + /* Get the CAN identifier. */ + + mcp2515_readregs(priv, MCP2515_RXB0SIDL + offset, ®val, 1); + +#ifdef CONFIG_CAN_EXTID + if ((regval & RXBSIDL_IDE) != 0) + { + + /* Save the extended ID of the newly received message */ + + /* EID7 - EID0 */ + + mcp2515_readregs(priv, MCP2515_RXB0EID0 + offset, ®val, 1); + hdr.ch_id = regval ; + + /* EID15 - EID8 */ + + mcp2515_readregs(priv, MCP2515_RXB0EID8 + offset, ®val, 1); + hdr.ch_id = hdr.ch_id | (regval << 8); + + /* EID17 and EID16 */ + + mcp2515_readregs(priv, MCP2515_RXB0SIDL + offset, ®val, 1); + hdr.ch_id = hdr.ch_id | ((regval & RXBSIDL_EID_MASK) << 16); + + /* STD2 - STD0 */ + + hdr.ch_id = hdr.ch_id | ((regval >> 5) << 18); + + /* STD10 - STD3 */ + + mcp2515_readregs(priv, MCP2515_RXB0SIDH + offset, ®val, 1); + hdr.ch_id = hdr.ch_id | (regval << 21); + hdr.ch_extid = true; + } + else + { + /* Save the standard ID of the newly received message */ + + mcp2515_readregs(priv, MCP2515_RXB0SIDH + offset, ®val, 1); + hdr.ch_id = regval; + mcp2515_readregs(priv, MCP2515_RXB0SIDL + offset, ®val, 1); + hdr.ch_id = (hdr.ch_id << 3) | (regval >> 5); + hdr.ch_extid = false; + } + +#else + if ((regval & RXBSIDL_IDE) != 0) + { + /* Drop any messages with extended IDs */ + + canerr("ERROR: Extended MSG in Standard Mode\n"); + + return; + } + + /* Save the standard ID of the newly received message */ + + mcp2515_readregs(priv, MCP2515_RXB0SIDH + offset, ®val, 1); + hdr.ch_id = regval; + mcp2515_readregs(priv, MCP2515_RXB0SIDL + offset, ®val, 1); + hdr.ch_id = (hdr.ch_id << 3) | (regval >> 5); +#endif + +#ifdef CONFIG_CAN_ERRORS + hdr.ch_error = 0; /* Error reporting not supported */ +#endif + hdr.ch_unused = 0; + + /* Extract the RTR bit */ + + mcp2515_readregs(priv, MCP2515_RXB0CTRL, ®val, 1); + hdr.ch_rtr = (regval & RXBCTRL_RXRTR) != 0; + + /* Get the DLC */ + + mcp2515_readregs(priv, MCP2515_RXB0DLC, ®val, 1); + hdr.ch_dlc = (regval & RXBDLC_DLC_MASK) >> RXBDLC_DLC_SHIFT; + + /* Save the message data */ + + mcp2515_readregs(priv, MCP2515_RXB0D0, data, (uint8_t) hdr.ch_dlc); + + ret = can_receive(dev, &hdr, (FAR uint8_t *) data); + + if (ret < 0) + { + canerr("ERROR: can_receive failed: %d\n", ret); + } +} + +/**************************************************************************** + * Name: mcp2515_interrupt + * + * Description: + * Common MCP2515 interrupt handler + * + * Input Parameters: + * dev - CAN-common state data + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int mcp2515_interrupt(FAR struct mcp2515_config_s *config, FAR void *arg) +{ + FAR struct can_dev_s *dev = (FAR struct can_dev_s *)arg; + FAR struct mcp2515_can_s *priv; + uint8_t ir; + uint8_t ie; + uint8_t pending; + bool handled; + + DEBUGASSERT(dev); + priv = dev->cd_priv; + DEBUGASSERT(priv != NULL); + DEBUGASSERT(priv && priv->config); + + /* Loop while there are pending interrupt events */ + + do + { + /* Get the set of pending interrupts. */ + + mcp2515_readregs(priv, MCP2515_CANINTF, &ir, 1); + mcp2515_readregs(priv, MCP2515_CANINTE, &ie, 1); + + pending = (ir & ie); + handled = false; + + /* Check for any errors */ + + if ((pending & MCP2515_ERROR_INTS) != 0) + { + /* Clear interrupt errors */ + + mcp2515_modifyreg(priv, MCP2515_CANINTF, MCP2515_ERROR_INTS, ~MCP2515_ERROR_INTS); + +#ifdef CONFIG_CAN_ERRORS + /* Report errors */ + + mcp2515_error(dev, pending & MCP2515_ERROR_INTS, priv->olderrors); + + priv->olderrors = (pending & MCP2515_ERROR_INTS); +#endif + handled = true; + } +#ifdef CONFIG_CAN_ERRORS + else if (priv->olderrors != 0) + { + /* All (old) errors cleared */ + + canerr("ERROR: CLEARED\n"); + + mcp2515_error(dev, 0, priv->olderrors); + + priv->olderrors = 0; + handled = true; + } +#endif + + /* Check for successful completion of a transmission */ + + if ((pending & MCP2515_TXBUFFER_INTS) != 0) + { + /* Clear the pending TX completion interrupt (and all + * other TX-related interrupts) + */ + + if (pending & MCP2515_INT_TX0) + { + caninfo("TX0 is empty to transmit new message!\n"); + + /* Clear TX0 interrupt */ + + mcp2515_modifyreg(priv, MCP2515_CANINTF, MCP2515_INT_TX0, ~MCP2515_INT_TX0); + } + + if (pending & MCP2515_INT_TX1) + { + caninfo("TX1 is empty to transmit new message!\n"); + + /* Clear TX1 interrupt */ + + mcp2515_modifyreg(priv, MCP2515_CANINTF, MCP2515_INT_TX1, ~MCP2515_INT_TX1); + } + + if (pending & MCP2515_INT_TX2) + { + caninfo("TX2 is empty to transmit new message!\n"); + + /* Clear TX2 interrupt */ + + mcp2515_modifyreg(priv, MCP2515_CANINTF, MCP2515_INT_TX2, ~MCP2515_INT_TX2); + } + + handled = true; + +#ifdef CONFIG_CAN_TXREADY + /* Inform the upper half driver that we are again ready to accept + * data in mcp2515_send(). + */ + + (void)can_txready(dev); +#endif + } + else if ((pending & priv->txints) != 0) + { + /* Clear unhandled TX events */ + + //mcp2515_putreg(priv, MCP2515_IR_OFFSET, priv->txints); + handled = true; + } + + /* Check if there is a new message to read */ + + if ((pending & MCP2515_RXBUFFER_INTS) != 0) + { + /* RX Buffer 0 is the "high priority" buffer: We will process + * all messages in RXB0 before processing any message from RX + * RXB1. + */ + + if ((pending & MCP2515_INT_RX0) != 0) + { + mcp2515_receive(dev, MCP2515_RX0_OFFSET); + + /* Clear RX0 interrupt */ + + mcp2515_modifyreg(priv, MCP2515_CANINTF, MCP2515_INT_RX0, ~MCP2515_INT_RX0); + } + else + { + if ((pending & MCP2515_INT_RX1) != 0) + { + mcp2515_receive(dev, MCP2515_RX1_OFFSET); + + /* Clear RX1 interrupt */ + + mcp2515_modifyreg(priv, MCP2515_CANINTF, MCP2515_INT_RX1, ~MCP2515_INT_RX1); + } + } + + /* Acknowledge reading the FIFO entry */ + handled = true; + } + } + while (handled); + + return OK; +} + +/**************************************************************************** + * Name: mcp2515_hw_initialize + * + * Description: + * MCP2515 hardware initialization + * + * Input Parameter: + * priv - A pointer to the private data structure for this MCP2515 peripheral + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int mcp2515_hw_initialize(struct mcp2515_can_s *priv) +{ + FAR struct mcp2515_config_s *config = priv->config; + uint8_t regval; + + caninfo("CAN%d\n", config->devid); + + /* Setup CNF1 register */ + + mcp2515_readregs(priv, MCP2515_CNF1, ®val, 1); + regval = (regval & ~CNF1_BRP_MASK) | (MCP2515_BRP << CNF1_BRP_SHIFT); + regval = (regval & ~CNF1_SJW_MASK) | ((MCP2515_SJW - 1) << CNF1_SJW_SHIFT); + mcp2515_writeregs(priv, MCP2515_CNF1, ®val, 1); + + /* Setup CNF2 register */ + + mcp2515_readregs(priv, MCP2515_CNF2, ®val, 1); + regval = (regval & ~CNF2_PRSEG_MASK) | ((MCP2515_PROPSEG - 1) << CNF2_PRSEG_SHIFT); + regval = (regval & ~CNF2_PHSEG1_MASK) | ((MCP2515_PHSEG1 - 1) << CNF2_PHSEG1_SHIFT); + regval = (regval | CNF2_SAM | CNF2_BTLMODE); + mcp2515_writeregs(priv, MCP2515_CNF2, ®val, 1); + + /* Setup CNF3 register */ + + mcp2515_readregs(priv, MCP2515_CNF3, ®val, 1); + regval = (regval & ~CNF3_PHSEG2_MASK) | ((MCP2515_PHSEG2 - 1) << CNF3_PHSEG2_SHIFT); + regval = (regval | CNF3_SOF); + mcp2515_writeregs(priv, MCP2515_CNF3, ®val, 1); + + /* Mask all messages to be received */ + + mcp2515_readregs(priv, MCP2515_RXB0CTRL, ®val, 1); + regval = (regval & ~RXBCTRL_RXM_MASK) | (RXBCTRL_RXM_ALLVALID << RXBCTRL_RXM_SHIFT); + regval = (regval | RXB0CTRL_BUKT); /* Enable Rollover from RXB0 to RXB1 */ + mcp2515_writeregs(priv, MCP2515_RXB0CTRL, ®val, 1); + + mcp2515_readregs(priv, MCP2515_RXB1CTRL, ®val, 1); + regval = (regval & ~RXBCTRL_RXM_MASK) | (RXBCTRL_RXM_ALLVALID << RXBCTRL_RXM_SHIFT); + mcp2515_writeregs(priv, MCP2515_RXB1CTRL, ®val, 1); + + regval = 0x00; + mcp2515_writeregs(priv, MCP2515_RXM0SIDH, ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXM0SIDL, ®val, 1); +#ifdef CONFIG_CAN_EXTID + mcp2515_writeregs(priv, MCP2515_RXM0EID8, ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXM0EID0, ®val, 1); +#endif + + mcp2515_writeregs(priv, MCP2515_RXM1SIDH, ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXM1SIDL, ®val, 1); +#ifdef CONFIG_CAN_EXTID + mcp2515_writeregs(priv, MCP2515_RXM1EID8, ®val, 1); + mcp2515_writeregs(priv, MCP2515_RXM1EID0, ®val, 1); +#endif + +#ifdef CONFIG_CAN_EXTID + mcp2515_modifyreg(priv, MCP2515_RXM0SIDL, RXFSIDL_EXIDE, RXFSIDL_EXIDE); + mcp2515_modifyreg(priv, MCP2515_RXM1SIDL, RXFSIDL_EXIDE, RXFSIDL_EXIDE); +#endif + + /* Leave the Configuration mode, Move to Normal mode */ + + mcp2515_readregs(priv, MCP2515_CANCTRL, ®val, 1); + regval = (regval & ~CANCTRL_REQOP_MASK) | (CANCTRL_REQOP_NORMAL); + mcp2515_writeregs(priv, MCP2515_CANCTRL, ®val, 1); + + usleep(100); + + /* Read the CANINTF */ + + mcp2515_readregs(priv, MCP2515_CANINTF, ®val, 1); + caninfo("CANINFT = 0x%02X\n", regval); + +#ifdef MCP2515_LOOPBACK + /* Is loopback mode selected for this peripheral? */ + + if (config->loopback) + { + /* To Be Implemented */ + } +#endif + + /* Configure interrupt lines */ + + /* Select RX-related interrupts */ + + priv->rxints = MCP2515_RXBUFFER_INTS; + + /* Select TX-related interrupts */ + + priv->txints = MCP2515_TXBUFFER_INTS; + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mcp2515_instantiate + * + * Description: + * Initialize the selected MCP2515 CAN Bus Controller over SPI + * + * Input Parameter: + * config - The configuration structure passed by the board. + * + * Returned Value: + * Valid CAN device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +FAR struct mcp2515_can_s *mcp2515_instantiate(FAR struct mcp2515_config_s *config) +{ + FAR struct mcp2515_can_s *priv; + uint8_t canctrl; + + caninfo("Starting mcp2515_instantiate()!\n"); + + priv = (FAR struct mcp2515_can_s *)kmm_malloc(sizeof(struct mcp2515_can_s)); + if (priv == NULL) + { + canerr("ERROR: Failed to allocate instance of mcp2515_can_s!\n"); + return NULL; + } + + /* Setup SPI frequency and mode */ + + SPI_SETFREQUENCY(config->spi, MCP2515_SPI_FREQUENCY); + SPI_SETMODE(config->spi, MCP2515_SPI_MODE); + SPI_SETBITS(config->spi, 8); + (void)SPI_HWFEATURES(config->spi, 0); + + /* Perform one time data initialization */ + + memset(priv, 0, sizeof(struct mcp2515_can_s)); + priv->config = config; + + /* Set the initial bit timing. This might change subsequently + * due to IOCTL command processing. + */ + + //priv->btp = config->btp; + //priv->fbtp = config->fbtp; + + /* Initialize semaphores */ + + sem_init(&priv->locksem, 0, 1); + sem_init(&priv->txfsem, 0, config->ntxbuffers); + + /* And put the hardware in the initial state */ + + mcp2515_reset_lowlevel(priv); + + /* Probe the MCP2515 to confirm it was detected */ + + mcp2515_readregs(priv, MCP2515_CANCTRL, &canctrl, 1); + + if (canctrl != DEFAULT_CANCTRL_CONFMODE) + { + canerr("ERROR: CANCTRL = 0x%02X ! It should be 0x87\n", canctrl); + return NULL; + } + + /* Return our private data structure as an opaque handle */ + + return (MCP2515_HANDLE)priv; +} + +/**************************************************************************** + * Name: mcp2515_initialize + * + * Description: + * Initialize the selected MCP2515 CAN Bus Controller over SPI + * + * Input Parameter: + * config - The configuration structure passed by the board. + * + * Returned Value: + * Valid CAN device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +FAR struct can_dev_s *mcp2515_initialize(FAR struct mcp2515_can_s *mcp2515can) +{ + FAR struct can_dev_s *dev; + + caninfo("Starting mcp2515_initialize()!\n"); + + /* Allocate a CAN Device structure */ + + dev = (FAR struct can_dev_s *)kmm_malloc(sizeof(struct can_dev_s)); + if (dev == NULL) + { + canerr("ERROR: Failed to allocate instance of can_dev_s!\n"); + return NULL; + } + + dev->cd_ops = &g_mcp2515ops; + dev->cd_priv = (FAR void *)mcp2515can; + + return dev; +} + +#endif /* CONFIG_CAN && CONFIG_MCP2515 */ diff --git a/drivers/can/mcp2515.h b/drivers/can/mcp2515.h new file mode 100644 index 0000000000..2b9c981572 --- /dev/null +++ b/drivers/can/mcp2515.h @@ -0,0 +1,397 @@ +/* Register Addresses */ + +#define MCP2515_RXF0SIDH 0x00 +#define MCP2515_RXF0SIDL 0x01 +#define MCP2515_RXF0EID8 0x02 +#define MCP2515_RXF0EID0 0x03 +#define MCP2515_RXF1SIDH 0x04 +#define MCP2515_RXF1SIDL 0x05 +#define MCP2515_RXF1EID8 0x06 +#define MCP2515_RXF1EID0 0x07 +#define MCP2515_RXF2SIDH 0x08 +#define MCP2515_RXF2SIDL 0x09 +#define MCP2515_RXF2EID8 0x0a +#define MCP2515_RXF2EID0 0x0b +#define MCP2515_BFPCTRL 0x0c +#define MCP2515_TXRTSCTRL 0x0d +#define MCP2515_CANSTAT 0x0e +#define MCP2515_CANCTRL 0x0f +#define MCP2515_RXF3SIDH 0x10 +#define MCP2515_RXF3SIDL 0x11 +#define MCP2515_RXF3EID8 0x12 +#define MCP2515_RXF3EID0 0x13 +#define MCP2515_RXF4SIDH 0x14 +#define MCP2515_RXF4SIDL 0x15 +#define MCP2515_RXF4EID8 0x16 +#define MCP2515_RXF4EID0 0x17 +#define MCP2515_RXF5SIDH 0x18 +#define MCP2515_RXF5SIDL 0x19 +#define MCP2515_RXF5EID8 0x1a +#define MCP2515_RXF5EID0 0x1b +#define MCP2515_TEC 0x1c +#define MCP2515_REC 0x1d +#define MCP2515_RXM0SIDH 0x20 +#define MCP2515_RXM0SIDL 0x21 +#define MCP2515_RXM0EID8 0x22 +#define MCP2515_RXM0EID0 0x23 +#define MCP2515_RXM1SIDH 0x24 +#define MCP2515_RXM1SIDL 0x25 +#define MCP2515_RXM1EID8 0x26 +#define MCP2515_RXM1EID0 0x27 +#define MCP2515_CNF3 0x28 +#define MCP2515_CNF2 0x29 +#define MCP2515_CNF1 0x2a +#define MCP2515_CANINTE 0x2b +#define MCP2515_CANINTF 0x2c +#define MCP2515_EFLG 0x2d +#define MCP2515_TXB0CTRL 0x30 +#define MCP2515_TXB0SIDH 0x31 +#define MCP2515_TXB0SIDL 0x32 +#define MCP2515_TXB0EID8 0x33 +#define MCP2515_TXB0EID0 0x34 +#define MCP2515_TXB0DLC 0x35 +#define MCP2515_TXB0D0 0x36 +#define MCP2515_TXB0D1 0x37 +#define MCP2515_TXB0D2 0x38 +#define MCP2515_TXB0D3 0x39 +#define MCP2515_TXB0D4 0x3a +#define MCP2515_TXB0D5 0x3b +#define MCP2515_TXB0D6 0x3c +#define MCP2515_TXB0D7 0x3d +#define MCP2515_TXB1CTRL 0x40 +#define MCP2515_TXB1SIDH 0x41 +#define MCP2515_TXB1SIDL 0x42 +#define MCP2515_TXB1EID8 0x43 +#define MCP2515_TXB1EID0 0x44 +#define MCP2515_TXB1DLC 0x45 +#define MCP2515_TXB1D0 0x46 +#define MCP2515_TXB1D1 0x47 +#define MCP2515_TXB1D2 0x48 +#define MCP2515_TXB1D3 0x49 +#define MCP2515_TXB1D4 0x4a +#define MCP2515_TXB1D5 0x4b +#define MCP2515_TXB1D6 0x4c +#define MCP2515_TXB1D7 0x4d +#define MCP2515_TXB2CTRL 0x50 +#define MCP2515_TXB2SIDH 0x51 +#define MCP2515_TXB2SIDL 0x52 +#define MCP2515_TXB2EID8 0x53 +#define MCP2515_TXB2EID0 0x54 +#define MCP2515_TXB2DLC 0x55 +#define MCP2515_TXB2D0 0x56 +#define MCP2515_TXB2D1 0x57 +#define MCP2515_TXB2D2 0x58 +#define MCP2515_TXB2D3 0x59 +#define MCP2515_TXB2D4 0x5a +#define MCP2515_TXB2D5 0x5b +#define MCP2515_TXB2D6 0x5c +#define MCP2515_TXB2D7 0x5d +#define MCP2515_RXB0CTRL 0x60 +#define MCP2515_RXB0SIDH 0x61 +#define MCP2515_RXB0SIDL 0x62 +#define MCP2515_RXB0EID8 0x63 +#define MCP2515_RXB0EID0 0x64 +#define MCP2515_RXB0DLC 0x65 +#define MCP2515_RXB0D0 0x66 +#define MCP2515_RXB0D1 0x67 +#define MCP2515_RXB0D2 0x68 +#define MCP2515_RXB0D3 0x69 +#define MCP2515_RXB0D4 0x6a +#define MCP2515_RXB0D5 0x6b +#define MCP2515_RXB0D6 0x6c +#define MCP2515_RXB0D7 0x6d +#define MCP2515_RXB1CTRL 0x70 +#define MCP2515_RXB1SIDH 0x71 +#define MCP2515_RXB1SIDL 0x72 +#define MCP2515_RXB1EID8 0x73 +#define MCP2515_RXB1EID0 0x74 +#define MCP2515_RXB1DLC 0x75 +#define MCP2515_RXB1D0 0x76 +#define MCP2515_RXB1D1 0x77 +#define MCP2515_RXB1D2 0x78 +#define MCP2515_RXB1D3 0x79 +#define MCP2515_RXB1D4 0x7a +#define MCP2515_RXB1D5 0x7b +#define MCP2515_RXB1D6 0x7c +#define MCP2515_RXB1D7 0x7d + +/* Offset to simplify mcp2515_receive() function */ + +#define MCP2515_RX0_OFFSET 0x00 +#define MCP2515_RX1_OFFSET 0x10 + +/* Offset to simplify mcp2515_send() function */ + +#define MCP2515_TX0_OFFSET 0x00 +#define MCP2515_TX1_OFFSET 0x10 +#define MCP2515_TX2_OFFSET 0x20 + +/* CANCTRL: CAN CONTROL REGISTER */ + +#define CANCTRL_CLKPRE_SHIFT (0) /* Bits 0-1: CLKOUT Pin Prescaler bits */ +#define CANCTRL_CLKPRE_MASK (3 << CANCTRL_CLKPRE_SHIFT) +#define CANCTRL_CLKEN (1 << 2) /* Bit 2: CLKOUT Pin Enable bit */ +#define CANCTRL_OSM (1 << 3) /* Bit 3: One-Shot Mode bit */ +#define CANCTRL_ABAT (1 << 4) /* Bit 4: Abort All Pending Transmissions bit */ +#define CANCTRL_REQOP_SHIFT (5) /* Bits 5-7: Request Operation Mode bits */ +#define CANCTRL_REQOP_MASK (7 << CANCTRL_REQOP_SHIFT) +#define CANCTRL_REQOP_NORMAL (0 << CANCTRL_REQOP_SHIFT) +#define CANCTRL_REQOP_SLEEP (1 << CANCTRL_REQOP_SHIFT) +#define CANCTRL_REQOP_LOOPBK (2 << CANCTRL_REQOP_SHIFT) +#define CANCTRL_REQOP_LISTEN (3 << CANCTRL_REQOP_SHIFT) +#define CANCTRL_REQOP_CONFIG (4 << CANCTRL_REQOP_SHIFT) + +/* TXBnCTRL – TRANSMIT BUFFER n CONTROL REGISTER */ + +#define TXBCTRL_TXP_SHIFT (0) /* Bits 0-1: Transmit Buffer Priority */ +#define TXBCTRL_TXP_MASK (3 << MCP2515_TXBCTRL_TXP_SHIFT) + /* Bit 2: Not used */ +#define TXBCTRL_TXREQ (1 << 3) /* Bit 3: Message Transmit Request bit */ +#define TXBCTRL_TXERR (1 << 4) /* Bit 4: Transmission Error Detected bit */ +#define TXBCTRL_MLOA (1 << 5) /* Bit 5: Message Lost Arbitration bit */ +#define TXBCTRL_ABTF (1 << 6) /* Bit 6: Message Aborted Flag bit */ + /* Bit 7: Not used */ + +/* TXRTSCTRL – TXnRTS PIN CONTROL AND STATUS REGISTER */ + +#define TXRTSCTRL_B0RTSM (1 << 0) /* Bit 0: TX0RTS Pin mode bit */ +#define TXRTSCTRL_B1RTSM (1 << 1) /* Bit 1: TX1RTS Pin mode bit */ +#define TXRTSCTRL_B2RTSM (1 << 2) /* Bit 2: TX2RTS Pin mode bit */ +#define TXRTSCTRL_B0RTS (1 << 3) /* Bit 3: TX0RTS Pin State bit */ +#define TXRTSCTRL_B1RTS (1 << 4) /* Bit 4: TX1RTS Pin State bit */ +#define TXRTSCTRL_B2RTS (1 << 5) /* Bit 5: TX2RTS Pin State bit */ + /* Bit 6-7: Not used */ + +/* TXBnSIDH – TRANSMIT BUFFER n STANDARD IDENTIFIER HIGH */ + +#define TXBSIDH_SID_MASK 0xff /* Standard Identifier bits <10:3> */ + + +/* TXBnSIDL – TRANSMIT BUFFER n STANDARD IDENTIFIER LOW */ + +#define TXBSIDL_SID_SHIFT (5) /* Bits 5-7: Standard Identifier bits <2:0> */ +#define TXBSIDL_SID_MASK (0x7 << TXBSIDL_SID_SHIFT) +#define TXBSIDL_EXIDE (1 << 3) /* Bit 3: Extended Identifier Enable bit */ +#define TXBSIDL_EID_SHIFT (0) /* Bits 0-1: Extended Identifier bits <17:16> */ +#define TXBSIDL_EID_MASK (0x03 << TXBSIDL_EID_MASK) + + +/* TXBnEID8 – TRANSMIT BUFFER n EXTENDED IDENTIFIER HIGH */ + +#define TXBEID8_EID_MASK 0xff /* Bits 0-7: Extended Identifier bits <15:8> */ + +/* TXBnEID0 – TRANSMIT BUFFER n EXTENDED IDENTIFIER LOW */ + +#define TXBEID0_EID_MASK 0xff /* Bits 0-7: Extended Identifier bits <7:0> */ + +/* TXBnDLC - TRANSMIT BUFFER n DATA LENGTH CODE */ + +#define TXBDLC_DLC_SHIFT (0) /* Bits 0-3: Data Length Code <3:0> bits */ +#define TXBDLC_DLC_MASK (0xf << TXBDLC_DLC_SHIFT) +#define TXBDLC_RTR (1 << 6) /* Bit 6: Remote Transmission Request bit */ + +/* TXBnDm – TRANSMIT BUFFER n DATA BYTE m */ + +#define TXBD_D0 (1 << 0) /* Bit 0: Transmit Buffer n Data Field Bytes 0 */ +#define TXBD_D1 (1 << 1) /* Bit 1: Transmit Buffer n Data Field Bytes 1 */ +#define TXBD_D2 (1 << 2) /* Bit 2: Transmit Buffer n Data Field Bytes 2 */ +#define TXBD_D3 (1 << 3) /* Bit 3: Transmit Buffer n Data Field Bytes 3 */ +#define TXBD_D4 (1 << 4) /* Bit 4: Transmit Buffer n Data Field Bytes 4 */ +#define TXBD_D5 (1 << 5) /* Bit 5: Transmit Buffer n Data Field Bytes 5 */ +#define TXBD_D6 (1 << 6) /* Bit 6: Transmit Buffer n Data Field Bytes 6 */ +#define TXBD_D7 (1 << 7) /* Bit 7: Transmit Buffer n Data Field Bytes 7 */ + +/* RXB0CTRL – RECEIVE BUFFER 0 CONTROL */ + +#define RXB0CTRL_FILHIT (1 << 0) /* Bit 0: Filter Hit bit - 1 = Msg was accepted by Filter 1; 0 = Filter 0 */ +#define RXB0CTRL_BUKT1 (1 << 1) /* Bit 1: Read-only Copy of BUKT bit (used internally by the MCP2515) */ +#define RXB0CTRL_BUKT (1 << 2) /* Bit 2: Rollover Enable bit */ + +/* These bits are common to RXB0 and RXB1: */ + +#define RXBCTRL_RXRTR (1 << 3) /* Bit 3: Received Remote Transfer Request bit */ + /* Bit 4: Not used */ +#define RXBCTRL_RXM_SHIFT (5) /* Bits 5-6: Receive Buffer Operating Mode bits */ +#define RXBCTRL_RXM_MASK (0x3 << RXBCTRL_RXM_SHIFT) +#define RXBCTRL_RXM_ALLMSG (3 << RXBCTRL_RXM_SHIFT) /* 11: Turn mask/filters off; receive any message */ +#define RXBCTRL_RXM_ALLVALID (0 << RXBCTRL_RXM_SHIFT) /* 00: Receive all valid msgs using (STD or EXT) that meet filter criteria */ + /* Bit 7: Not used */ + +/* N.B.: In the datasheet DS21801D the file RXM of RXBnCTRL could to assume + the value 01 and 10 to receive only STD or EXT msgs respectively. + But in a more recent datasheet DS20001801H it was removed. */ + +/* RXB1CTRL – RECEIVE BUFFER 1 CONTROL */ + +#define RXB1CTRL_FILHIT_SHIFT (0) /* Filter Hit bits - indicates which acceptance filter enabled reception of message */ +#define RXB1CTRL_FILHIT_MASK (0x7 << RXB0CTRL_FILHIT_SHIFT) +#define RXB1CTRL_FILHIT_F5 (5 << RXB1CTRL_FILHIT_SHIFT) /* Acceptance Filter 5 (RXF5) */ +#define RXB1CTRL_FILHIT_F4 (4 << RXB1CTRL_FILHIT_SHIFT) /* Acceptance Filter 4 (RXF4) */ +#define RXB1CTRL_FILHIT_F3 (3 << RXB1CTRL_FILHIT_SHIFT) /* Acceptance Filter 3 (RXF3) */ +#define RXB1CTRL_FILHIT_F2 (2 << RXB1CTRL_FILHIT_SHIFT) /* Acceptance Filter 2 (RXF2) */ +#define RXB1CTRL_FILHIT_F1 (1 << RXB1CTRL_FILHIT_SHIFT) /* Acceptance Filter 1 (RXF1) (Only if BUKT bit set in RXB0CTRL) */ +#define RXB1CTRL_FILHIT_F0 (0 << RXB1CTRL_FILHIT_SHIFT) /* Acceptance Filter 0 (RXF0) (Only if BUKT bit set in RXB0CTRL) */ + +/* BFPCTRL – RXnBF PIN CONTROL AND STATUS */ + +#define BFPCTRL_B0BFM (1 << 0) /* Bit 0: RX0BF Pin Operation Mode bit */ +#define BFPCTRL_B1BFM (1 << 1) /* Bit 1: RX1BF Pin Operation Mode bit */ +#define BFPCTRL_B0BFE (1 << 2) /* Bit 2: RX0BF Pin Function Enable bit */ +#define BFPCTRL_B1BFE (1 << 3) /* Bit 3: RX1BF Pin Function Enable bit */ +#define BFPCTRL_B0BFS (1 << 4) /* Bit 4: RX0BF Pin State bit (Digital Output mode only) */ +#define BFPCTRL_B1BFS (1 << 5) /* Bit 5: RX1BF Pin State bit (Digital Output mode only) */ + /* Bits 6-7: Not used */ + +/* RXBnSIDH – RECEIVE BUFFER n STANDARD IDENTIFIER HIGH */ + +#define RXBSIDH_SID_MASK 0xff /* Standard Identifier bits <10:3> */ + +/* RXBnSIDL – RECEIVE BUFFER n STANDARD IDENTIFIER LOW */ + +#define RXBSIDL_SID_SHIFT (5) /* Bits 5-7: Standard Identifier bits <2:0> */ +#define RXBSIDL_SID_MASK (0x7 << RXBSIDL_SID_SHIFT) +#define RXBSIDL_SRR (1 << 4) /* Bit 4: Standard Frame Remote Transmit Request bit (valid only if IDE bit = '0')*/ +#define RXBSIDL_IDE (1 << 3) /* Bit 3: Extended Identifier Message received */ + /* Bit 2: Not used */ +#define RXBSIDL_EID_SHIFT (0) /* Bits 0-1: Extended Identifier bits <17:16> */ +#define RXBSIDL_EID_MASK (0x03 << RXBSIDL_EID_SHIFT) + +/* RXBnEID8 – RECEIVE BUFFER n EXTENDED IDENTIFIER HIGH */ + +#define RXBEID8_EID_MASK 0xff /* Bits 0-7: Extended Identifier bits <15:8> */ + +/* RXBnEID0 – RECEIVE BUFFER n EXTENDED IDENTIFIER LOW */ + +#define RXBEID0_EID_MASK 0xff /* Bits 0-7: Extended Identifier bits <7:0> */ + +/* RXBnDLC – RECEIVE BUFFER n DATA LENGHT CODE */ + +#define RXBDLC_DLC_SHIFT (0) /* Bits 0-3: Data Length Code <3:0> bits */ +#define RXBDLC_DLC_MASK (0xf << RXBDLC_DLC_SHIFT) +#define RXBDLC_RB0 (1 << 4) /* Bit 4: Reserved bit 0 */ +#define RXBDLC_RB1 (1 << 5) /* Bit 5: Reserved bit 1 */ +#define RXBDLC_RTR (1 << 6) /* Bit 6: Remote Transmission Request bit */ + /* Bit 7: Not used */ + +/* RXFnSIDH – FILTER n STANDARD IDENTIFIER HIGH */ + +#define RXFSIDH_SID_MASK 0xff /* Standard Identifier Filter bits <10:3> */ + +/* RXFnSIDL – FILTER n STANDARD IDENTIFIER LOW */ + +#define RXFSIDL_EID_SHIFT (0) /* Bit 0-1: Extended Identifier Filter bits <17:16> */ +#define RXFSIDL_EID_MASK (3 << RXFSIDL_EID_SHIFT) +#define RXFSIDL_EXIDE (1 << 3) /* Bit 3: Extended Identifier Enable bit */ +#define RXFSIDL_SID_SHIFT (5) /* Bits 5-7: Standard Identifier Filter bits <2:0> */ +#define RXFSIDL_SID_MASK (0x7 << RXFSIDL_SID_SHIFT) + +/* RXFnEID8 – FILTER n EXTENDED IDENTIFIER HIGH */ + +#define RXFEID8_EID_MASK 0xff /* Extended Identifier bits <15:8> */ + +/* RXFnEID0 – FILTER n EXTENDED IDENTIFIER LOW */ + +#define RXFEID0_EID_MASK 0xff /* Extended Identifier bits <7:0> */ + +/* RXMnSIDH – MASK n STANDARD IDENTIFIER HIGH */ + +#define RXMSIDH_SID_MASK 0xff /* Standard Identifier Mask bits <10:3> */ + +/* RXMnSIDL – MASK n STANDARD IDENTIFIER LOW */ + +#define RXMSIDL_EID_SHIFT (0) /* Bits 0-1: Extended Identifier Mask bits <17:16> */ +#define RXMSIDL_EID_MASK (3 << RXMSIDH_EID_SHIFT) +#define RXMSIDL_SID_SHIFT (5) /* Bits 5-7: Standard Identifier Mask bits <2:0> */ +#define RXMSIDL_MASK (7 << RXMSIDH_SID_SHIFT) + +/* RXMnEID8 – MASK n EXTENDED IDENTIFIER HIGH */ + +#define RXMEID8_EID_MASK 0xff /* Extended Identifier bits <15:8> */ + +/* RXMnEID0 – MASK n EXTENDED IDENTIFIER LOW */ + +#define RXMEID0_EID_MASK 0xff /* Extended Identifier Mask bits <7:0> */ + +/* CNF1 – CONFIGURATION 1 */ + +#define CNF1_BRP_SHIFT (0) /* Bits 0-5: Baud Rate Prescaler bits <5:0>, TQ = 2 x (BRP + 1)/Fosc */ +#define CNF1_BRP_MASK (0x3f << CNF1_BRP_SHIFT) +#define CNF1_SJW_SHIFT (6) /* Bit 6-7: Synchronization Jump Width Length bits <1:0> */ +#define CNF1_SJW_MASK (3 << CNF1_SJW_SHIFT) +# define CNF1_SJW_4xTQ (3 << CNF1_SJW_SHIFT) /* Length = 4 x TQ */ +# define CNF1_SJW_3xTQ (2 << CNF1_SJW_SHIFT) /* Length = 3 x TQ */ +# define CNF1_SJW_2xTQ (1 << CNF1_SJW_SHIFT) /* Length = 2 x TQ */ +# define CNF1_SJW_1xTQ (0 << CNF1_SJW_SHIFT) /* Length = 1 x TQ */ + +/* CNF2 – CONFIGURATION 2 */ + +#define CNF2_PRSEG_SHIFT (0) /* Bits 0-2: Propagation Segment Length bits <2:0>, (PRSEG + 1) x TQ */ +#define CNF2_PRSEG_MASK (7 << CNF2_PRSEG_SHIFT) +#define CNF2_PHSEG1_SHIFT (3) /* Bits 3-5: PS1 Length bits <2:0>, (PHSEG1 + 1) x TQ */ +#define CNF2_PHSEG1_MASK (7 << CNF2_PHSEG1_SHIFT) +#define CNF2_SAM (1 << 6) /* Bit 6: Sample Point Configuration bit */ +#define CNF2_BTLMODE (1 << 7) /* Bit 7: PS2 Bit Time Length bit */ + +/* CNF3 - CONFIGURATION 3 */ + +#define CNF3_PHSEG2_SHIFT (0) /* Bits 0-2: PS2 Length bits<2:0>, (PHSEG2 + 1) x TQ */ +#define CNF3_PHSEG2_MASK (7 << CNF3_PHSEG2_SHIFT) +#define CNF3_WAKFIL (1 << 6) /* Bit 3: Wake-up Filter bit */ +#define CNF3_SOF (1 << 7) /* Bit 7: Start-of-Frame signal bit */ + +/* TEC – TRANSMIT ERROR COUNTER */ + +#define TEC_MASK 0xff /* Transmit Error Count bits <7:0> */ + +/* REC – RECEIVER ERROR COUNTER */ + +#define REC_MASK 0xff /* Receive Error Count bits <7:0> */ + +/* EFLG – ERROR FLAG */ + +#define EFLG_EWARN (1 << 0) /* Bit 0: Error Warning Flag bit */ +#define EFLG_RXWAR (1 << 1) /* Bit 1: Receive Error Warning Flag bit */ +#define EFLG_TXWAR (1 << 2) /* Bit 2: Transmit Error Warning Flag bit */ +#define EFLG_RXEP (1 << 3) /* Bit 3: Receive Error-Passive Flag bit */ +#define EFLG_TXEP (1 << 4) /* Bit 4: Transmit Error-Passive Flag bit */ +#define EFLG_TXBO (1 << 5) /* Bit 5: Bus-Off Error Flag bit */ +#define EFLG_RX0OVR (1 << 6) /* Bit 6: Receive Buffer 0 Overflow Flag bit */ +#define EFLG_RX1OVR (1 << 7) /* Bit 7: Receive Buffer 1 Overflow Flag bit */ + +/* CANINTE/CANINTF – INTERRUPT ENABLE/FLAG */ + +#define MCP2515_INT_RX0 (1 << 0) /* Bit 0: Receive Buffer 0 Full Interrupt Enable bit */ +#define MCP2515_INT_RX1 (1 << 1) /* Bit 1: Receive Buffer 1 Full Interrupt Enable bit */ +#define MCP2515_INT_TX0 (1 << 2) /* Bit 2: Transmit Buffer 0 Empty Interrupt Enable bit */ +#define MCP2515_INT_TX1 (1 << 3) /* Bit 3: Transmit Buffer 1 Empty Interrupt Enable bit */ +#define MCP2515_INT_TX2 (1 << 4) /* Bit 4: Transmit Buffer 2 Empty Interrupt Enable bit */ +#define MCP2515_INT_ERR (1 << 5) /* Bit 5: Error Interrupt Enable bit (multiple sources in EFLG register) */ +#define MCP2515_INT_WAK (1 << 6) /* Bit 6: Wakeup Interrupt Enable bit */ +#define MCP2515_INT_MERR (1 << 7) /* Bit 7: Message Error Interrupt Enable bit */ + +/* MCP2515 SPI Instruction/Command byte */ + +#define MCP2515_RESET 0xC0 +#define MCP2515_READ 0x03 +#define MCP2515_READ_RX0 0x90 +#define MCP2515_READ_RX1 0x94 +#define MCP2515_WRITE 0x02 +#define MCP2515_LOAD_TX0 0x40 +#define MCP2515_LOAD_TX1 0x42 +#define MCP2515_LOAD_TX2 0x44 +#define MCP2515_RTS_TX0 0x81 +#define MCP2515_RTS_TX1 0x82 +#define MCP2515_RTS_TX2 0x84 +#define MCP2515_RTS_ALL 0x87 +#define MCP2515_READ_STATUS 0xA0 +#define MCP2515_RX_STATUS 0xB0 +#define MCP2515_BITMOD 0x05 + +/* CANCTRL register will be 0x87 after reset and in Conf. Mode */ + +#define DEFAULT_CANCTRL_CONFMODE 0x87 + +/* Crystal Frequency used on MCP2515 board */ + +#define MCP2515_CANCLK_FREQUENCY 8000000 + diff --git a/include/nuttx/can/mcp2515.h b/include/nuttx/can/mcp2515.h new file mode 100644 index 0000000000..bca2d0db73 --- /dev/null +++ b/include/nuttx/can/mcp2515.h @@ -0,0 +1,164 @@ +/**************************************************************************** + * include/nuttx/can/mcp2515.h + * + * Copyright (C) 2017 Alan Carvalho de Assis. All rights reserved. + * Author: Alan Carvalho de Assis + * + * 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. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_CAN_MCP2515_H +#define __INCLUDE_NUTTX_CAN_MCP2515_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#if defined(CONFIG_CAN) && defined(CONFIG_CAN_MCP2515) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* SPI BUS PARAMETERS *******************************************************/ + +#define MCP2515_SPI_FREQUENCY (1000000) /* 1 MHz */ +#define MCP2515_SPI_MODE (SPIDEV_MODE0) /* Device uses SPI Mode 0: CPOL=0, CPHA=0 */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef void (*mcp2515_handler_t)(FAR struct mcp2515_config_s *config, FAR void *arg); + +/* A reference to a structure of this type must be passed to the MCP2515 driver when the + * driver is instantiated. This structure provides information about the configuration of the + * MCP2515 and provides some board-specific hooks. + * + * Memory for this structure is provided by the caller. It is not copied by the driver + * and is presumed to persist while the driver is active. The memory must be writeable + * because, under certain circumstances, the driver may modify the frequency. + */ + +struct mcp2515_config_s +{ + struct spi_dev_s *spi; /* SPI used for MCP2515 communication */ + uint32_t baud; /* Configured baud */ + uint32_t btp; /* Bit timing/prescaler register setting */ + uint8_t devid; /* MCP2515 device ID */ + uint8_t mode; /* See enum mcp2515_canmod_e */ + uint8_t nfilters; /* Number of standard/extended filters */ + uint8_t ntxbuffers; /* Number of TX Buffer available */ + uint8_t txbuf0[10]; /* Transmit Buffer 0 */ + uint8_t txbuf1[10]; /* Transmit Buffer 1 */ + uint8_t txbuf2[10]; /* Transmit Buffer 2 */ +#ifdef MCP2515_LOOPBACK + bool loopback; /* True: Loopback mode */ +#endif + + /* Device characterization */ + + /* IRQ/GPIO access callbacks. These operations all hidden behind + * callbacks to isolate the ADXL345 driver from differences in GPIO + * interrupt handling by varying boards and MCUs. + * + * attach - Attach the ADXL345 interrupt handler to the GPIO interrupt + */ + + int (*attach)(FAR struct mcp2515_config_s *state, mcp2515_handler_t handler, + FAR void *arg); +}; + + +typedef FAR void *MCP2515_HANDLE; + +struct mcp2515_can_s; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: mcp2515_instantiate + * + * Description: + * Initialize a CAN Driver for MCP2515. + * + * Input Parameters: + * spi - An instance of the SPI interface to use to communicate with + * MCP2515 + * config - Describes the configuration of the MCP2515 part. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +FAR struct mcp2515_can_s *mcp2515_instantiate(FAR struct mcp2515_config_s *config); + +/**************************************************************************** + * Name: mcp2515_initialize + * + * Description: + * Initialize a CAN Driver for MCP2515. + * + * Input Parameters: + * spi - An instance of the SPI interface to use to communicate with + * MCP2515 + * config - Describes the configuration of the MCP2515 part. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +FAR struct can_dev_s *mcp2515_initialize(FAR struct mcp2515_can_s *mcp2515can); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_CAN && CONFIG_CAN_MCP2515 */ + +#endif /* __INCLUDE_NUTTX_CAN_MCP2515_H */ diff --git a/include/nuttx/spi/spi.h b/include/nuttx/spi/spi.h index ddeb222635..6a03a2a9d8 100644 --- a/include/nuttx/spi/spi.h +++ b/include/nuttx/spi/spi.h @@ -457,6 +457,7 @@ #define SPIDEV_IEEE802154(n) SPIDEV_ID(SPIDEVTYPE_IEEE802154, (n)) #define SPIDEV_CONTACTLESS(n) SPIDEV_ID(SPIDEVTYPE_CONTACTLESS, (n)) #define SPIDEV_USER(n) SPIDEV_ID(SPIDEVTYPE_USER, (n)) +#define SPIDEV_CANBUS(n) SPIDEV_ID(SPIDEVTYPE_CANBUS, (n)) /**************************************************************************** * Public Types @@ -491,7 +492,8 @@ enum spi_devtype_e SPIDEVTYPE_TEMPERATURE, /* Select SPI Temperature sensor device */ SPIDEVTYPE_IEEE802154, /* Select SPI IEEE 802.15.4 wireless device */ SPIDEVTYPE_CONTACTLESS, /* Select SPI Contactless device */ - SPIDEVTYPE_USER /* Board-specific values start here */ + SPIDEVTYPE_USER, /* Board-specific values start here */ + SPIDEVTYPE_CANBUS /* Select SPI CAN Bus controller over SPI */ }; /* Certain SPI devices may required different clocking modes */