Feature/add memap cstack usage ports (#661)
* Added memap, avstack, and checkstackusage tools to STM32F4xx Makefile and CMake builds to calculate CSTACK depth and RAM usage * Added memap, cstack, and ram-usage recipes to stm32f10x port Makefile. Added Cmake build. * Removed local dlmstp.c module from stm32f10x port, and used the common datalink dlmstp.c module with MS/TP extended frames and zero-config support. * Added .nm and .su to .gitignore to skip the analysis file residue.
This commit is contained in:
@@ -0,0 +1,311 @@
|
||||
# This is a CMake example for STM32 ARM Cortex-M3 STM32F103RGT6 on
|
||||
# a STM32 Discovery Kit evaluation board using the ARM GCC compiler
|
||||
# and STM32 CMSIS library.
|
||||
#
|
||||
# Board STM32F103 Discovery Kit
|
||||
# MCU STM32F103RGT6
|
||||
# CPU Cortex-M3
|
||||
# RAM 96KB
|
||||
# Flash 1024KB
|
||||
#
|
||||
# To build this project you need to install:
|
||||
# - ARM GCC compiler
|
||||
# - CMake
|
||||
#
|
||||
# To build this project you need to run:
|
||||
# - cmake -S . -B build
|
||||
# - cmake --build build
|
||||
#
|
||||
# To flash this project you need to run:
|
||||
# - st-flash write build/bacnet-mstp.hex 0x8000000
|
||||
#
|
||||
# To debug this project you need to run:
|
||||
# - arm-none-eabi-gdb -q build/bacnet-mstp.out
|
||||
# - (gdb) target extended-remote localhost:3333
|
||||
# - (gdb) monitor reset halt
|
||||
# - (gdb) load
|
||||
# - (gdb) monitor reset halt
|
||||
# - (gdb) monitor reset init
|
||||
# - (gdb) monitor reset run
|
||||
# - (gdb) monitor reset exit
|
||||
# - (gdb) quit
|
||||
#
|
||||
# You can also use VSCode with Cortex-Debug extension
|
||||
#
|
||||
# This example was tested with:
|
||||
# - ARM GCC 10.3.1
|
||||
# - CMake 3.22.1
|
||||
# - stm32f10x_StdPeriph_Driver V1.0.0
|
||||
# - BACnet Stack V1.3.2
|
||||
#
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
# Cross compilers and tools
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_VERSION 1)
|
||||
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
|
||||
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
|
||||
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
|
||||
set(CMAKE_AR arm-none-eabi-ar)
|
||||
set(CMAKE_OBJCOPY arm-none-eabi-objcopy)
|
||||
set(CMAKE_OBJDUMP arm-none-eabi-objdump)
|
||||
set(CMAKE_SIZE arm-none-eabi-size)
|
||||
set(CMAKE_NM arm-none-eabi-nm)
|
||||
set(CMAKE_CSTACK "${CMAKE_SOURCE_DIR}/../../tools/check-stack-usage/checkStackUsage.py")
|
||||
set(CMAKE_MEMAP "${CMAKE_SOURCE_DIR}/../../tools/memap/memap.py")
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
set(EXECUTABLE ${PROJECT_NAME}.elf)
|
||||
|
||||
project(bacnet-mstp)
|
||||
|
||||
enable_language(C ASM)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_EXTENSIONS ON)
|
||||
|
||||
# Specific ARM microcontroller compiler and linker settings
|
||||
add_compile_options(-mcpu=cortex-m3)
|
||||
add_compile_options(-mthumb -mno-thumb-interwork -mabi=aapcs)
|
||||
add_link_options(-mcpu=cortex-m3)
|
||||
add_link_options(-mthumb -mno-thumb-interwork -mabi=aapcs)
|
||||
# Compiler and linker settings for garbage collection and memory usage
|
||||
add_compile_options(-ffunction-sections -fdata-sections)
|
||||
add_compile_options(-fno-common -fmessage-length=0)
|
||||
add_compile_options(-fstack-usage -fdump-rtl-dfinish)
|
||||
add_link_options(-Wl,-gc-sections,--print-memory-usage)
|
||||
|
||||
# Build types
|
||||
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
|
||||
message(STATUS "Maximum optimization for speed")
|
||||
add_compile_options(-Ofast)
|
||||
elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo")
|
||||
message(STATUS "Maximum optimization for speed, debug info included")
|
||||
add_compile_options(-Ofast -g)
|
||||
elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "MinSizeRel")
|
||||
message(STATUS "Maximum optimization for size")
|
||||
add_compile_options(-Os)
|
||||
else ()
|
||||
message(STATUS "Minimal optimization, debug info included")
|
||||
add_compile_definitions(DEBUG)
|
||||
add_compile_options(-Og -g3)
|
||||
endif ()
|
||||
|
||||
# eliminate the deprecated function warnings
|
||||
option(BACNET_STACK_DEPRECATED_DISABLE "Disable deprecation compile warnings" ON)
|
||||
if(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
add_definitions(-DBACNET_STACK_DEPRECATED_DISABLE)
|
||||
endif()
|
||||
|
||||
set(LIBRARY_BACNET_INC "${CMAKE_SOURCE_DIR}/../../src")
|
||||
set(LIBRARY_BACNET_CORE "${CMAKE_SOURCE_DIR}/../../src/bacnet")
|
||||
set(LIBRARY_BACNET_BASIC "${CMAKE_SOURCE_DIR}/../../src/bacnet/basic")
|
||||
set(LIBRARY_STM32_SRC "${CMAKE_SOURCE_DIR}/drivers/src")
|
||||
set(LIBRARY_STM32_INC "${CMAKE_SOURCE_DIR}/drivers/inc")
|
||||
set(LIBRARY_CMSIS_INC "${CMAKE_SOURCE_DIR}/CMSIS")
|
||||
set(LIBRARY_CMSIS_GCC_INC "${CMAKE_SOURCE_DIR}/CMSIS/gcc_ride7")
|
||||
|
||||
set(BACNET_PROJECT_SOURCE
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_adc.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_bkp.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_can.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_cec.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_crc.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_dac.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_dbgmcu.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_dma.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_exti.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_flash.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_fsmc.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_gpio.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_i2c.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_iwdg.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_misc.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_pwr.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_rcc.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_rtc.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_sdio.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_spi.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_tim.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_usart.c
|
||||
${LIBRARY_STM32_SRC}/stm32f10x_wwdg.c
|
||||
${LIBRARY_STM32_SRC}/syscalls.c
|
||||
|
||||
${CMAKE_SOURCE_DIR}/stm32f10x_conf.h
|
||||
# main entry and STM32 hardware setup
|
||||
${CMAKE_SOURCE_DIR}/main.c
|
||||
${CMAKE_SOURCE_DIR}/stm32f10x_it.c
|
||||
${CMAKE_SOURCE_DIR}/stm32f10x_it.h
|
||||
${CMAKE_SOURCE_DIR}/system_stm32f10x.c
|
||||
# BACnet specific hardware abstraction, configuration and tasks
|
||||
${CMAKE_SOURCE_DIR}/bacnet.c
|
||||
${CMAKE_SOURCE_DIR}/led.c
|
||||
${CMAKE_SOURCE_DIR}/mstimer-init.c
|
||||
${CMAKE_SOURCE_DIR}/rs485.c
|
||||
# BACnet objects in this device
|
||||
${CMAKE_SOURCE_DIR}/device.c
|
||||
${CMAKE_SOURCE_DIR}/netport.c
|
||||
${CMAKE_SOURCE_DIR}/bo.c
|
||||
# BACnet services library
|
||||
${LIBRARY_BACNET_BASIC}/service/h_dcc.c
|
||||
${LIBRARY_BACNET_BASIC}/service/h_apdu.c
|
||||
${LIBRARY_BACNET_BASIC}/npdu/h_npdu.c
|
||||
${LIBRARY_BACNET_BASIC}/service/h_rd.c
|
||||
${LIBRARY_BACNET_BASIC}/service/h_rp.c
|
||||
${LIBRARY_BACNET_BASIC}/service/h_rpm.c
|
||||
${LIBRARY_BACNET_BASIC}/service/h_whohas.c
|
||||
${LIBRARY_BACNET_BASIC}/service/h_whois.c
|
||||
${LIBRARY_BACNET_BASIC}/service/h_wp.c
|
||||
${LIBRARY_BACNET_BASIC}/service/h_noserv.c
|
||||
${LIBRARY_BACNET_BASIC}/service/s_iam.c
|
||||
${LIBRARY_BACNET_BASIC}/service/s_ihave.c
|
||||
${LIBRARY_BACNET_BASIC}/tsm/tsm.c
|
||||
${LIBRARY_BACNET_BASIC}/sys/debug.c
|
||||
${LIBRARY_BACNET_BASIC}/sys/ringbuf.c
|
||||
${LIBRARY_BACNET_BASIC}/sys/fifo.c
|
||||
${LIBRARY_BACNET_BASIC}/sys/mstimer.c
|
||||
# BACnet core library
|
||||
${LIBRARY_BACNET_CORE}/abort.c
|
||||
${LIBRARY_BACNET_CORE}/bacaddr.c
|
||||
${LIBRARY_BACNET_CORE}/bacapp.c
|
||||
${LIBRARY_BACNET_CORE}/bacdcode.c
|
||||
${LIBRARY_BACNET_CORE}/bacdest.c
|
||||
${LIBRARY_BACNET_CORE}/bacdevobjpropref.c
|
||||
${LIBRARY_BACNET_CORE}/bacerror.c
|
||||
${LIBRARY_BACNET_CORE}/bacint.c
|
||||
${LIBRARY_BACNET_CORE}/bacreal.c
|
||||
${LIBRARY_BACNET_CORE}/bacstr.c
|
||||
${LIBRARY_BACNET_CORE}/datalink/cobs.c
|
||||
${LIBRARY_BACNET_CORE}/datalink/crc.c
|
||||
${LIBRARY_BACNET_CORE}/datalink/dlmstp.c
|
||||
${LIBRARY_BACNET_CORE}/datalink/mstp.c
|
||||
${LIBRARY_BACNET_CORE}/datalink/mstptext.c
|
||||
${LIBRARY_BACNET_CORE}/datetime.c
|
||||
${LIBRARY_BACNET_CORE}/dcc.c
|
||||
${LIBRARY_BACNET_CORE}/indtext.c
|
||||
${LIBRARY_BACNET_CORE}/iam.c
|
||||
${LIBRARY_BACNET_CORE}/ihave.c
|
||||
${LIBRARY_BACNET_CORE}/hostnport.c
|
||||
${LIBRARY_BACNET_CORE}/lighting.c
|
||||
${LIBRARY_BACNET_CORE}/memcopy.c
|
||||
${LIBRARY_BACNET_CORE}/npdu.c
|
||||
${LIBRARY_BACNET_CORE}/proplist.c
|
||||
${LIBRARY_BACNET_CORE}/rd.c
|
||||
${LIBRARY_BACNET_CORE}/reject.c
|
||||
${LIBRARY_BACNET_CORE}/rp.c
|
||||
${LIBRARY_BACNET_CORE}/rpm.c
|
||||
${LIBRARY_BACNET_CORE}/timestamp.c
|
||||
${LIBRARY_BACNET_CORE}/weeklyschedule.c
|
||||
${LIBRARY_BACNET_CORE}/dailyschedule.c
|
||||
${LIBRARY_BACNET_CORE}/calendar_entry.c
|
||||
${LIBRARY_BACNET_CORE}/special_event.c
|
||||
${LIBRARY_BACNET_CORE}/bactimevalue.c
|
||||
${LIBRARY_BACNET_CORE}/whohas.c
|
||||
${LIBRARY_BACNET_CORE}/whois.c
|
||||
${LIBRARY_BACNET_CORE}/wp.c
|
||||
|
||||
${LIBRARY_CMSIS_GCC_INC}/startup_stm32f10x_xl.s
|
||||
CMSIS/stm32f10x.h
|
||||
)
|
||||
|
||||
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/stm32f10x.ld)
|
||||
|
||||
set(EXECUTABLE ${PROJECT_NAME}.elf)
|
||||
|
||||
add_executable(${EXECUTABLE} ${BACNET_PROJECT_SOURCE})
|
||||
|
||||
target_compile_definitions(${EXECUTABLE} PRIVATE
|
||||
-DNDEBUG
|
||||
# STM32 CMSIS library
|
||||
-DUSE_STDPERIPH_DRIVER
|
||||
-DSTM32F10X_CL
|
||||
-DHSE_VALUE=25000000
|
||||
# BACnet Stack library
|
||||
-DBACDL_MSTP
|
||||
-DMAX_APDU=1476
|
||||
-DBIG_ENDIAN=0
|
||||
-DMAX_TSM_TRANSACTIONS=0
|
||||
-DBACAPP_MINIMAL
|
||||
-DMAX_CHARACTER_STRING_BYTES=64
|
||||
-DMAX_OCTET_STRING_BYTES=64
|
||||
)
|
||||
|
||||
# inhibit pedantic warnings
|
||||
target_compile_options(${EXECUTABLE} PRIVATE
|
||||
-Wall -Wextra -pedantic
|
||||
-Wfloat-equal -Wconversion -Wredundant-decls
|
||||
-Wswitch-default
|
||||
# don't warn about conversion, sign, compares, long long and attributes
|
||||
# since they are common in embedded
|
||||
-Wno-sign-conversion
|
||||
-Wno-conversion
|
||||
-Wno-sign-compare
|
||||
-Wno-long-long
|
||||
-Wno-attributes
|
||||
# don't warn about implicit fallthrough since it is common in network protocols
|
||||
-Wno-implicit-fallthrough
|
||||
# the SDK does not meet coding guidelines
|
||||
-Wno-comment
|
||||
-Wno-missing-braces
|
||||
-Wno-unused-variable
|
||||
# reference the linker file for CSTACK size
|
||||
-Wstack-usage=16384
|
||||
-Wno-unused-parameter
|
||||
-Wno-char-subscripts
|
||||
)
|
||||
|
||||
target_include_directories(${EXECUTABLE} PRIVATE
|
||||
${CMAKE_SOURCE_DIR}
|
||||
${LIBRARY_CMSIS_INC}
|
||||
${LIBRARY_CMSIS_GCC_INC}
|
||||
${LIBRARY_STM32_INC}
|
||||
${LIBRARY_BACNET_INC}
|
||||
)
|
||||
|
||||
target_link_options(${EXECUTABLE} PRIVATE
|
||||
-T${LINKER_SCRIPT}
|
||||
-specs=nano.specs
|
||||
-lm
|
||||
-lnosys
|
||||
-Wl,-Map=${PROJECT_NAME}.map,--cref
|
||||
-Wl,--gc-sections
|
||||
)
|
||||
|
||||
# Create hex and bin files
|
||||
add_custom_command(TARGET ${EXECUTABLE}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_OBJCOPY} -O ihex ${EXECUTABLE} ${PROJECT_NAME}.hex
|
||||
COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE} ${PROJECT_NAME}.bin
|
||||
)
|
||||
|
||||
# Print executable size
|
||||
add_custom_command(TARGET ${EXECUTABLE}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_SIZE} ${EXECUTABLE}
|
||||
)
|
||||
|
||||
# sort the RAM usage by size and place into a file
|
||||
add_custom_target(symbols
|
||||
DEPENDS ${EXECUTABLE}
|
||||
COMMENT "Print memory symbols by size"
|
||||
COMMAND ${CMAKE_NM} -t d -S --size-sort ${EXECUTABLE} 1> ${PROJECT_NAME}.nm
|
||||
COMMAND echo "RAM usage by size analysis in ${PROJECT_NAME}.nm"
|
||||
COMMAND echo "=ADDRESS= ==RAM=== = ==VARIABLE-NAME=="
|
||||
COMMAND tail ${PROJECT_NAME}.nm
|
||||
)
|
||||
|
||||
# calculate the worst case CSTACK memory usage by size and place into a file
|
||||
add_custom_target(cstack
|
||||
DEPENDS ${EXECUTABLE}
|
||||
COMMENT "Print CSTACK memory depth by size"
|
||||
COMMAND ${CMAKE_CSTACK} ${EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR} 1> ${PROJECT_NAME}.su
|
||||
COMMAND echo "C-Stack maxium depth analysis in ${PROJECT_NAME}.su"
|
||||
COMMAND echo "==DEPTH== : == Functions called =="
|
||||
COMMAND tail ${PROJECT_NAME}.su
|
||||
)
|
||||
|
||||
# Print file and library sizes
|
||||
add_custom_target(memmap
|
||||
DEPENDS ${PROJECT_NAME}.map
|
||||
COMMENT "Print file and library memory usage by size"
|
||||
COMMAND ${CMAKE_MEMAP} -t GCC_ARM ${PROJECT_NAME}.map
|
||||
)
|
||||
+41
-22
@@ -13,6 +13,9 @@ LIBRARY_STM32 = ./drivers/src
|
||||
LIBRARY_STM32_INCLUDES = ./drivers/inc
|
||||
LIBRARY_CMSIS = ./CMSIS
|
||||
|
||||
CSTACK_TOOL := $(BACNET_DIR)/tools/avstack/avstack.pl
|
||||
MEMAP_TOOL := $(BACNET_DIR)/tools/memap/memap.py
|
||||
|
||||
INCLUDES = -I$(PLATFORM_DIR)
|
||||
INCLUDES += -I$(LIBRARY_STM32_INCLUDES)
|
||||
INCLUDES += -I$(LIBRARY_CMSIS)
|
||||
@@ -23,7 +26,6 @@ PLATFORM_SRC = \
|
||||
$(PLATFORM_DIR)/bacnet.c \
|
||||
$(PLATFORM_DIR)/bo.c \
|
||||
$(PLATFORM_DIR)/device.c \
|
||||
$(PLATFORM_DIR)/dlmstp.c \
|
||||
$(PLATFORM_DIR)/netport.c \
|
||||
$(PLATFORM_DIR)/led.c \
|
||||
$(PLATFORM_DIR)/rs485.c \
|
||||
@@ -61,13 +63,15 @@ BACNET_SRC = \
|
||||
$(BACNET_CORE)/bacint.c \
|
||||
$(BACNET_CORE)/bacreal.c \
|
||||
$(BACNET_CORE)/bacstr.c \
|
||||
$(BACNET_CORE)/datalink/automac.c \
|
||||
$(BACNET_CORE)/datalink/crc.c \
|
||||
$(BACNET_CORE)/bactimevalue.c \
|
||||
$(BACNET_CORE)/calendar_entry.c \
|
||||
$(BACNET_CORE)/datetime.c \
|
||||
$(BACNET_CORE)/dailyschedule.c \
|
||||
$(BACNET_CORE)/dcc.c \
|
||||
$(BACNET_CORE)/hostnport.c \
|
||||
$(BACNET_CORE)/iam.c \
|
||||
$(BACNET_CORE)/ihave.c \
|
||||
$(BACNET_CORE)/hostnport.c \
|
||||
$(BACNET_CORE)/indtext.c \
|
||||
$(BACNET_CORE)/lighting.c \
|
||||
$(BACNET_CORE)/memcopy.c \
|
||||
$(BACNET_CORE)/npdu.c \
|
||||
@@ -76,16 +80,20 @@ BACNET_SRC = \
|
||||
$(BACNET_CORE)/reject.c \
|
||||
$(BACNET_CORE)/rp.c \
|
||||
$(BACNET_CORE)/rpm.c \
|
||||
$(BACNET_CORE)/special_event.c \
|
||||
$(BACNET_CORE)/timestamp.c \
|
||||
$(BACNET_CORE)/weeklyschedule.c \
|
||||
$(BACNET_CORE)/dailyschedule.c \
|
||||
$(BACNET_CORE)/bactimevalue.c \
|
||||
$(BACNET_CORE)/calendar_entry.c \
|
||||
$(BACNET_CORE)/special_event.c \
|
||||
$(BACNET_CORE)/whohas.c \
|
||||
$(BACNET_CORE)/whois.c \
|
||||
$(BACNET_CORE)/wp.c
|
||||
|
||||
DATALINK_SRC = \
|
||||
$(BACNET_CORE)/datalink/cobs.c \
|
||||
$(BACNET_CORE)/datalink/crc.c \
|
||||
$(BACNET_CORE)/datalink/dlmstp.c \
|
||||
$(BACNET_CORE)/datalink/mstp.c \
|
||||
$(BACNET_CORE)/datalink/mstptext.c
|
||||
|
||||
STM32_SRC = \
|
||||
$(LIBRARY_STM32)/stm32f10x_adc.c \
|
||||
$(LIBRARY_STM32)/stm32f10x_bkp.c \
|
||||
@@ -115,17 +123,20 @@ STM32_SRC = \
|
||||
CSRC = $(PLATFORM_SRC)
|
||||
CSRC += $(BASIC_SRC)
|
||||
CSRC += $(BACNET_SRC)
|
||||
CSRC += $(DATALINK_SRC)
|
||||
CSRC += $(STM32_SRC)
|
||||
|
||||
ASRC = $(LIBRARY_CMSIS)/gcc_ride7/startup_stm32f10x_xl.s
|
||||
|
||||
#Set the toolchain command names (only the ones needed are defined)
|
||||
# sudo apt install gcc-arm-none-eabi
|
||||
PREFIX ?= arm-none-eabi-
|
||||
|
||||
CC = $(PREFIX)gcc
|
||||
OBJCOPY = $(PREFIX)objcopy
|
||||
OBJDUMP = $(PREFIX)objdump
|
||||
AR = $(PREFIX)ar
|
||||
NM = $(PREFIX)nm
|
||||
SIZE = $(PREFIX)size
|
||||
|
||||
LDSCRIPT = $(PLATFORM_DIR)/stm32f10x.ld
|
||||
@@ -142,7 +153,7 @@ OPTIMIZE_FLAGS += -DNDEBUG
|
||||
|
||||
BACNET_FLAGS = -DBACDL_MSTP=1
|
||||
BACNET_FLAGS += -DBACAPP_MINIMAL
|
||||
BACNET_FLAGS += -DMAX_APDU=480
|
||||
BACNET_FLAGS += -DMAX_APDU=1476
|
||||
BACNET_FLAGS += -DBIG_ENDIAN=0
|
||||
BACNET_FLAGS += -DMAX_TSM_TRANSACTIONS=0
|
||||
BACNET_FLAGS += -DMAX_CHARACTER_STRING_BYTES=64
|
||||
@@ -161,6 +172,8 @@ CFLAGS += $(BACNET_FLAGS)
|
||||
CFLAGS += $(INCLUDES)
|
||||
# enable garbage collection of unused functions and data to shrink binary
|
||||
CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
|
||||
# enable stack usage tracking
|
||||
CFLAGS += -fstack-usage
|
||||
# function calls will not use any special __builtin_xx to allow debug/linking
|
||||
CFLAGS += -fno-builtin
|
||||
# place uninitialized global variables in the data section of the object file.
|
||||
@@ -199,6 +212,7 @@ ODFLAGS = -x --syms
|
||||
|
||||
AOBJ = $(ASRC:.s=.o)
|
||||
COBJ = $(CSRC:.c=.o)
|
||||
CSTACK = $(CSRC:.c=.su)
|
||||
|
||||
all: $(TARGET).bin $(TARGET).elf
|
||||
$(OBJDUMP) $(ODFLAGS) $(TARGET).elf > $(TARGET).dmp
|
||||
@@ -210,18 +224,22 @@ $(TARGET).bin: $(TARGET).elf
|
||||
$(TARGET).elf: $(COBJ) $(AOBJ) Makefile
|
||||
$(CC) $(CFLAGS) $(AOBJ) $(COBJ) $(LDFLAGS) -o $@
|
||||
|
||||
# allow a single file to be unoptimized for debugging purposes
|
||||
#dlmstp.o:
|
||||
# $(CC) -c $(CFLAGS) $*.c -o $@
|
||||
#
|
||||
#main.o:
|
||||
# $(CC) -c $(CFLAGS) $*.c -o $@
|
||||
#
|
||||
#$(BACNET_CORE)/npdu.o:
|
||||
# $(CC) -c $(CFLAGS) $*.c -o $@
|
||||
#
|
||||
#$(BACNET_CORE)/apdu.o:
|
||||
# $(CC) -c $(CFLAGS) $*.c -o $@
|
||||
.PHONY: ram-usage
|
||||
ram-usage:
|
||||
@$(NM) -t d -S --size-sort $(TARGET).elf 1> $(TARGET).nm
|
||||
@echo "=ADDRESS= ==SIZE== = ==VARIABLE NAME=="
|
||||
@tail $(TARGET).nm
|
||||
|
||||
.PHONY: cstack
|
||||
cstack:
|
||||
@$(CSTACK_TOOL) $(COBJ) 2> /dev/null 1> $(TARGET).su
|
||||
@head -n 25 $(TARGET).su
|
||||
|
||||
.PHONY: memap
|
||||
memap:
|
||||
# memmap needs Python and PrettyPrint and IntelHex
|
||||
# sudo apt install python3-prettytable python3-intelhex
|
||||
$(MEMAP_TOOL) -t GCC_ARM $(TARGET).map
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(OPTIMIZATION) $(CFLAGS) $*.c -o $@
|
||||
@@ -231,8 +249,9 @@ $(TARGET).elf: $(COBJ) $(AOBJ) Makefile
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
-rm -rf $(COBJ) $(AOBJ) $(COREOBJ)
|
||||
-rm -rf $(COBJ) $(AOBJ) $(COREOBJ) $(CSTACK)
|
||||
-rm -rf $(TARGET).elf $(TARGET).bin $(TARGET).dmp $(TARGET).map
|
||||
-rm -rf $(TARGET).su $(TARGET).nm
|
||||
-rm -rf *.lst
|
||||
|
||||
## Other dependencies
|
||||
|
||||
@@ -227,7 +227,7 @@
|
||||
<state>STM32F10X_XL</state>
|
||||
<state>USE_STDPERIPH_DRIVER</state>
|
||||
<state>BACDL_MSTP</state>
|
||||
<state>MAX_APDU=480</state>
|
||||
<state>MAX_APDU=1476</state>
|
||||
<state>MAX_TSM_TRANSACTIONS=0</state>
|
||||
<state>BACAPP_MINIMAL</state>
|
||||
</option>
|
||||
@@ -1079,6 +1079,9 @@
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\src\bacnet\dcc.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\src\bacnet\indtext.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\src\bacnet\iam.c</name>
|
||||
</file>
|
||||
@@ -1131,13 +1134,19 @@
|
||||
<group>
|
||||
<name>BACnet-Datalink</name>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\src\bacnet\datalink\automac.c</name>
|
||||
<name>$PROJ_DIR$\..\..\src\bacnet\datalink\cobs.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\src\bacnet\datalink\crc.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\dlmstp.c</name>
|
||||
<name>$PROJ_DIR$\..\..\src\bacnet\datalink\dlmstp.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\src\bacnet\datalink\mstp.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\src\bacnet\datalink\mstptext.c</name>
|
||||
</file>
|
||||
</group>
|
||||
<group>
|
||||
|
||||
@@ -45,10 +45,6 @@
|
||||
#include "bacnet/basic/object/netport.h"
|
||||
#endif
|
||||
|
||||
/* forward prototype */
|
||||
int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata);
|
||||
bool Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data);
|
||||
|
||||
static struct my_object_functions {
|
||||
BACNET_OBJECT_TYPE Object_Type;
|
||||
object_init_function Object_Init;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,8 +20,6 @@
|
||||
extern int errno;
|
||||
extern int __io_putchar(int ch);
|
||||
|
||||
register char * stack_ptr asm("sp");
|
||||
|
||||
char *__env[1] = { 0 };
|
||||
char **environ = __env;
|
||||
|
||||
@@ -61,6 +59,7 @@ int _write(int file, char *ptr, int len)
|
||||
|
||||
caddr_t _sbrk(int incr)
|
||||
{
|
||||
register char * stack_ptr asm("sp");
|
||||
extern char end asm("end");
|
||||
static char *heap_end;
|
||||
char *prev_heap_end;
|
||||
|
||||
+63
-1
@@ -27,13 +27,40 @@
|
||||
#include <stdint.h>
|
||||
#include "hardware.h"
|
||||
#include "bacnet/basic/sys/mstimer.h"
|
||||
#include "bacnet/basic/sys/mstimer.h"
|
||||
#include "bacnet/datalink/datalink.h"
|
||||
#include "bacnet/datalink/dlmstp.h"
|
||||
#include "bacnet/datalink/mstp.h"
|
||||
#include "rs485.h"
|
||||
#include "led.h"
|
||||
#include "bacnet.h"
|
||||
|
||||
/* local version override */
|
||||
char *BACnet_Version = "1.0";
|
||||
/* MS/TP port */
|
||||
static struct mstp_port_struct_t MSTP_Port;
|
||||
static struct dlmstp_rs485_driver RS485_Driver = {
|
||||
.init = rs485_init,
|
||||
.send = rs485_bytes_send,
|
||||
.read = rs485_byte_available,
|
||||
.transmitting = rs485_rts_enabled,
|
||||
.baud_rate = rs485_baud_rate,
|
||||
.baud_rate_set = rs485_baud_rate_set,
|
||||
.silence_milliseconds = rs485_silence_milliseconds,
|
||||
.silence_reset = rs485_silence_reset
|
||||
};
|
||||
static struct dlmstp_user_data_t MSTP_User_Data;
|
||||
static uint8_t Input_Buffer[DLMSTP_MPDU_MAX];
|
||||
static uint8_t Output_Buffer[DLMSTP_MPDU_MAX];
|
||||
|
||||
/**
|
||||
* @brief Called from _write() function from printf and friends
|
||||
* @param[in] ch Character to send
|
||||
*/
|
||||
int __io_putchar(int ch)
|
||||
{
|
||||
(void)ch;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
|
||||
@@ -102,6 +129,37 @@ void lse_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the MSTP datalink layer
|
||||
*/
|
||||
static void mstp_configure(void)
|
||||
{
|
||||
/* initialize MSTP datalink layer */
|
||||
MSTP_Port.Nmax_info_frames = DLMSTP_MAX_INFO_FRAMES;
|
||||
MSTP_Port.Nmax_master = DLMSTP_MAX_MASTER;
|
||||
MSTP_Port.InputBuffer = Input_Buffer;
|
||||
MSTP_Port.InputBufferSize = sizeof(Input_Buffer);
|
||||
MSTP_Port.OutputBuffer = Output_Buffer;
|
||||
MSTP_Port.OutputBufferSize = sizeof(Output_Buffer);
|
||||
/* user data */
|
||||
MSTP_Port.ZeroConfigEnabled = true;
|
||||
MSTP_Port.SlaveNodeEnabled = false;
|
||||
MSTP_User_Data.RS485_Driver = &RS485_Driver;
|
||||
MSTP_Port.UserData = &MSTP_User_Data;
|
||||
dlmstp_init((char *)&MSTP_Port);
|
||||
if (MSTP_Port.ZeroConfigEnabled) {
|
||||
dlmstp_set_mac_address(255);
|
||||
} else {
|
||||
/* FIXME: get the address from hardware DIP or from EEPROM */
|
||||
dlmstp_set_mac_address(1);
|
||||
}
|
||||
/* FIXME: get the baud rate from hardware DIP or from EEPROM */
|
||||
dlmstp_set_baud_rate(DLMSTP_BAUD_RATE_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Main entry point of the C application
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
struct mstimer Blink_Timer;
|
||||
@@ -116,9 +174,13 @@ int main(void)
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
|
||||
RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE,
|
||||
ENABLE);
|
||||
/* initialize hardware layer */
|
||||
mstimer_init();
|
||||
lse_init();
|
||||
led_init();
|
||||
/* initialize MSTP datalink layer */
|
||||
mstp_configure();
|
||||
/* initialize application layer*/
|
||||
bacnet_init();
|
||||
mstimer_set(&Blink_Timer, 125);
|
||||
for (;;) {
|
||||
|
||||
+95
-118
@@ -45,70 +45,35 @@ static FIFO_BUFFER Receive_Buffer;
|
||||
static struct mstimer Silence_Timer;
|
||||
/* baud rate */
|
||||
static uint32_t Baud_Rate = 38400;
|
||||
/* flag to track RTS status */
|
||||
static volatile bool Transmitting;
|
||||
|
||||
/* The minimum time after the end of the stop bit of the final octet of a */
|
||||
/* received frame before a node may enable its EIA-485 driver: 40 bit times. */
|
||||
/* At 9600 baud, 40 bit times would be about 4.166 milliseconds */
|
||||
/* At 19200 baud, 40 bit times would be about 2.083 milliseconds */
|
||||
/* At 38400 baud, 40 bit times would be about 1.041 milliseconds */
|
||||
/* At 57600 baud, 40 bit times would be about 0.694 milliseconds */
|
||||
/* At 76800 baud, 40 bit times would be about 0.520 milliseconds */
|
||||
/* At 115200 baud, 40 bit times would be about 0.347 milliseconds */
|
||||
/* 40 bits is 4 octets including a start and stop bit with each octet */
|
||||
#define Tturnaround (40UL)
|
||||
/* statistics */
|
||||
static volatile uint32_t RS485_Transmit_Bytes;
|
||||
static volatile uint32_t RS485_Receive_Bytes;
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Reset the silence on the wire timer.
|
||||
* Returns: nothing
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Reset the silence on the wire timer.
|
||||
*/
|
||||
void rs485_silence_reset(void)
|
||||
{
|
||||
mstimer_set(&Silence_Timer, 0);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Determine the amount of silence on the wire from the timer.
|
||||
* Returns: true if the amount of time has elapsed
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
bool rs485_silence_elapsed(uint32_t interval)
|
||||
/**
|
||||
* @brief Return the RS-485 silence time in milliseconds
|
||||
* @return silence time in milliseconds
|
||||
*/
|
||||
uint32_t rs485_silence_milliseconds(void)
|
||||
{
|
||||
return (mstimer_elapsed(&Silence_Timer) > interval);
|
||||
return mstimer_elapsed(&Silence_Timer);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Baud rate determines turnaround time.
|
||||
* Returns: amount of milliseconds
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
static uint16_t rs485_turnaround_time(void)
|
||||
{
|
||||
/* delay after reception before transmitting - per MS/TP spec */
|
||||
/* wait a minimum 40 bit times since reception */
|
||||
/* at least 2 ms for errors: rounding, clock tick */
|
||||
if (Baud_Rate) {
|
||||
return (2 + ((Tturnaround * 1000UL) / Baud_Rate));
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Use the silence timer to determine turnaround time.
|
||||
* Returns: true if turnaround time has expired.
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
bool rs485_turnaround_elapsed(void)
|
||||
{
|
||||
return (mstimer_elapsed(&Silence_Timer) > rs485_turnaround_time());
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Determines if an error occured while receiving
|
||||
* Returns: true an error occurred.
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
/**
|
||||
* @brief Determines if an error occured while receiving
|
||||
* @return true an error occurred
|
||||
*/
|
||||
bool rs485_receive_error(void)
|
||||
{
|
||||
return false;
|
||||
@@ -125,6 +90,7 @@ void USART2_IRQHandler(void)
|
||||
/* Read one byte from the receive data register */
|
||||
data_byte = USART_ReceiveData(USART2);
|
||||
(void)FIFO_Put(&Receive_Buffer, data_byte);
|
||||
RS485_Receive_Bytes++;
|
||||
}
|
||||
if (USART_GetFlagStatus(USART2, USART_FLAG_ORE) != RESET) {
|
||||
/* note: enabling RXNE interrupt also enables the ORE interrupt! */
|
||||
@@ -134,11 +100,35 @@ void USART2_IRQHandler(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* DESCRIPTION: Return true if a byte is available
|
||||
* RETURN: true if a byte is available, with the byte in the parameter
|
||||
* NOTES: none
|
||||
**************************************************************************/
|
||||
/**
|
||||
* @brief Control the DE and /RE pins on the RS-485 transceiver
|
||||
* @param enable - true to set DE and /RE high, false to set /DE and RE low
|
||||
*/
|
||||
void rs485_rts_enable(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
led_tx_on_interval(10);
|
||||
GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET);
|
||||
} else {
|
||||
GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_RESET);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine the status of the transmit-enable line on the RS-485
|
||||
* transceiver
|
||||
* @return true if RTS is enabled, false if RTS is disabled
|
||||
*/
|
||||
bool rs485_rts_enabled(void)
|
||||
{
|
||||
return Transmitting;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return true if a byte is available
|
||||
* @param data_register - byte in this parameter if there is one available
|
||||
* @return true if a byte is available, with the byte in the parameter
|
||||
*/
|
||||
bool rs485_byte_available(uint8_t *data_register)
|
||||
{
|
||||
bool data_available = false; /* return value */
|
||||
@@ -155,50 +145,37 @@ bool rs485_byte_available(uint8_t *data_register)
|
||||
return data_available;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* DESCRIPTION: Sends a byte of data
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
**************************************************************************/
|
||||
void rs485_byte_send(uint8_t tx_byte)
|
||||
{
|
||||
led_tx_on_interval(10);
|
||||
USART_SendData(USART2, tx_byte);
|
||||
rs485_silence_reset();
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Determines if a byte in the USART has been shifted from
|
||||
* register
|
||||
* Returns: true if the USART register is empty
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
/**
|
||||
* @brief Determines if a byte in the USART has been shifted from register
|
||||
* @return true if the USART register is empty
|
||||
*/
|
||||
bool rs485_byte_sent(void)
|
||||
{
|
||||
return USART_GetFlagStatus(USART2, USART_FLAG_TXE);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Determines if the entire frame is sent from USART FIFO
|
||||
* Returns: true if the USART FIFO is empty
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
/**
|
||||
* @brief Determines if the entire frame is sent from USART FIFO
|
||||
* @brief true if the USART FIFO is empty
|
||||
*/
|
||||
bool rs485_frame_sent(void)
|
||||
{
|
||||
return USART_GetFlagStatus(USART2, USART_FLAG_TC);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* DESCRIPTION: Send some data and wait until it is sent
|
||||
* RETURN: true if a collision or timeout occurred
|
||||
* NOTES: none
|
||||
**************************************************************************/
|
||||
/**
|
||||
* @brief Transmit one or more bytes on RS-485.
|
||||
* @param buffer - array of one or more bytes to transmit
|
||||
* @param nbytes - number of bytes to transmit
|
||||
* @return true if added to queue
|
||||
*/
|
||||
void rs485_bytes_send(uint8_t *buffer, /* data to send */
|
||||
uint16_t nbytes)
|
||||
{ /* number of bytes of data */
|
||||
uint8_t tx_byte;
|
||||
|
||||
while (nbytes) {
|
||||
rs485_rts_enable(true);
|
||||
/* Send the data byte */
|
||||
tx_byte = *buffer;
|
||||
/* Send one byte */
|
||||
@@ -208,22 +185,22 @@ void rs485_bytes_send(uint8_t *buffer, /* data to send */
|
||||
}
|
||||
buffer++;
|
||||
nbytes--;
|
||||
RS485_Transmit_Bytes++;
|
||||
}
|
||||
/* was the frame sent? */
|
||||
while (!rs485_frame_sent()) {
|
||||
/* do nothing - wait until the entire frame in the
|
||||
Transmit Shift Register has been shifted out */
|
||||
}
|
||||
rs485_rts_enable(false);
|
||||
rs485_silence_reset();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Configures the baud rate of the USART
|
||||
* Returns: nothing
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
/**
|
||||
* @brief Configures the baud rate of the USART
|
||||
*/
|
||||
static void rs485_baud_rate_configure(void)
|
||||
{
|
||||
USART_InitTypeDef USART_InitStructure;
|
||||
@@ -240,11 +217,10 @@ static void rs485_baud_rate_configure(void)
|
||||
USART_Init(USART2, &USART_InitStructure);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Sets the baud rate to non-volatile storeage and configures USART
|
||||
* Returns: true if a value baud rate was saved
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
/**
|
||||
* @brief Sets the baud rate to non-volatile storeage and configures USART
|
||||
* @return true if a value baud rate was saved
|
||||
*/
|
||||
bool rs485_baud_rate_set(uint32_t baud)
|
||||
{
|
||||
bool valid = true;
|
||||
@@ -267,35 +243,36 @@ bool rs485_baud_rate_set(uint32_t baud)
|
||||
return valid;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Determines the baud rate in bps
|
||||
* Returns: baud rate in bps
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
/**
|
||||
* @brief Return the RS-485 baud rate
|
||||
* @return baud - RS-485 baud rate in bits per second (bps)
|
||||
*/
|
||||
uint32_t rs485_baud_rate(void)
|
||||
{
|
||||
return Baud_Rate;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Enable the Request To Send (RTS) aka Transmit Enable pin
|
||||
* Returns: nothing
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
void rs485_rts_enable(bool enable)
|
||||
/**
|
||||
* @brief Return the RS-485 statistics for transmit bytes
|
||||
* @return number of bytes transmitted
|
||||
*/
|
||||
uint32_t rs485_bytes_transmitted(void)
|
||||
{
|
||||
if (enable) {
|
||||
GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET);
|
||||
} else {
|
||||
GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_RESET);
|
||||
}
|
||||
return RS485_Transmit_Bytes;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Initialize the room network USART
|
||||
* Returns: nothing
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
/**
|
||||
* @brief Return the RS-485 statistics for receive bytes
|
||||
* @return number of bytes received
|
||||
*/
|
||||
uint32_t rs485_bytes_received(void)
|
||||
{
|
||||
return RS485_Receive_Bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the room network USART
|
||||
*/
|
||||
void rs485_init(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
+14
-13
@@ -36,33 +36,34 @@ extern "C" {
|
||||
|
||||
void rs485_init(
|
||||
void);
|
||||
|
||||
void rs485_rts_enable(
|
||||
bool enable);
|
||||
bool rs485_rts_enabled(
|
||||
void);
|
||||
|
||||
bool rs485_byte_available(
|
||||
uint8_t * data_register);
|
||||
bool rs485_receive_error(
|
||||
void);
|
||||
void rs485_bytes_send(
|
||||
uint8_t * buffer, /* data to send */
|
||||
uint16_t nbytes); /* number of bytes of data */
|
||||
uint8_t * buffer,
|
||||
uint16_t nbytes);
|
||||
|
||||
uint32_t rs485_baud_rate(
|
||||
void);
|
||||
bool rs485_baud_rate_set(
|
||||
uint32_t baud);
|
||||
/* a granular approach */
|
||||
void rs485_byte_send(
|
||||
uint8_t data_register);
|
||||
bool rs485_byte_sent(
|
||||
void);
|
||||
bool rs485_frame_sent(
|
||||
void);
|
||||
bool rs485_turnaround_elapsed(
|
||||
void);
|
||||
|
||||
uint32_t rs485_silence_milliseconds(
|
||||
void);
|
||||
void rs485_silence_reset(
|
||||
void);
|
||||
bool rs485_silence_elapsed(
|
||||
uint32_t interval);
|
||||
|
||||
uint32_t rs485_bytes_transmitted(
|
||||
void);
|
||||
uint32_t rs485_bytes_received(
|
||||
void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user