mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-02-21 15:23:57 -04:00
AP_Networking: split ChibiOS code into its own backend
This commit is contained in:
parent
5705c68954
commit
fd70f5c7d7
@ -4,34 +4,31 @@
|
||||
#if AP_NETWORKING_ENABLED
|
||||
|
||||
#include "AP_Networking.h"
|
||||
#include "AP_Math/definitions.h"
|
||||
#include "AP_Networking_ChibiOS.h"
|
||||
#include <GCS_MAVLink/GCS.h>
|
||||
|
||||
extern const AP_HAL::HAL& hal;
|
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
|
||||
#include <hal_mii.h>
|
||||
#include <lwip/sockets.h>
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#endif
|
||||
|
||||
extern const AP_HAL::HAL& hal;
|
||||
|
||||
|
||||
const AP_Param::GroupInfo AP_Networking::var_info[] = {
|
||||
|
||||
// @Param: ENABLED
|
||||
// @DisplayName: Networking Enable
|
||||
// @Description: Networking Enable
|
||||
// @Values: 0:Disable,1:Enable
|
||||
// @RebootRequired: True
|
||||
// @User: Advanced
|
||||
AP_GROUPINFO_FLAGS("ENABLED", 0, AP_Networking, _param.enabled, 0, AP_PARAM_FLAG_ENABLE),
|
||||
AP_GROUPINFO_FLAGS("ENABLED", 1, AP_Networking, param.enabled, 0, AP_PARAM_FLAG_ENABLE),
|
||||
|
||||
// @Group: IPADDR
|
||||
// @Path: AP_Networking_address.cpp
|
||||
AP_SUBGROUPINFO(_param.ipaddr, "IPADDR", 1, AP_Networking, AP_Networking_IPV4),
|
||||
AP_SUBGROUPINFO(param.ipaddr, "IPADDR", 2, AP_Networking, AP_Networking_IPV4),
|
||||
|
||||
// @Param: NETMASK
|
||||
// @DisplayName: IP Subnet mask
|
||||
@ -39,7 +36,7 @@ const AP_Param::GroupInfo AP_Networking::var_info[] = {
|
||||
// @Range: 0 32
|
||||
// @RebootRequired: True
|
||||
// @User: Advanced
|
||||
AP_GROUPINFO("NETMASK", 2, AP_Networking, _param.netmask, AP_NETWORKING_DEFAULT_NETMASK),
|
||||
AP_GROUPINFO("NETMASK", 3, AP_Networking, param.netmask, AP_NETWORKING_DEFAULT_NETMASK),
|
||||
|
||||
// @Param: DHCP
|
||||
// @DisplayName: DHCP client
|
||||
@ -47,101 +44,39 @@ const AP_Param::GroupInfo AP_Networking::var_info[] = {
|
||||
// @Values: 0:Disable, 1:Enable
|
||||
// @RebootRequired: True
|
||||
// @User: Advanced
|
||||
AP_GROUPINFO("DHCP", 3, AP_Networking, _param.dhcp, AP_NETWORKING_DEFAULT_DHCP_ENABLE),
|
||||
AP_GROUPINFO("DHCP", 4, AP_Networking, param.dhcp, AP_NETWORKING_DEFAULT_DHCP_ENABLE),
|
||||
|
||||
// @Group: GWADDR
|
||||
// @Path: AP_Networking_address.cpp
|
||||
AP_SUBGROUPINFO(_param.gwaddr, "GWADDR", 4, AP_Networking, AP_Networking_IPV4),
|
||||
AP_SUBGROUPINFO(param.gwaddr, "GWADDR", 5, AP_Networking, AP_Networking_IPV4),
|
||||
|
||||
// @Group: MACADDR
|
||||
// @Path: AP_Networking_address.cpp
|
||||
AP_SUBGROUPINFO(_param.macaddr, "MACADDR", 5, AP_Networking, AP_Networking_MAC),
|
||||
AP_SUBGROUPINFO(param.macaddr, "MACADDR", 6, AP_Networking, AP_Networking_MAC),
|
||||
|
||||
AP_GROUPEND
|
||||
};
|
||||
|
||||
/*
|
||||
constructor
|
||||
*/
|
||||
AP_Networking::AP_Networking(void)
|
||||
{
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL
|
||||
if (_singleton != nullptr) {
|
||||
if (singleton != nullptr) {
|
||||
AP_HAL::panic("AP_Networking must be singleton");
|
||||
}
|
||||
#endif
|
||||
|
||||
_singleton = this;
|
||||
singleton = this;
|
||||
AP_Param::setup_object_defaults(this, var_info);
|
||||
}
|
||||
|
||||
#if defined(STM32_ETH_BUFFERS_EXTERN) && (CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS)
|
||||
stm32_eth_rx_descriptor_t *__eth_rd;
|
||||
stm32_eth_tx_descriptor_t *__eth_td;
|
||||
uint32_t *__eth_rb[STM32_MAC_RECEIVE_BUFFERS];
|
||||
uint32_t *__eth_tb[STM32_MAC_TRANSMIT_BUFFERS];
|
||||
|
||||
static bool allocate_buffers()
|
||||
{
|
||||
#define AP_NETWORKING_EXTERN_MAC_BUFFER_SIZE ((((STM32_MAC_BUFFERS_SIZE - 1) | 3) + 1) / 4) // typically == 381
|
||||
// check total size of buffers
|
||||
const uint32_t total_size = sizeof(stm32_eth_rx_descriptor_t)*STM32_MAC_RECEIVE_BUFFERS +
|
||||
sizeof(stm32_eth_tx_descriptor_t)*STM32_MAC_TRANSMIT_BUFFERS +
|
||||
sizeof(uint32_t)*STM32_MAC_RECEIVE_BUFFERS*AP_NETWORKING_EXTERN_MAC_BUFFER_SIZE +
|
||||
sizeof(uint32_t)*STM32_MAC_TRANSMIT_BUFFERS*AP_NETWORKING_EXTERN_MAC_BUFFER_SIZE; // typically == 9240
|
||||
|
||||
// ensure that we allocate 32-bit aligned memory, and mark it non-cacheable
|
||||
uint32_t size = 2;
|
||||
uint8_t rasr = 0;
|
||||
// find size closest to power of 2
|
||||
while (size < total_size) {
|
||||
size = size << 1;
|
||||
rasr++;
|
||||
}
|
||||
void *mem = malloc_eth_safe(size);
|
||||
if (mem == nullptr) {
|
||||
return false;
|
||||
}
|
||||
// ensure our memory is aligned
|
||||
// ref. Cortex-M7 peripherals PM0253, section 4.6.4 MPU region base address register
|
||||
if (((uint32_t)mem) % size) {
|
||||
AP_HAL::panic("Bad alignment of ETH memory");
|
||||
}
|
||||
|
||||
// for total_size == 9240, size should be 16384 and (rasr-1) should be 13 (MPU_RASR_SIZE_16K)
|
||||
const uint32_t rasr_size = MPU_RASR_SIZE(rasr-1);
|
||||
|
||||
// set up MPU region for buffers
|
||||
mpuConfigureRegion(STM32_NOCACHE_MPU_REGION_ETH,
|
||||
(uint32_t)mem,
|
||||
MPU_RASR_ATTR_AP_RW_RW |
|
||||
MPU_RASR_ATTR_NON_CACHEABLE |
|
||||
MPU_RASR_ATTR_S |
|
||||
rasr_size |
|
||||
MPU_RASR_ENABLE);
|
||||
mpuEnable(MPU_CTRL_PRIVDEFENA);
|
||||
SCB_CleanInvalidateDCache();
|
||||
|
||||
// assign buffers
|
||||
__eth_rd = (stm32_eth_rx_descriptor_t *)mem;
|
||||
__eth_td = (stm32_eth_tx_descriptor_t *)&__eth_rd[STM32_MAC_RECEIVE_BUFFERS];
|
||||
__eth_rb[0] = (uint32_t*)&__eth_td[STM32_MAC_TRANSMIT_BUFFERS];
|
||||
for (uint16_t i = 1; i < STM32_MAC_RECEIVE_BUFFERS; i++) {
|
||||
__eth_rb[i] = &(__eth_rb[i-1][AP_NETWORKING_EXTERN_MAC_BUFFER_SIZE]);
|
||||
}
|
||||
__eth_tb[0] = &(__eth_rb[STM32_MAC_RECEIVE_BUFFERS-1][AP_NETWORKING_EXTERN_MAC_BUFFER_SIZE]);
|
||||
for (uint16_t i = 1; i < STM32_MAC_TRANSMIT_BUFFERS; i++) {
|
||||
__eth_tb[i] = &(__eth_tb[i-1][AP_NETWORKING_EXTERN_MAC_BUFFER_SIZE]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif // STM32_ETH_BUFFERS_EXTERN
|
||||
|
||||
/*
|
||||
initialise networking subsystem
|
||||
*/
|
||||
void AP_Networking::init()
|
||||
{
|
||||
#ifdef HAL_GPIO_ETH_ENABLE
|
||||
hal.gpio->pinMode(HAL_GPIO_ETH_ENABLE, HAL_GPIO_OUTPUT);
|
||||
hal.gpio->write(HAL_GPIO_ETH_ENABLE, _param.enabled ? 1 : 0);
|
||||
#endif
|
||||
|
||||
if (!_param.enabled || _init.done) {
|
||||
if (!param.enabled || backend != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -151,110 +86,57 @@ void AP_Networking::init()
|
||||
const bool udid_is_ok = hal.util->get_system_id_unformatted(uuid, uuid_len) && uuid_len >= 3;
|
||||
if (udid_is_ok) {
|
||||
for (uint8_t i=0; i<3; i++) {
|
||||
_param.macaddr.set_default_address_byte(i, uuid[uuid_len-3+i]);
|
||||
param.macaddr.set_default_address_byte(i, uuid[uuid_len-3+i]);
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
|
||||
#ifdef STM32_ETH_BUFFERS_EXTERN
|
||||
if (!allocate_buffers()) {
|
||||
GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "NET: Failed to allocate buffers");
|
||||
return;
|
||||
}
|
||||
backend = new AP_Networking_ChibiOS(*this);
|
||||
#endif
|
||||
if (!macInit()) {
|
||||
GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "NET: macInit failed");
|
||||
|
||||
if (backend == nullptr) {
|
||||
GCS_SEND_TEXT(MAV_SEVERITY_INFO, "NET: backend failed");
|
||||
return;
|
||||
}
|
||||
|
||||
_param.macaddr.get_address(_activeSettings.macaddr);
|
||||
|
||||
#if !AP_NETWORKING_DHCP_AVAILABLE
|
||||
set_dhcp_enable(false);
|
||||
GCS_SEND_TEXT(MAV_SEVERITY_INFO, "NET: DHCP Not Supported");
|
||||
#endif
|
||||
|
||||
net_addr_mode_t addrMode;
|
||||
if (get_dhcp_enabled()) {
|
||||
_activeSettings.ip = 0;
|
||||
_activeSettings.nm = 0;
|
||||
_activeSettings.gw = 0;
|
||||
addrMode = NET_ADDRESS_DHCP;
|
||||
} else {
|
||||
_activeSettings.ip = get_ip_param();
|
||||
_activeSettings.nm = get_netmask_param();
|
||||
_activeSettings.gw = get_gateway_param();
|
||||
addrMode = NET_ADDRESS_STATIC;
|
||||
if (!backend->init()) {
|
||||
GCS_SEND_TEXT(MAV_SEVERITY_INFO, "NET: backend init failed");
|
||||
backend = nullptr;
|
||||
}
|
||||
|
||||
lwip_options.macaddress = _activeSettings.macaddr;
|
||||
lwip_options.address = _activeSettings.ip;
|
||||
lwip_options.netmask = _activeSettings.nm;
|
||||
lwip_options.gateway = _activeSettings.gw;
|
||||
lwip_options.addrMode = addrMode;
|
||||
|
||||
lwipInit(&lwip_options);
|
||||
#endif
|
||||
|
||||
#if AP_NETWORKING_DHCP_AVAILABLE
|
||||
if (get_dhcp_enabled()) {
|
||||
// give DHCP a chance to get an address before we show the boot-up address
|
||||
_activeSettings.announce_ms = AP_HAL::millis();
|
||||
}
|
||||
#endif
|
||||
announce_address_changes();
|
||||
|
||||
GCS_SEND_TEXT(MAV_SEVERITY_DEBUG,"NET: Initialized");
|
||||
_init.done = true;
|
||||
}
|
||||
|
||||
/*
|
||||
check if we should announce changes to IP addresses
|
||||
*/
|
||||
void AP_Networking::announce_address_changes()
|
||||
{
|
||||
const uint32_t now_ms = AP_HAL::millis();
|
||||
if (now_ms - _activeSettings.announce_ms < 1000) {
|
||||
// Never announce changes any faster than 1 sec
|
||||
return;
|
||||
}
|
||||
auto &as = backend->activeSettings;
|
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
|
||||
const uint32_t ip = lwipGetIp();
|
||||
const uint32_t nm = lwipGetNetmask();
|
||||
const uint32_t gw = lwipGetGateway();
|
||||
#else
|
||||
const uint32_t ip = 0;
|
||||
const uint32_t nm = 0;
|
||||
const uint32_t gw = 0;
|
||||
#endif
|
||||
|
||||
if (_activeSettings.announce_at_boot_done &&
|
||||
ip == _activeSettings.ip &&
|
||||
nm == _activeSettings.nm &&
|
||||
gw == _activeSettings.gw) {
|
||||
if (as.last_change_ms == 0 || as.last_change_ms == announce_ms) {
|
||||
// nothing changed and we've already printed it at least once. Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
_activeSettings.ip = ip;
|
||||
_activeSettings.nm = nm;
|
||||
_activeSettings.gw = gw;
|
||||
|
||||
GCS_SEND_TEXT(MAV_SEVERITY_INFO, "NET: IP %s", get_ip_active_str());
|
||||
GCS_SEND_TEXT(MAV_SEVERITY_INFO, "NET: Mask %s", get_netmask_active_str());
|
||||
GCS_SEND_TEXT(MAV_SEVERITY_INFO, "NET: Gateway %s", get_gateway_active_str());
|
||||
|
||||
if (!_activeSettings.announce_at_boot_done && ip == 0 && nm == 0 && gw == 0 && get_dhcp_enabled()) {
|
||||
GCS_SEND_TEXT(MAV_SEVERITY_INFO,"NET: DHCP enabled, waiting for IP");
|
||||
}
|
||||
|
||||
_activeSettings.announce_ms = now_ms;
|
||||
_activeSettings.announce_at_boot_done = true;
|
||||
announce_ms = as.last_change_ms;
|
||||
}
|
||||
|
||||
/*
|
||||
update called at 10Hz
|
||||
*/
|
||||
void AP_Networking::update()
|
||||
{
|
||||
if (!is_healthy()) {
|
||||
return;
|
||||
}
|
||||
|
||||
backend->update();
|
||||
announce_address_changes();
|
||||
}
|
||||
|
||||
@ -263,7 +145,6 @@ uint32_t AP_Networking::convert_netmask_bitcount_to_ip(const uint32_t netmask_bi
|
||||
if (netmask_bitcount > 32) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t netmask_ip = 0;
|
||||
for (uint32_t i=0; i<netmask_bitcount; i++) {
|
||||
netmask_ip |= (1UL << i);
|
||||
@ -299,6 +180,7 @@ const char* AP_Networking::convert_ip_to_str(const uint8_t ip[4])
|
||||
}
|
||||
return _str_buffer;
|
||||
}
|
||||
|
||||
const char* AP_Networking::convert_ip_to_str(const uint32_t ip)
|
||||
{
|
||||
uint8_t ip_array[4];
|
||||
@ -337,39 +219,8 @@ bool AP_Networking::convert_str_to_macaddr(const char *mac_str, uint8_t addr[6])
|
||||
return true;
|
||||
}
|
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
|
||||
int32_t AP_Networking::send_udp(struct udp_pcb *pcb, const ip4_addr_t &ip4_addr, const uint16_t port, const uint8_t* data, uint16_t data_len)
|
||||
{
|
||||
if (!AP::network().is_healthy()) {
|
||||
return ERR_IF;
|
||||
}
|
||||
AP_Networking *AP_Networking::singleton;
|
||||
|
||||
if (pcb == nullptr) {
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
data_len = (data == nullptr) ? 0 : data_len;
|
||||
|
||||
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, data_len, PBUF_RAM);
|
||||
if (p == nullptr) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
ip_addr_t dst;
|
||||
ip_addr_copy_from_ip4(dst, ip4_addr);
|
||||
|
||||
if (data_len > 0) {
|
||||
memcpy(p->payload, data, data_len);
|
||||
}
|
||||
|
||||
const err_t err = udp_sendto(pcb, p, &dst, port);
|
||||
pbuf_free(p);
|
||||
|
||||
return err == ERR_OK ? data_len : err;
|
||||
}
|
||||
#endif // #if CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
|
||||
|
||||
AP_Networking *AP_Networking::_singleton;
|
||||
namespace AP
|
||||
{
|
||||
AP_Networking &network()
|
||||
|
@ -7,17 +7,8 @@
|
||||
#include <AP_HAL/AP_HAL.h>
|
||||
#include <AP_Param/AP_Param.h>
|
||||
|
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
|
||||
#include "lwipthread.h"
|
||||
#include "lwip/udp.h"
|
||||
#include <lwip/ip_addr.h>
|
||||
#else
|
||||
#include <AP_Common/missing/byteswap.h>
|
||||
#define IP4_ADDR_VALUE(a,b,c,d) be32toh(UINT32_VALUE(a,b,c,d))
|
||||
#endif
|
||||
|
||||
#include "AP_Networking_address.h"
|
||||
#include "AP_Networking_backend.h"
|
||||
|
||||
/*
|
||||
Note! all uint32_t IPv4 addresses are in network byte order (big-endian)
|
||||
@ -26,6 +17,8 @@
|
||||
class AP_Networking
|
||||
{
|
||||
public:
|
||||
friend class AP_Networking_ChibiOS;
|
||||
|
||||
AP_Networking();
|
||||
|
||||
/* Do not allow copies */
|
||||
@ -34,42 +27,42 @@ public:
|
||||
// initialize the library. This should only be run once
|
||||
void init();
|
||||
|
||||
// update task. For most applications this should run as fast as possible. Default is 1000Hz for lowest latency
|
||||
// update task, called at 10Hz
|
||||
void update();
|
||||
|
||||
static AP_Networking *get_singleton(void)
|
||||
{
|
||||
return _singleton;
|
||||
return singleton;
|
||||
}
|
||||
|
||||
// Networking interface is enabled and initialized
|
||||
bool is_healthy() const
|
||||
{
|
||||
return _param.enabled && _init.done;
|
||||
return param.enabled && backend != nullptr;
|
||||
}
|
||||
|
||||
// returns true if DHCP is enabled
|
||||
bool get_dhcp_enabled() const
|
||||
{
|
||||
return _param.dhcp;
|
||||
return param.dhcp;
|
||||
}
|
||||
|
||||
// Sets DHCP to be enabled or disabled
|
||||
void set_dhcp_enable(const bool enable)
|
||||
{
|
||||
_param.dhcp.set(enable);
|
||||
param.dhcp.set(enable);
|
||||
}
|
||||
|
||||
// returns the 32bit value of the active IP address that is currently in use
|
||||
uint32_t get_ip_active() const
|
||||
{
|
||||
return _activeSettings.ip;
|
||||
return backend?backend->activeSettings.ip:0;
|
||||
}
|
||||
|
||||
// returns the 32bit value of the user-parameter static IP address
|
||||
uint32_t get_ip_param() const
|
||||
{
|
||||
return _param.ipaddr.get_uint32();
|
||||
return param.ipaddr.get_uint32();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -84,19 +77,19 @@ public:
|
||||
// sets the user-parameter static IP address from a 32bit value
|
||||
void set_ip_param(const uint32_t ip)
|
||||
{
|
||||
_param.ipaddr.set_uint32(ip);
|
||||
param.ipaddr.set_uint32(ip);
|
||||
}
|
||||
|
||||
// returns the 32bit value of the active Netmask that is currently in use
|
||||
uint32_t get_netmask_active() const
|
||||
{
|
||||
return _activeSettings.nm;
|
||||
return backend?backend->activeSettings.nm:0;
|
||||
}
|
||||
|
||||
// returns the 32bit value of the of the user-parameter static Netmask
|
||||
uint32_t get_netmask_param() const
|
||||
{
|
||||
return convert_netmask_bitcount_to_ip(_param.netmask.get());
|
||||
return convert_netmask_bitcount_to_ip(param.netmask.get());
|
||||
}
|
||||
|
||||
// returns a null terminated string of the active Netmask address. Example: "192.168.12.13"
|
||||
@ -117,17 +110,17 @@ public:
|
||||
|
||||
void set_netmask_param(const uint32_t nm)
|
||||
{
|
||||
_param.netmask.set(convert_netmask_ip_to_bitcount(nm));
|
||||
param.netmask.set(convert_netmask_ip_to_bitcount(nm));
|
||||
}
|
||||
|
||||
uint32_t get_gateway_active() const
|
||||
{
|
||||
return _activeSettings.gw;
|
||||
return backend?backend->activeSettings.gw:0;
|
||||
}
|
||||
|
||||
uint32_t get_gateway_param() const
|
||||
{
|
||||
return _param.gwaddr.get_uint32();
|
||||
return param.gwaddr.get_uint32();
|
||||
}
|
||||
|
||||
const char *get_gateway_active_str()
|
||||
@ -147,10 +140,9 @@ public:
|
||||
|
||||
void set_gateway_param(const uint32_t gw)
|
||||
{
|
||||
_param.gwaddr.set_uint32(gw);
|
||||
param.gwaddr.set_uint32(gw);
|
||||
}
|
||||
|
||||
|
||||
// helper functions to convert between 32bit IP addresses and null terminated strings and back
|
||||
static uint32_t convert_str_to_ip(const char* ip_str);
|
||||
static const char* convert_ip_to_str(const uint8_t ip[4]);
|
||||
@ -163,24 +155,13 @@ public:
|
||||
static uint32_t convert_netmask_bitcount_to_ip(const uint32_t netmask_bitcount);
|
||||
static uint8_t convert_netmask_ip_to_bitcount(const uint32_t netmask_ip);
|
||||
|
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
|
||||
static int32_t send_udp(struct udp_pcb *pcb, const ip4_addr_t &ip4_addr, const uint16_t port, const uint8_t* data, uint16_t data_len);
|
||||
#endif
|
||||
|
||||
static const struct AP_Param::GroupInfo var_info[];
|
||||
|
||||
private:
|
||||
static AP_Networking *_singleton;
|
||||
|
||||
uint8_t _num_instances; // number of feature instances
|
||||
static AP_Networking *singleton;
|
||||
|
||||
void announce_address_changes();
|
||||
|
||||
struct {
|
||||
bool done;
|
||||
} _init;
|
||||
|
||||
struct {
|
||||
AP_Networking_IPV4 ipaddr{AP_NETWORKING_DEFAULT_STATIC_IP_ADDR};
|
||||
AP_Int8 netmask; // bits to mask. example: (16 == 255.255.0.0) and (24 == 255.255.255.0)
|
||||
@ -190,24 +171,19 @@ private:
|
||||
AP_Networking_MAC macaddr{AP_NETWORKING_DEFAULT_MAC_ADDR};
|
||||
AP_Int8 enabled;
|
||||
AP_Int32 options;
|
||||
} _param;
|
||||
} param;
|
||||
|
||||
struct {
|
||||
uint32_t ip;
|
||||
uint32_t nm;
|
||||
uint32_t gw;
|
||||
uint32_t announce_ms;
|
||||
uint8_t macaddr[6];
|
||||
bool announce_at_boot_done;
|
||||
} _activeSettings;
|
||||
struct lwipthread_opts lwip_options;
|
||||
AP_Networking_backend *backend;
|
||||
|
||||
HAL_Semaphore _sem;
|
||||
HAL_Semaphore sem;
|
||||
|
||||
private:
|
||||
uint32_t announce_ms;
|
||||
};
|
||||
|
||||
namespace AP
|
||||
{
|
||||
AP_Networking &network();
|
||||
AP_Networking &network();
|
||||
};
|
||||
|
||||
#endif // AP_NETWORKING_ENABLED
|
||||
|
178
libraries/AP_Networking/AP_Networking_ChibiOS.cpp
Normal file
178
libraries/AP_Networking/AP_Networking_ChibiOS.cpp
Normal file
@ -0,0 +1,178 @@
|
||||
|
||||
#include "AP_Networking_Config.h"
|
||||
|
||||
#if AP_NETWORKING_ENABLED && CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
|
||||
|
||||
#include "AP_Networking.h"
|
||||
#include "AP_Networking_ChibiOS.h"
|
||||
#include <AP_HAL/AP_HAL.h>
|
||||
#include <GCS_MAVLink/GCS.h>
|
||||
|
||||
#include <lwipthread.h>
|
||||
#include <lwip/udp.h>
|
||||
#include <lwip/ip_addr.h>
|
||||
|
||||
extern const AP_HAL::HAL& hal;
|
||||
|
||||
#ifndef STM32_ETH_BUFFERS_EXTERN
|
||||
#error "Must use external ethernet buffers"
|
||||
#endif
|
||||
|
||||
/*
|
||||
these are referenced as globals inside lwip
|
||||
*/
|
||||
stm32_eth_rx_descriptor_t *__eth_rd;
|
||||
stm32_eth_tx_descriptor_t *__eth_td;
|
||||
uint32_t *__eth_rb[STM32_MAC_RECEIVE_BUFFERS];
|
||||
uint32_t *__eth_tb[STM32_MAC_TRANSMIT_BUFFERS];
|
||||
|
||||
/*
|
||||
allocate buffers for LWIP
|
||||
*/
|
||||
bool AP_Networking_ChibiOS::allocate_buffers()
|
||||
{
|
||||
#define AP_NETWORKING_EXTERN_MAC_BUFFER_SIZE ((((STM32_MAC_BUFFERS_SIZE - 1) | 3) + 1) / 4) // typically == 381
|
||||
// check total size of buffers
|
||||
const uint32_t total_size = sizeof(stm32_eth_rx_descriptor_t)*STM32_MAC_RECEIVE_BUFFERS +
|
||||
sizeof(stm32_eth_tx_descriptor_t)*STM32_MAC_TRANSMIT_BUFFERS +
|
||||
sizeof(uint32_t)*STM32_MAC_RECEIVE_BUFFERS*AP_NETWORKING_EXTERN_MAC_BUFFER_SIZE +
|
||||
sizeof(uint32_t)*STM32_MAC_TRANSMIT_BUFFERS*AP_NETWORKING_EXTERN_MAC_BUFFER_SIZE; // typically == 9240
|
||||
|
||||
// ensure that we allocate 32-bit aligned memory, and mark it non-cacheable
|
||||
uint32_t size = 2;
|
||||
uint8_t rasr = 0;
|
||||
// find size closest to power of 2
|
||||
while (size < total_size) {
|
||||
size = size << 1;
|
||||
rasr++;
|
||||
}
|
||||
void *mem = malloc_eth_safe(size);
|
||||
if (mem == nullptr) {
|
||||
return false;
|
||||
}
|
||||
// ensure our memory is aligned
|
||||
// ref. Cortex-M7 peripherals PM0253, section 4.6.4 MPU region base address register
|
||||
if (((uint32_t)mem) % size) {
|
||||
AP_HAL::panic("Bad alignment of ETH memory");
|
||||
}
|
||||
|
||||
// for total_size == 9240, size should be 16384 and (rasr-1) should be 13 (MPU_RASR_SIZE_16K)
|
||||
const uint32_t rasr_size = MPU_RASR_SIZE(rasr-1);
|
||||
|
||||
// set up MPU region for buffers
|
||||
mpuConfigureRegion(STM32_NOCACHE_MPU_REGION_ETH,
|
||||
(uint32_t)mem,
|
||||
MPU_RASR_ATTR_AP_RW_RW |
|
||||
MPU_RASR_ATTR_NON_CACHEABLE |
|
||||
MPU_RASR_ATTR_S |
|
||||
rasr_size |
|
||||
MPU_RASR_ENABLE);
|
||||
mpuEnable(MPU_CTRL_PRIVDEFENA);
|
||||
SCB_CleanInvalidateDCache();
|
||||
|
||||
// assign buffers
|
||||
__eth_rd = (stm32_eth_rx_descriptor_t *)mem;
|
||||
__eth_td = (stm32_eth_tx_descriptor_t *)&__eth_rd[STM32_MAC_RECEIVE_BUFFERS];
|
||||
__eth_rb[0] = (uint32_t*)&__eth_td[STM32_MAC_TRANSMIT_BUFFERS];
|
||||
for (uint16_t i = 1; i < STM32_MAC_RECEIVE_BUFFERS; i++) {
|
||||
__eth_rb[i] = &(__eth_rb[i-1][AP_NETWORKING_EXTERN_MAC_BUFFER_SIZE]);
|
||||
}
|
||||
__eth_tb[0] = &(__eth_rb[STM32_MAC_RECEIVE_BUFFERS-1][AP_NETWORKING_EXTERN_MAC_BUFFER_SIZE]);
|
||||
for (uint16_t i = 1; i < STM32_MAC_TRANSMIT_BUFFERS; i++) {
|
||||
__eth_tb[i] = &(__eth_tb[i-1][AP_NETWORKING_EXTERN_MAC_BUFFER_SIZE]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
initialise ChibiOS network backend using LWIP
|
||||
*/
|
||||
bool AP_Networking_ChibiOS::init()
|
||||
{
|
||||
#ifdef HAL_GPIO_ETH_ENABLE
|
||||
hal.gpio->pinMode(HAL_GPIO_ETH_ENABLE, HAL_GPIO_OUTPUT);
|
||||
hal.gpio->write(HAL_GPIO_ETH_ENABLE, _param.enabled ? 1 : 0);
|
||||
#endif
|
||||
|
||||
if (!allocate_buffers()) {
|
||||
GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "NET: Failed to allocate buffers");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!macInit()) {
|
||||
GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "NET: macInit failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !AP_NETWORKING_DHCP_AVAILABLE
|
||||
frontend.set_dhcp_enable(false);
|
||||
#endif
|
||||
|
||||
lwip_options = new lwipthread_opts;
|
||||
|
||||
if (frontend.get_dhcp_enabled()) {
|
||||
lwip_options->addrMode = NET_ADDRESS_DHCP;
|
||||
} else {
|
||||
lwip_options->addrMode = NET_ADDRESS_STATIC;
|
||||
lwip_options->address = frontend.get_ip_param();
|
||||
lwip_options->netmask = frontend.get_netmask_param();
|
||||
lwip_options->gateway = frontend.get_gateway_param();
|
||||
}
|
||||
frontend.param.macaddr.get_address(macaddr);
|
||||
lwip_options->macaddress = macaddr;
|
||||
|
||||
lwipInit(lwip_options);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
update called at 10Hz
|
||||
*/
|
||||
void AP_Networking_ChibiOS::update()
|
||||
{
|
||||
const uint32_t ip = lwipGetIp();
|
||||
const uint32_t nm = lwipGetNetmask();
|
||||
const uint32_t gw = lwipGetGateway();
|
||||
|
||||
if (ip != activeSettings.ip ||
|
||||
nm != activeSettings.nm ||
|
||||
gw != activeSettings.gw) {
|
||||
activeSettings.ip = ip;
|
||||
activeSettings.gw = gw;
|
||||
activeSettings.nm = nm;
|
||||
activeSettings.last_change_ms = AP_HAL::millis();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
send a UDP packet
|
||||
*/
|
||||
int32_t AP_Networking_ChibiOS::send_udp(struct udp_pcb *pcb, const ip4_addr_t &ip4_addr, const uint16_t port, const uint8_t* data, uint16_t data_len)
|
||||
{
|
||||
if (pcb == nullptr) {
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
data_len = (data == nullptr) ? 0 : data_len;
|
||||
|
||||
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, data_len, PBUF_RAM);
|
||||
if (p == nullptr) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
ip_addr_t dst;
|
||||
ip_addr_copy_from_ip4(dst, ip4_addr);
|
||||
|
||||
if (data_len > 0) {
|
||||
memcpy(p->payload, data, data_len);
|
||||
}
|
||||
|
||||
const err_t err = udp_sendto(pcb, p, &dst, port);
|
||||
pbuf_free(p);
|
||||
|
||||
return err == ERR_OK ? data_len : err;
|
||||
}
|
||||
|
||||
#endif // AP_NETWORKING_ENABLED && CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
|
||||
|
29
libraries/AP_Networking/AP_Networking_ChibiOS.h
Normal file
29
libraries/AP_Networking/AP_Networking_ChibiOS.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "AP_Networking_Config.h"
|
||||
|
||||
#if AP_NETWORKING_ENABLED && CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
|
||||
#include "AP_Networking_backend.h"
|
||||
|
||||
class AP_Networking_ChibiOS : public AP_Networking_backend
|
||||
{
|
||||
public:
|
||||
using AP_Networking_backend::AP_Networking_backend;
|
||||
|
||||
/* Do not allow copies */
|
||||
CLASS_NO_COPY(AP_Networking_ChibiOS);
|
||||
|
||||
bool init() override;
|
||||
void update() override;
|
||||
|
||||
private:
|
||||
bool allocate_buffers(void);
|
||||
int32_t send_udp(struct udp_pcb *pcb, const struct ip4_addr &ip4_addr, const uint16_t port, const uint8_t* data, uint16_t data_len);
|
||||
|
||||
private:
|
||||
struct lwipthread_opts *lwip_options;
|
||||
uint8_t macaddr[6];
|
||||
};
|
||||
|
||||
#endif // AP_NETWORKING_ENABLED && CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
|
||||
|
35
libraries/AP_Networking/AP_Networking_backend.h
Normal file
35
libraries/AP_Networking/AP_Networking_backend.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "AP_Networking_Config.h"
|
||||
|
||||
#if AP_NETWORKING_ENABLED
|
||||
|
||||
class AP_Networking;
|
||||
|
||||
class AP_Networking_backend
|
||||
{
|
||||
public:
|
||||
friend class AP_Networking;
|
||||
|
||||
AP_Networking_backend(AP_Networking &_frontend) : frontend(_frontend) {}
|
||||
|
||||
/* Do not allow copies */
|
||||
CLASS_NO_COPY(AP_Networking_backend);
|
||||
|
||||
virtual bool init() = 0;
|
||||
virtual void update() = 0;
|
||||
|
||||
protected:
|
||||
AP_Networking &frontend;
|
||||
|
||||
struct {
|
||||
uint32_t ip;
|
||||
uint32_t nm;
|
||||
uint32_t gw;
|
||||
uint32_t announce_ms;
|
||||
uint8_t macaddr[6];
|
||||
uint32_t last_change_ms;
|
||||
} activeSettings;
|
||||
};
|
||||
|
||||
#endif // AP_NETWORKING_ENABLED
|
Loading…
Reference in New Issue
Block a user