Fixes after STM32 example merge

This commit is contained in:
Valerio De Benedetto 2024-12-08 11:38:45 +01:00
parent 3bf5ed37c8
commit c660369a43
6 changed files with 252 additions and 291 deletions

View File

@ -2,10 +2,10 @@ cmake_minimum_required(VERSION 3.16)
set(PROJ_NAME stm32-blackpill) set(PROJ_NAME stm32-blackpill)
include(FetchContent) include(FetchContent)
FetchContent_Declare( stm32_cmake FetchContent_Declare(stm32_cmake
GIT_REPOSITORY https://github.com/ObKo/stm32-cmake GIT_REPOSITORY https://github.com/ObKo/stm32-cmake
GIT_TAG v2.1.0 GIT_TAG v2.1.0
GIT_SHALLOW TRUE GIT_SHALLOW TRUE
) )
FetchContent_Populate(stm32_cmake) FetchContent_Populate(stm32_cmake)
set(CMAKE_TOOLCHAIN_FILE ${stm32_cmake_SOURCE_DIR}/cmake/stm32_gcc.cmake) set(CMAKE_TOOLCHAIN_FILE ${stm32_cmake_SOURCE_DIR}/cmake/stm32_gcc.cmake)
@ -20,24 +20,24 @@ find_package(CMSIS COMPONENTS STM32F401CC REQUIRED)
find_package(HAL COMPONENTS STM32F4 REQUIRED) find_package(HAL COMPONENTS STM32F4 REQUIRED)
add_compile_options( add_compile_options(
-mcpu=cortex-m4 -mcpu=cortex-m4
-mfpu=fpv4-sp-d16 -mfpu=fpv4-sp-d16
-mfloat-abi=hard -mfloat-abi=hard
) )
set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_INCLUDE_CURRENT_DIR ON)
set( FREERTOS_HEAP "4") set(FREERTOS_HEAP "4")
set( FREERTOS_PORT "GCC_ARM_CM4F") set(FREERTOS_PORT "GCC_ARM_CM4F")
add_library(freertos_config INTERFACE) add_library(freertos_config INTERFACE)
target_include_directories(freertos_config SYSTEM target_include_directories(freertos_config SYSTEM
INTERFACE INTERFACE
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
) )
FetchContent_Declare( freertos_kernel FetchContent_Declare(freertos_kernel
GIT_REPOSITORY https://github.com/FreeRTOS/FreeRTOS-Kernel.git GIT_REPOSITORY https://github.com/FreeRTOS/FreeRTOS-Kernel.git
GIT_TAG V11.1.0 GIT_TAG V11.1.0
GIT_SHALLOW TRUE GIT_SHALLOW TRUE
) )
FetchContent_MakeAvailable(freertos_kernel) FetchContent_MakeAvailable(freertos_kernel)
@ -45,82 +45,82 @@ FetchContent_MakeAvailable(freertos_kernel)
set(WIZ_CHIP W5500) set(WIZ_CHIP W5500)
FetchContent_Declare( FetchContent_Declare(
wizchip wizchip
GIT_REPOSITORY https://github.com/donghoonpark/wizchip-cmake GIT_REPOSITORY https://github.com/donghoonpark/wizchip-cmake
GIT_SHALLOW TRUE GIT_SHALLOW TRUE
) )
FetchContent_MakeAvailable(wizchip) FetchContent_MakeAvailable(wizchip)
FetchContent_Declare( FetchContent_Declare(
nanomodbus nanomodbus
GIT_REPOSITORY https://github.com/debevv/nanoMODBUS GIT_REPOSITORY https://github.com/debevv/nanoMODBUS
GIT_TAG v1.18.1 GIT_TAG v1.18.1
GIT_SHALLOW TRUE GIT_SHALLOW TRUE
) )
FetchContent_GetProperties(nanomodbus) FetchContent_GetProperties(nanomodbus)
if(NOT nanomodbus_POPULATED) if (NOT nanomodbus_POPULATED)
FetchContent_Populate(nanomodbus) FetchContent_Populate(nanomodbus)
endif() endif ()
add_library(nanomodbus ${nanomodbus_SOURCE_DIR}/nanomodbus.c) add_library(nanomodbus ${nanomodbus_SOURCE_DIR}/nanomodbus.c)
target_include_directories(nanomodbus PUBLIC ${nanomodbus_SOURCE_DIR}) target_include_directories(nanomodbus PUBLIC ${nanomodbus_SOURCE_DIR})
set(TARGET_NAMES modbus_rtu modbus_tcp) set(TARGET_NAMES modbus_rtu modbus_tcp)
foreach(TARGET_NAME ${TARGET_NAMES}) foreach (TARGET_NAME ${TARGET_NAMES})
add_executable(${TARGET_NAME} add_executable(${TARGET_NAME}
${TARGET_NAME}.c ${TARGET_NAME}.c
bsp/blackpill/blackpill.c bsp/blackpill/blackpill.c
nmbs/port.c nmbs/port.c
)
target_include_directories(
${TARGET_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/bsp
${CMAKE_CURRENT_SOURCE_DIR}/nmbs
)
if(${TARGET_NAME} STREQUAL "modbus_rtu")
target_compile_definitions(
${TARGET_NAME} PRIVATE
NMBS_RTU
) )
elseif(${TARGET_NAME} STREQUAL "modbus_tcp")
target_compile_definitions( target_include_directories(
${TARGET_NAME} PRIVATE ${TARGET_NAME} PRIVATE
NMBS_TCP ${CMAKE_CURRENT_SOURCE_DIR}/bsp
${CMAKE_CURRENT_SOURCE_DIR}/nmbs
) )
endif()
target_link_libraries( if (${TARGET_NAME} STREQUAL "modbus_rtu")
${TARGET_NAME} target_compile_definitions(
STM32::NoSys ${TARGET_NAME} PRIVATE
CMSIS::STM32::F401CC NMBS_RTU
HAL::STM32::F4::CORTEX )
HAL::STM32::F4::RCC elseif (${TARGET_NAME} STREQUAL "modbus_tcp")
HAL::STM32::F4::PWR target_compile_definitions(
HAL::STM32::F4::GPIO ${TARGET_NAME} PRIVATE
HAL::STM32::F4::TIM NMBS_TCP
HAL::STM32::F4::UART )
HAL::STM32::F4::USART endif ()
HAL::STM32::F4::SPI
HAL::STM32::F4::DMA
wizchip
freertos_kernel
nanomodbus
)
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD target_link_libraries(
COMMAND ${CMAKE_SIZE} $<TARGET_FILE:${TARGET_NAME}> ${TARGET_NAME}
) STM32::NoSys
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD CMSIS::STM32::F401CC
COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${TARGET_NAME}> ${TARGET_NAME}.hex HAL::STM32::F4::CORTEX
) HAL::STM32::F4::RCC
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD HAL::STM32::F4::PWR
COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${TARGET_NAME}> ${TARGET_NAME}.bin HAL::STM32::F4::GPIO
) HAL::STM32::F4::TIM
HAL::STM32::F4::UART
HAL::STM32::F4::USART
HAL::STM32::F4::SPI
HAL::STM32::F4::DMA
wizchip
freertos_kernel
nanomodbus
)
endforeach() add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
COMMAND ${CMAKE_SIZE} $<TARGET_FILE:${TARGET_NAME}>
)
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${TARGET_NAME}> ${TARGET_NAME}.hex
)
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${TARGET_NAME}> ${TARGET_NAME}.bin
)
endforeach ()

View File

@ -11,27 +11,23 @@
static void blink(void* args); static void blink(void* args);
static void modbus(void* args); static void modbus(void* args);
uint32_t HAL_GetTick(void) uint32_t HAL_GetTick(void) {
{
return xTaskGetTickCount(); return xTaskGetTickCount();
} }
int main(void) int main(void) {
{
BSP_Init(); BSP_Init();
xTaskCreate(blink, "blink", 128, NULL, 4, NULL); xTaskCreate(blink, "blink", 128, NULL, 4, NULL);
xTaskCreate(modbus, "modbus", 128 * 16, NULL, 2, NULL); xTaskCreate(modbus, "modbus", 128 * 16, NULL, 2, NULL);
vTaskStartScheduler(); vTaskStartScheduler();
for(;;){} for (;;) {}
} }
static void blink(void* args) static void blink(void* args) {
{ for (;;) {
for(;;)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
vTaskDelay(500); vTaskDelay(500);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
@ -40,15 +36,19 @@ static void blink(void* args)
} }
nmbs_t nmbs; nmbs_t nmbs;
nmbs_server_t nmbs_server = nmbs_server_t nmbs_server = {
{ .id = 0x01,
.id = 0x01, .coils =
.coils = {0,}, {
.regs = {0,}, 0,
},
.regs =
{
0,
},
}; };
static void modbus(void* args) static void modbus(void* args) {
{
#if TEST_SERVER #if TEST_SERVER
nmbs_server_init(&nmbs, &nmbs_server); nmbs_server_init(&nmbs, &nmbs_server);
#endif #endif
@ -59,7 +59,7 @@ static void modbus(void* args)
nmbs_client_init(&nmbs); nmbs_client_init(&nmbs);
#endif #endif
for(;;){ for (;;) {
#if TEST_SERVER #if TEST_SERVER
nmbs_server_poll(&nmbs); nmbs_server_poll(&nmbs);
taskYIELD(); taskYIELD();
@ -68,9 +68,8 @@ static void modbus(void* args)
nmbs_set_destination_rtu_address(&nmbs, 0x01); nmbs_set_destination_rtu_address(&nmbs, 0x01);
nmbs_error status = nmbs_read_holding_registers(&nmbs, 0, 32, regs_test); nmbs_error status = nmbs_read_holding_registers(&nmbs, 0, 32, regs_test);
status = nmbs_write_multiple_registers(&nmbs, 0, 32, regs_test); status = nmbs_write_multiple_registers(&nmbs, 0, 32, regs_test);
if(status != NMBS_ERROR_NONE) if (status != NMBS_ERROR_NONE) {
{ while (true) {}
while(true){}
} }
#endif #endif
} }

View File

@ -1,85 +1,68 @@
#include "blackpill/blackpill.h" #include "blackpill/blackpill.h"
#include "wizchip.h" #include "wizchip.h"
#include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h>
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h"
#include <socket.h>
#include "nanomodbus.h" #include "nanomodbus.h"
#include "nmbs/port.h" #include "nmbs/port.h"
#include "task.h"
#include <socket.h>
extern SPI_HandleTypeDef hspi1; extern SPI_HandleTypeDef hspi1;
wiz_NetInfo net_info = { wiz_NetInfo net_info = {
.mac = { 0xEA, 0x11, 0x22, 0x33, 0x44, 0xEA }, .mac = {0xEA, 0x11, 0x22, 0x33, 0x44, 0xEA},
.ip = {192, 168, 137, 100}, // You can find this ip if you set your ethernet port ip as 192.168.137.XXX .ip = {192, 168, 137, 100}, // You can find this ip if you set your ethernet port ip as 192.168.137.XXX
.sn = {255, 255, 255, 0}, .sn = {255, 255, 255, 0},
.gw = {192, 168, 137, 1}, .gw = {192, 168, 137, 1},
.dns = {0, 0, 0, 0}, .dns = {0, 0, 0, 0},
}; // Network information. }; // Network information.
uint8_t transaction_buf_sizes[] = { uint8_t transaction_buf_sizes[] = {2, 2, 2, 2, 2, 2, 2, 2}; // All 2kB buffer setting for each sockets
2, 2, 2, 2, 2, 2, 2, 2
}; // All 2kB buffer setting for each sockets
#if USE_HAL_SPI_REGISTER_CALLBACKS == 0 #if USE_HAL_SPI_REGISTER_CALLBACKS == 0
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef* hspi) {
{
wizchip_dma_rx_cplt((void*) hspi); wizchip_dma_rx_cplt((void*) hspi);
} }
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef* hspi) {
{
wizchip_dma_tx_cplt((void*) hspi); wizchip_dma_tx_cplt((void*) hspi);
} }
#endif #endif
uint32_t HAL_GetTick(void) uint32_t HAL_GetTick(void) {
{
return xTaskGetTickCount(); return xTaskGetTickCount();
} }
static void blink(void* args); static void blink(void* args);
static void modbus(void* args); static void modbus(void* args);
int main(void) int main(void) {
{
BSP_Init(); BSP_Init();
wizchip_register_hal( wizchip_register_hal(&hspi1, (fHalSpiTransaction) HAL_SPI_Receive, (fHalSpiTransaction) HAL_SPI_Transmit,
&hspi1, (fHalSpiTransactionDma) HAL_SPI_Receive_DMA, (fHalSpiTransactionDma) HAL_SPI_Transmit_DMA,
(fHalSpiTransaction) HAL_SPI_Receive, GPIOA, GPIO_PIN_15, (fHalGpioWritePin) HAL_GPIO_WritePin);
(fHalSpiTransaction) HAL_SPI_Transmit,
(fHalSpiTransactionDma) HAL_SPI_Receive_DMA,
(fHalSpiTransactionDma) HAL_SPI_Transmit_DMA,
GPIOA,
GPIO_PIN_15,
(fHalGpioWritePin) HAL_GPIO_WritePin
);
wizchip_init(transaction_buf_sizes, transaction_buf_sizes); wizchip_init(transaction_buf_sizes, transaction_buf_sizes);
setSHAR(net_info.mac); setSHAR(net_info.mac);
setSIPR(net_info.ip); setSIPR(net_info.ip);
setSUBR(net_info.sn); setSUBR(net_info.sn);
setGAR (net_info.gw); setGAR(net_info.gw);
xTaskCreate(blink, "blink", 128, NULL, 4, NULL); xTaskCreate(blink, "blink", 128, NULL, 4, NULL);
xTaskCreate(modbus, "modbus", 128 * 16, NULL, 2, NULL); xTaskCreate(modbus, "modbus", 128 * 16, NULL, 2, NULL);
vTaskStartScheduler(); vTaskStartScheduler();
while(true) while (true) {}
{
}
} }
static void blink(void* args) static void blink(void* args) {
{ for (;;) {
for(;;)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
vTaskDelay(500); vTaskDelay(500);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
@ -88,41 +71,43 @@ static void blink(void* args)
} }
static nmbs_t nmbs; static nmbs_t nmbs;
static nmbs_server_t nmbs_server = static nmbs_server_t nmbs_server = {
{ .id = 0x01,
.id = 0x01, .coils =
.coils = {0,}, {
.regs = {0,}, 0,
},
.regs =
{
0,
},
}; };
static void modbus(void* args) static void modbus(void* args) {
{
int status; int status;
nmbs_server_init(&nmbs, &nmbs_server); nmbs_server_init(&nmbs, &nmbs_server);
for(;;) for (;;) {
{ switch ((status = getSn_SR(MB_SOCKET))) {
switch ((status = getSn_SR(MB_SOCKET))) case SOCK_ESTABLISHED:
{ nmbs_server_poll(&nmbs);
case SOCK_ESTABLISHED: break;
nmbs_server_poll(&nmbs);
break;
case SOCK_INIT :
listen(MB_SOCKET);
break;
case SOCK_CLOSED:
socket(MB_SOCKET, Sn_MR_TCP, 502, 0);
break;
case SOCK_CLOSE_WAIT :
disconnect(MB_SOCKET);
break;
default: case SOCK_INIT:
taskYIELD(); listen(MB_SOCKET);
break; break;
case SOCK_CLOSED:
socket(MB_SOCKET, Sn_MR_TCP, 502, 0);
break;
case SOCK_CLOSE_WAIT:
disconnect(MB_SOCKET);
break;
default:
taskYIELD();
break;
} }
} }
} }

View File

@ -1,6 +1,6 @@
#include <string.h>
#include "nmbs/port.h" #include "nmbs/port.h"
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include <string.h>
#ifdef NMBS_TCP #ifdef NMBS_TCP
static int32_t read_socket(uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg); static int32_t read_socket(uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg);
@ -10,58 +10,60 @@ static int32_t write_socket(const uint8_t* buf, uint16_t count, int32_t byte_tim
static int32_t read_serial(uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg); static int32_t read_serial(uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg);
static int32_t write_serial(const uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg); static int32_t write_serial(const uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg);
#if MB_UART_DMA #if MB_UART_DMA
#include "queue.h" #include "queue.h"
xQueueHandle rtu_rx_q; xQueueHandle rtu_rx_q;
uint8_t rtu_rx_b[MB_RX_BUF_SIZE]; uint8_t rtu_rx_b[MB_RX_BUF_SIZE];
#endif #endif
#endif #endif
static nmbs_server_t* server; static nmbs_server_t* server;
static nmbs_error server_read_coils(uint16_t address, uint16_t quantity, nmbs_bitfield coils_out, uint8_t unit_id, void* arg); static nmbs_error server_read_coils(uint16_t address, uint16_t quantity, nmbs_bitfield coils_out, uint8_t unit_id,
static nmbs_error server_read_holding_registers(uint16_t address, uint16_t quantity, uint16_t* registers_out, uint8_t unit_id, void* arg); void* arg);
static nmbs_error server_read_holding_registers(uint16_t address, uint16_t quantity, uint16_t* registers_out,
uint8_t unit_id, void* arg);
static nmbs_error server_write_single_coil(uint16_t address, bool value, uint8_t unit_id, void* arg); static nmbs_error server_write_single_coil(uint16_t address, bool value, uint8_t unit_id, void* arg);
static nmbs_error server_write_multiple_coils(uint16_t address, uint16_t quantity, const nmbs_bitfield coils, uint8_t unit_id, void* arg); static nmbs_error server_write_multiple_coils(uint16_t address, uint16_t quantity, const nmbs_bitfield coils,
uint8_t unit_id, void* arg);
static nmbs_error server_write_single_register(uint16_t address, uint16_t value, uint8_t unit_id, void* arg); static nmbs_error server_write_single_register(uint16_t address, uint16_t value, uint8_t unit_id, void* arg);
static nmbs_error server_write_multiple_registers(uint16_t address, uint16_t quantity, const uint16_t* registers, uint8_t unit_id, void* arg); static nmbs_error server_write_multiple_registers(uint16_t address, uint16_t quantity, const uint16_t* registers,
uint8_t unit_id, void* arg);
nmbs_error nmbs_server_init(nmbs_t* nmbs, nmbs_server_t* _server) nmbs_error nmbs_server_init(nmbs_t* nmbs, nmbs_server_t* _server) {
{
nmbs_platform_conf conf; nmbs_platform_conf conf;
nmbs_callbacks cb; nmbs_callbacks cb;
nmbs_platform_conf_create(&conf); nmbs_platform_conf_create(&conf);
#ifdef NMBS_TCP #ifdef NMBS_TCP
conf.transport = NMBS_TRANSPORT_TCP; conf.transport = NMBS_TRANSPORT_TCP;
conf.read = read_socket; conf.read = read_socket;
conf.write = write_socket; conf.write = write_socket;
#endif #endif
#ifdef NMBS_RTU #ifdef NMBS_RTU
conf.transport = NMBS_TRANSPORT_RTU; conf.transport = NMBS_TRANSPORT_RTU;
conf.read = read_serial; conf.read = read_serial;
conf.write = write_serial; conf.write = write_serial;
#endif #endif
server = _server; server = _server;
nmbs_callbacks_create(&cb); nmbs_callbacks_create(&cb);
cb.read_coils = server_read_coils; cb.read_coils = server_read_coils;
cb.read_holding_registers = server_read_holding_registers; cb.read_holding_registers = server_read_holding_registers;
cb.write_single_coil = server_write_single_coil; cb.write_single_coil = server_write_single_coil;
cb.write_multiple_coils = server_write_multiple_coils; cb.write_multiple_coils = server_write_multiple_coils;
cb.write_single_register = server_write_single_register; cb.write_single_register = server_write_single_register;
cb.write_multiple_registers = server_write_multiple_registers; cb.write_multiple_registers = server_write_multiple_registers;
#if MB_UART_DMA #if MB_UART_DMA
rtu_rx_q = xQueueCreate(MB_RX_BUF_SIZE, sizeof(uint8_t)); rtu_rx_q = xQueueCreate(MB_RX_BUF_SIZE, sizeof(uint8_t));
HAL_UARTEx_ReceiveToIdle_DMA(&MB_UART, rtu_rx_b, MB_RX_BUF_SIZE); HAL_UARTEx_ReceiveToIdle_DMA(&MB_UART, rtu_rx_b, MB_RX_BUF_SIZE);
#endif #endif
nmbs_error status = nmbs_server_create(nmbs, server->id, &conf, &cb); nmbs_error status = nmbs_server_create(nmbs, server->id, &conf, &cb);
if(status != NMBS_ERROR_NONE) if (status != NMBS_ERROR_NONE) {
{
return status; return status;
} }
@ -71,25 +73,23 @@ nmbs_error nmbs_server_init(nmbs_t* nmbs, nmbs_server_t* _server)
return NMBS_ERROR_NONE; return NMBS_ERROR_NONE;
} }
nmbs_error nmbs_client_init(nmbs_t* nmbs) nmbs_error nmbs_client_init(nmbs_t* nmbs) {
{
nmbs_platform_conf conf; nmbs_platform_conf conf;
nmbs_platform_conf_create(&conf); nmbs_platform_conf_create(&conf);
#ifdef NMBS_TCP #ifdef NMBS_TCP
conf.transport = NMBS_TRANSPORT_TCP; conf.transport = NMBS_TRANSPORT_TCP;
conf.read = read_socket; conf.read = read_socket;
conf.write = write_socket; conf.write = write_socket;
#endif #endif
#ifdef NMBS_RTU #ifdef NMBS_RTU
conf.transport = NMBS_TRANSPORT_RTU; conf.transport = NMBS_TRANSPORT_RTU;
conf.read = read_serial; conf.read = read_serial;
conf.write = write_serial; conf.write = write_serial;
#endif #endif
nmbs_error status = nmbs_client_create(nmbs, &conf); nmbs_error status = nmbs_client_create(nmbs, &conf);
if(status != NMBS_ERROR_NONE) if (status != NMBS_ERROR_NONE) {
{
return status; return status;
} }
@ -100,27 +100,21 @@ nmbs_error nmbs_client_init(nmbs_t* nmbs)
} }
static nmbs_server_t* get_server(uint8_t id) static nmbs_server_t* get_server(uint8_t id) {
{ if (id == server->id) {
if(id == server->id)
{
return server; return server;
} }
else else {
{
return NULL; return NULL;
} }
} }
static nmbs_error server_read_coils(uint16_t address, uint16_t quantity, nmbs_bitfield coils_out, uint8_t unit_id, void* arg) static nmbs_error server_read_coils(uint16_t address, uint16_t quantity, nmbs_bitfield coils_out, uint8_t unit_id,
{ void* arg) {
nmbs_server_t* server = get_server(unit_id); nmbs_server_t* server = get_server(unit_id);
for(size_t i = 0; i < quantity; i++) for (size_t i = 0; i < quantity; i++) {
{ if ((address >> 3) > COIL_BUF_SIZE) {
if((address>>3) > COIL_BUF_SIZE)
{
return NMBS_ERROR_INVALID_REQUEST; return NMBS_ERROR_INVALID_REQUEST;
} }
nmbs_bitfield_write(coils_out, address, nmbs_bitfield_read(server->coils, address)); nmbs_bitfield_write(coils_out, address, nmbs_bitfield_read(server->coils, address));
@ -129,14 +123,12 @@ static nmbs_error server_read_coils(uint16_t address, uint16_t quantity, nmbs_bi
return NMBS_ERROR_NONE; return NMBS_ERROR_NONE;
} }
static nmbs_error server_read_holding_registers(uint16_t address, uint16_t quantity, uint16_t* registers_out, uint8_t unit_id, void* arg) static nmbs_error server_read_holding_registers(uint16_t address, uint16_t quantity, uint16_t* registers_out,
{ uint8_t unit_id, void* arg) {
nmbs_server_t* server = get_server(unit_id); nmbs_server_t* server = get_server(unit_id);
for(size_t i = 0; i < quantity; i++) for (size_t i = 0; i < quantity; i++) {
{ if (address > REG_BUF_SIZE) {
if(address > REG_BUF_SIZE)
{
return NMBS_ERROR_INVALID_REQUEST; return NMBS_ERROR_INVALID_REQUEST;
} }
registers_out[i] = server->regs[address++]; registers_out[i] = server->regs[address++];
@ -144,24 +136,20 @@ static nmbs_error server_read_holding_registers(uint16_t address, uint16_t quant
return NMBS_ERROR_NONE; return NMBS_ERROR_NONE;
} }
static nmbs_error server_write_single_coil(uint16_t address, bool value, uint8_t unit_id, void* arg) static nmbs_error server_write_single_coil(uint16_t address, bool value, uint8_t unit_id, void* arg) {
{
uint8_t coil = 0; uint8_t coil = 0;
if(value) if (value) {
{
coil |= 0x01; coil |= 0x01;
} }
return server_write_multiple_coils(address, 1, &coil, unit_id, arg); return server_write_multiple_coils(address, 1, &coil, unit_id, arg);
} }
static nmbs_error server_write_multiple_coils(uint16_t address, uint16_t quantity, const nmbs_bitfield coils, uint8_t unit_id, void* arg) static nmbs_error server_write_multiple_coils(uint16_t address, uint16_t quantity, const nmbs_bitfield coils,
{ uint8_t unit_id, void* arg) {
nmbs_server_t* server = get_server(unit_id); nmbs_server_t* server = get_server(unit_id);
for(size_t i = 0; i < quantity; i++) for (size_t i = 0; i < quantity; i++) {
{ if ((address >> 3) > COIL_BUF_SIZE) {
if((address>>3) > COIL_BUF_SIZE)
{
return NMBS_ERROR_INVALID_REQUEST; return NMBS_ERROR_INVALID_REQUEST;
} }
nmbs_bitfield_write(server->coils, address, nmbs_bitfield_read(coils, i)); nmbs_bitfield_write(server->coils, address, nmbs_bitfield_read(coils, i));
@ -170,20 +158,17 @@ static nmbs_error server_write_multiple_coils(uint16_t address, uint16_t quantit
return NMBS_ERROR_NONE; return NMBS_ERROR_NONE;
} }
static nmbs_error server_write_single_register(uint16_t address, uint16_t value, uint8_t unit_id, void* arg) static nmbs_error server_write_single_register(uint16_t address, uint16_t value, uint8_t unit_id, void* arg) {
{
uint16_t reg = value; uint16_t reg = value;
return server_write_multiple_registers(address, 1, &reg, unit_id, arg); return server_write_multiple_registers(address, 1, &reg, unit_id, arg);
} }
static nmbs_error server_write_multiple_registers(uint16_t address, uint16_t quantity, const uint16_t* registers, uint8_t unit_id, void* arg) static nmbs_error server_write_multiple_registers(uint16_t address, uint16_t quantity, const uint16_t* registers,
{ uint8_t unit_id, void* arg) {
nmbs_server_t* server = get_server(unit_id); nmbs_server_t* server = get_server(unit_id);
for(size_t i = 0; i < quantity; i++) for (size_t i = 0; i < quantity; i++) {
{ if (address > REG_BUF_SIZE) {
if(address > REG_BUF_SIZE)
{
return NMBS_ERROR_INVALID_REQUEST; return NMBS_ERROR_INVALID_REQUEST;
} }
server->regs[address++] = registers[i]; server->regs[address++] = registers[i];
@ -192,66 +177,53 @@ static nmbs_error server_write_multiple_registers(uint16_t address, uint16_t qua
} }
#ifdef NMBS_TCP #ifdef NMBS_TCP
int32_t read_socket(uint8_t *buf, uint16_t count, int32_t byte_timeout_ms, void *arg) int32_t read_socket(uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg) {
{
uint32_t tick_start = HAL_GetTick(); uint32_t tick_start = HAL_GetTick();
while(recv(MB_SOCKET, buf, count) != count) while (recv(MB_SOCKET, buf, count) != count) {
{ if (HAL_GetTick() - tick_start >= (uint32_t) byte_timeout_ms) {
if(HAL_GetTick() - tick_start >= (uint32_t)byte_timeout_ms)
{
return 0; return 0;
} }
} }
return count; return count;
} }
int32_t write_socket(const uint8_t *buf, uint16_t count, int32_t byte_timeout_ms, void *arg) int32_t write_socket(const uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg) {
{
return send(MB_SOCKET, buf, count); return send(MB_SOCKET, buf, count);
} }
#endif #endif
#ifdef NMBS_RTU #ifdef NMBS_RTU
static int32_t read_serial(uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg) static int32_t read_serial(uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg) {
{
#if MB_UART_DMA #if MB_UART_DMA
uint32_t tick_start = HAL_GetTick(); uint32_t tick_start = HAL_GetTick();
while(uxQueueMessagesWaiting(rtu_rx_q) < count) while (uxQueueMessagesWaiting(rtu_rx_q) < count) {
{ if (HAL_GetTick() - tick_start >= (uint32_t) byte_timeout_ms) {
if(HAL_GetTick() - tick_start >= (uint32_t)byte_timeout_ms)
{
return 0; return 0;
} }
} }
for(int i = 0; i < count; i++) for (int i = 0; i < count; i++) {
{
xQueueReceive(rtu_rx_q, buf + i, 1); xQueueReceive(rtu_rx_q, buf + i, 1);
} }
return count; return count;
#else #else
HAL_StatusTypeDef status = HAL_UART_Receive(&MB_UART, buf, count, byte_timeout_ms); HAL_StatusTypeDef status = HAL_UART_Receive(&MB_UART, buf, count, byte_timeout_ms);
if(status == HAL_OK) if (status == HAL_OK) {
{
return count; return count;
} }
else else {
{
return 0; return 0;
} }
#endif #endif
} }
static int32_t write_serial(const uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg) static int32_t write_serial(const uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg) {
{ #if MB_UART_DMA
#if MB_UART_DMA
HAL_UART_Transmit_DMA(&MB_UART, buf, count); HAL_UART_Transmit_DMA(&MB_UART, buf, count);
#else #else
HAL_StatusTypeDef status = HAL_UART_Transmit(&MB_UART, buf, count, byte_timeout_ms); HAL_StatusTypeDef status = HAL_UART_Transmit(&MB_UART, buf, count, byte_timeout_ms);
if(status == HAL_OK) if (status == HAL_OK) {
{
return count; return count;
} }
else else {
{
return 0; return 0;
} }
#endif #endif
@ -259,16 +231,13 @@ static int32_t write_serial(const uint8_t* buf, uint16_t count, int32_t byte_tim
#if MB_UART_DMA #if MB_UART_DMA
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef* huart, uint16_t Size) {
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if(huart == &MB_UART) if (huart == &MB_UART) {
{ for (int i = 0; i < Size; i++) {
for(int i = 0; i < Size; i++)
{
xQueueSendFromISR(rtu_rx_q, rtu_rx_b + i, &xHigherPriorityTaskWoken); xQueueSendFromISR(rtu_rx_q, rtu_rx_b + i, &xHigherPriorityTaskWoken);
} }
HAL_UARTEx_ReceiveToIdle_DMA(huart, rtu_rx_b, MB_RX_BUF_SIZE); HAL_UARTEx_ReceiveToIdle_DMA(huart, rtu_rx_b, MB_RX_BUF_SIZE);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
} }
// You may add your additional uart handler below // You may add your additional uart handler below

View File

@ -6,32 +6,32 @@ extern "C" {
#endif #endif
// Max size of coil and register area // Max size of coil and register area
#define COIL_BUF_SIZE 1024 #define COIL_BUF_SIZE 1024
#define REG_BUF_SIZE 2048 #define REG_BUF_SIZE 2048
// NanoModbus include // NanoModbus include
#include "nanomodbus.h" #include "nanomodbus.h"
#include "stm32f4xx_hal.h" #include "stm32f4xx_hal.h"
#ifdef NMBS_TCP #ifdef NMBS_TCP
// modbus tcp // modbus tcp
#define MB_SOCKET 1 #define MB_SOCKET 1
#include <socket.h> #include <socket.h>
#endif #endif
#ifdef NMBS_RTU #ifdef NMBS_RTU
// modbus rtu // modbus rtu
#define MB_UART huart1 #define MB_UART huart1
#define MB_UART_DMA 1 #define MB_UART_DMA 1
#define MB_RX_BUF_SIZE 256 #define MB_RX_BUF_SIZE 256
extern UART_HandleTypeDef MB_UART; extern UART_HandleTypeDef MB_UART;
#endif #endif
typedef struct tNmbsServer{ typedef struct tNmbsServer {
uint8_t id; uint8_t id;
uint8_t coils[COIL_BUF_SIZE]; uint8_t coils[COIL_BUF_SIZE];
uint16_t regs[REG_BUF_SIZE]; uint16_t regs[REG_BUF_SIZE];
}nmbs_server_t; } nmbs_server_t;
nmbs_error nmbs_server_init(nmbs_t* nmbs, nmbs_server_t* server); nmbs_error nmbs_server_init(nmbs_t* nmbs, nmbs_server_t* server);
nmbs_error nmbs_client_init(nmbs_t* nmbs); nmbs_error nmbs_client_init(nmbs_t* nmbs);

View File

@ -1,29 +1,37 @@
# STM32 nanomodbus porting # STM32 nanomodbus porting
## Target hardware ## Target hardware
![Blackpill board image](https://dfimg.dfrobot.com/enshop/image/data/DFR0864/Pinout-Diagram.png) ![Blackpill board image](https://dfimg.dfrobot.com/enshop/image/data/DFR0864/Pinout-Diagram.png)
- Blackpill board - Blackpill board
- STM32F401CCUx - STM32F401CCUx
- USART1 (with/without) DMA - USART1 (with/without) DMA
- PA9 : TX1 - PA9 : TX1
- PA10 : RX1 - PA10 : RX1
- SPI1 with DMA (connected to W5500) - SPI1 with DMA (connected to W5500)
- PB3 : SCK1 - PB3 : SCK1
- PB4 : MISO1 - PB4 : MISO1
- PB5 : MOSI1 - PB5 : MOSI1
- PA15 : NSS (Software select) - PA15 : NSS (Software select)
## Toolchain and environment ## Toolchain and environment
Tested on Mac OS Sonoma(Apple Silicon) & Windows 10 but other os having same toolchain should have no problem. Tested on Mac OS Sonoma(Apple Silicon) & Windows 10 but other os having same toolchain should have no problem.
- arm-none-eabi-gcc - arm-none-eabi-gcc
- cmake - cmake
- ninja - ninja
- openocd - openocd
- vscode - vscode
- CMake - CMake
- cortex-debug - cortex-debug
## Building
```
mkdir build
cd build
cmake ..
make -j16
```