Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2019-10-26 11:46:31 +0300
committerDavid Crocker <dcrocker@eschertech.com>2019-10-26 11:46:31 +0300
commit587f49d5699a6a0fc3cb8307e17dd5c2fa43f73b (patch)
tree311cc1342502b74cad2808ee6bf4e9cb66a7ac4c
parentc25d73194252791ceb479ced79ffc77b31c810fe (diff)
Cached memory and Lwip networking changes
Put CAN, GMAC and some DMA buffers in new .ram_nocache memory section (needs new linker script in CoreNG) Added option to use separate Ethernet GMAC task (not working yet, so disabled - see LWIP_GMAC_TASK in compiler settings) Added code to set up non-cached memory usnig MPU (not working yet, so disabled)
-rw-r--r--.cproject4
-rw-r--r--src/CAN/CanInterface.cpp1
-rw-r--r--src/Duet3_V05/Pins_Duet3_V05.h5
-rw-r--r--src/Duet3_V06/Pins_Duet3_V06.h5
-rw-r--r--src/DuetNG/DueXn.cpp1
-rw-r--r--src/Endstops/ZProbe.cpp2
-rw-r--r--src/Heating/Heat.cpp2
-rw-r--r--src/Movement/HeightControl/HeightController.cpp1
-rw-r--r--src/Movement/Move.cpp1
-rw-r--r--src/Movement/StepperDrivers/TMC51xx.cpp6
-rw-r--r--src/Networking/LwipEthernet/GMAC/ethernet_sam.cpp2
-rw-r--r--src/Networking/LwipEthernet/GMAC/same70_gmac.cpp (renamed from src/Networking/LwipEthernet/GMAC/same70_gmac.c)105
-rw-r--r--src/Networking/LwipEthernet/Lwip/lwipopts.h12
-rw-r--r--src/Networking/LwipEthernet/Lwip/src/core/sys.c105
-rw-r--r--src/Networking/LwipEthernet/Lwip/src/core/sys.cpp255
-rw-r--r--src/Networking/LwipEthernet/Lwip/src/include/arch/cc.h2
-rw-r--r--src/Networking/LwipEthernet/Lwip/src/include/arch/sys_arch.h10
-rw-r--r--src/Networking/LwipEthernet/Lwip/src/include/lwip/sys.h15
-rw-r--r--src/Networking/LwipEthernet/LwipEthernetInterface.cpp16
-rw-r--r--src/Networking/Network.cpp11
-rw-r--r--src/Platform.cpp14
-rw-r--r--src/RepRap.cpp4
-rw-r--r--src/RepRapFirmware.h31
-rw-r--r--src/TaskPriorities.h29
-rw-r--r--src/Tasks.cpp85
-rw-r--r--src/Version.h4
26 files changed, 500 insertions, 228 deletions
diff --git a/.cproject b/.cproject
index c68caf47..f2487979 100644
--- a/.cproject
+++ b/.cproject
@@ -1201,6 +1201,7 @@
<listOptionValue builtIn="false" value="__SAME70Q20B__"/>
<listOptionValue builtIn="false" value="RTOS"/>
<listOptionValue builtIn="false" value="DUET3_V05"/>
+ <listOptionValue builtIn="false" value="LWIP_GMAC_TASK=0"/>
</option>
<option id="gnu.c.compiler.option.dialect.std.1184547155" name="Language standard" superClass="gnu.c.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.c.compiler.dialect.default" valueType="enumerated"/>
<option id="gnu.c.compiler.option.dialect.flags.1834251763" name="Other dialect flags" superClass="gnu.c.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=gnu99" valueType="string"/>
@@ -1271,6 +1272,7 @@
<listOptionValue builtIn="false" value="__SAME70Q20B__"/>
<listOptionValue builtIn="false" value="RTOS"/>
<listOptionValue builtIn="false" value="DUET3_V05"/>
+ <listOptionValue builtIn="false" value="LWIP_GMAC_TASK=0"/>
<listOptionValue builtIn="false" value="_XOPEN_SOURCE"/>
</option>
<option id="gnu.cpp.compiler.option.dialect.std.264694574" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/>
@@ -1540,6 +1542,7 @@
<listOptionValue builtIn="false" value="__SAME70Q20B__"/>
<listOptionValue builtIn="false" value="RTOS"/>
<listOptionValue builtIn="false" value="DUET3_V06"/>
+ <listOptionValue builtIn="false" value="LWIP_GMAC_TASK=0"/>
</option>
<option id="gnu.c.compiler.option.dialect.std.1738681846" name="Language standard" superClass="gnu.c.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.c.compiler.dialect.default" valueType="enumerated"/>
<option id="gnu.c.compiler.option.dialect.flags.1952106689" name="Other dialect flags" superClass="gnu.c.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=gnu99" valueType="string"/>
@@ -1607,6 +1610,7 @@
<listOptionValue builtIn="false" value="__SAME70Q20B__"/>
<listOptionValue builtIn="false" value="RTOS"/>
<listOptionValue builtIn="false" value="DUET3_V06"/>
+ <listOptionValue builtIn="false" value="LWIP_GMAC_TASK=0"/>
<listOptionValue builtIn="false" value="_XOPEN_SOURCE"/>
</option>
<option id="gnu.cpp.compiler.option.dialect.std.1240779290" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/>
diff --git a/src/CAN/CanInterface.cpp b/src/CAN/CanInterface.cpp
index 4099430f..fc00a910 100644
--- a/src/CAN/CanInterface.cpp
+++ b/src/CAN/CanInterface.cpp
@@ -17,6 +17,7 @@
#include "Movement/DriveMovement.h"
#include "Movement/StepTimer.h"
#include <RTOSIface/RTOSIface.h>
+#include <TaskPriorities.h>
#if HAS_LINUX_INTERFACE
# include "Linux/LinuxInterface.h"
diff --git a/src/Duet3_V05/Pins_Duet3_V05.h b/src/Duet3_V05/Pins_Duet3_V05.h
index e71976ce..cf1be0f4 100644
--- a/src/Duet3_V05/Pins_Duet3_V05.h
+++ b/src/Duet3_V05/Pins_Duet3_V05.h
@@ -252,6 +252,9 @@ constexpr Pin LinuxTfrReadyPin = PortEPin(2);
Spi * const LinuxSpi = SPI1;
// Timer allocation
+
+#if !LWIP_GMAC_TASK
+
// Network timer is timer 4 aka TC1 channel1
#define NETWORK_TC (TC1)
#define NETWORK_TC_CHAN (1)
@@ -259,6 +262,8 @@ Spi * const LinuxSpi = SPI1;
#define NETWORK_TC_HANDLER TC4_Handler
#define NETWORK_TC_ID ID_TC4
+#endif
+
// Step timer is timer 2 aka TC0 channel 2
#define STEP_TC (TC0)
#define STEP_TC_CHAN (2)
diff --git a/src/Duet3_V06/Pins_Duet3_V06.h b/src/Duet3_V06/Pins_Duet3_V06.h
index ee574454..c02f461b 100644
--- a/src/Duet3_V06/Pins_Duet3_V06.h
+++ b/src/Duet3_V06/Pins_Duet3_V06.h
@@ -265,6 +265,9 @@ constexpr Pin LinuxTfrReadyPin = PortEPin(2);
Spi * const LinuxSpi = SPI1;
// Timer allocation
+
+#if !LWIP_GMAC_TASK
+
// Network timer is timer 4 aka TC1 channel1
#define NETWORK_TC (TC1)
#define NETWORK_TC_CHAN (1)
@@ -272,6 +275,8 @@ Spi * const LinuxSpi = SPI1;
#define NETWORK_TC_HANDLER TC4_Handler
#define NETWORK_TC_ID ID_TC4
+#endif
+
// Step timer is timer 2 aka TC0 channel 2
#define STEP_TC (TC0)
#define STEP_TC_CHAN (2)
diff --git a/src/DuetNG/DueXn.cpp b/src/DuetNG/DueXn.cpp
index 3e6cab27..f568691a 100644
--- a/src/DuetNG/DueXn.cpp
+++ b/src/DuetNG/DueXn.cpp
@@ -11,6 +11,7 @@
#include "RepRap.h"
#include "Wire.h"
#include "Hardware/I2C.h"
+#include <TaskPriorities.h>
namespace DuetExpansion
{
diff --git a/src/Endstops/ZProbe.cpp b/src/Endstops/ZProbe.cpp
index 9edb6bc2..68e4530a 100644
--- a/src/Endstops/ZProbe.cpp
+++ b/src/Endstops/ZProbe.cpp
@@ -84,7 +84,7 @@ int ZProbe::GetReading() const
case ZProbeType::unfilteredDigital: // Switch connected to Z probe input, no filtering
case ZProbeType::blTouch: // blTouch is now unfiltered too
- zProbeVal = GetRawReading()/4;
+ zProbeVal = GetRawReading();
break;
case ZProbeType::zMotorStall:
diff --git a/src/Heating/Heat.cpp b/src/Heating/Heat.cpp
index daa93fed..6b335e7a 100644
--- a/src/Heating/Heat.cpp
+++ b/src/Heating/Heat.cpp
@@ -25,7 +25,7 @@ Licence: GPL
#include "RepRap.h"
#include "Sensors/TemperatureSensor.h"
#include "GCodes/GCodeBuffer/GCodeBuffer.h"
-#include "Tasks.h"
+#include <TaskPriorities.h>
#if SUPPORT_DHT_SENSOR
# include "Sensors/DhtSensor.h"
diff --git a/src/Movement/HeightControl/HeightController.cpp b/src/Movement/HeightControl/HeightController.cpp
index e8f2b0e2..a203e61e 100644
--- a/src/Movement/HeightControl/HeightController.cpp
+++ b/src/Movement/HeightControl/HeightController.cpp
@@ -15,6 +15,7 @@
#include "Heating/Heat.h"
#include "Heating/Sensors/TemperatureSensor.h"
#include "Movement/Move.h"
+#include <TaskPriorities.h>
HeightController::HeightController()
: heightControllerTask(nullptr), sensorNumber(-1),
diff --git a/src/Movement/Move.cpp b/src/Movement/Move.cpp
index 1c38bc7b..26574714 100644
--- a/src/Movement/Move.cpp
+++ b/src/Movement/Move.cpp
@@ -39,6 +39,7 @@
#include "GCodes/GCodeBuffer/GCodeBuffer.h"
#include "Tools/Tool.h"
#include "Endstops/ZProbe.h"
+#include <TaskPriorities.h>
#if SUPPORT_CAN_EXPANSION
# include "CAN/CanMotion.h"
diff --git a/src/Movement/StepperDrivers/TMC51xx.cpp b/src/Movement/StepperDrivers/TMC51xx.cpp
index 3ccc76b8..59776a9a 100644
--- a/src/Movement/StepperDrivers/TMC51xx.cpp
+++ b/src/Movement/StepperDrivers/TMC51xx.cpp
@@ -12,6 +12,7 @@
#if SUPPORT_TMC51xx
#include <RTOSIface/RTOSIface.h>
+#include <TaskPriorities.h>
#include <Movement/Move.h>
#include <Hardware/DmacManager.h>
#include <Endstops/Endstop.h>
@@ -911,8 +912,9 @@ static TmcDriverState driverStates[MaxSmartDrivers];
// TMC51xx management task
static Task<TmcTaskStackWords> tmcTask;
-static uint8_t sendData[5 * MaxSmartDrivers];
-static uint8_t rcvData[5 * MaxSmartDrivers];
+// Declare the DMA buffers with the __nocache attribute
+static __nocache uint8_t sendData[5 * MaxSmartDrivers];
+static __nocache uint8_t rcvData[5 * MaxSmartDrivers];
// Set up the PDC or DMAC to send a register and receive the status, but don't enable it yet
static void SetupDMA()
diff --git a/src/Networking/LwipEthernet/GMAC/ethernet_sam.cpp b/src/Networking/LwipEthernet/GMAC/ethernet_sam.cpp
index 1b685f93..a1ac7db8 100644
--- a/src/Networking/LwipEthernet/GMAC/ethernet_sam.cpp
+++ b/src/Networking/LwipEthernet/GMAC/ethernet_sam.cpp
@@ -214,8 +214,10 @@ bool ethernet_link_established(void)
*/
void ethernet_task(void)
{
+#if !LWIP_GMAC_TASK
/* Run polling tasks */
while (ethernetif_input(&gs_net_if)) { }
+#endif
/* Run periodic tasks */
ethernet_timers_update();
diff --git a/src/Networking/LwipEthernet/GMAC/same70_gmac.c b/src/Networking/LwipEthernet/GMAC/same70_gmac.cpp
index 1d22d5cc..12f070c8 100644
--- a/src/Networking/LwipEthernet/GMAC/same70_gmac.c
+++ b/src/Networking/LwipEthernet/GMAC/same70_gmac.cpp
@@ -41,13 +41,13 @@
*
*/
-#include "ethernet_phy.h"
#include "same70_gmac.h"
-#include "pmc.h"
-#include "sysclk.h"
+#include "pmc/pmc.h"
#include "conf_eth.h"
-#include <string.h>
+#include <cstring>
+extern "C" {
+#include "ethernet_phy.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/opt.h"
@@ -56,7 +56,20 @@
#include "lwip/stats.h"
#include "lwip/sys.h"
#include "netif/etharp.h"
+}
+
+#define __nocache __attribute__((section(".ram_nocache")))
+
+#if LWIP_GMAC_TASK
+
+// We can't #include RepRapFirmware.h here because that leads to a duplicate definition of ERR_TIMEOUT
+#include <RTOSIface/RTOSIface.h>
+#include <TaskPriorities.h>
+constexpr size_t EthernetTaskStackWords = 200;
+static Task<EthernetTaskStackWords> ethernetTask;
+
+#endif
/** Network interface identifier. */
#define IFNAME0 'e'
@@ -68,11 +81,10 @@
/** Network link speed. */
#define NET_LINK_SPEED 100000000
-#if (NO_SYS == 0)
+#if LWIP_GMAC_TASK
/* Interrupt priorities. (lowest value = highest priority) */
/* ISRs using FreeRTOS *FromISR APIs must have priorities below or equal to */
/* configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY. */
-#define INT_PRIORITY_GMAC 12
/** The GMAC interrupts to enable */
#define GMAC_INT_GROUP (GMAC_ISR_RCOMP | GMAC_ISR_ROVR | GMAC_ISR_HRESP | GMAC_ISR_TCOMP | GMAC_ISR_TUR | GMAC_ISR_TFC)
@@ -126,18 +138,12 @@ struct gmac_device {
/** Reference to lwIP netif structure. */
struct netif *netif;
-
-#if NO_SYS == 0
- /** RX task notification semaphore. */
- sys_sem_t rx_sem;
-#endif
};
/**
* GMAC driver instance.
*/
-COMPILER_ALIGNED(8)
-static struct gmac_device gs_gmac_dev;
+__nocache __aligned(8) static struct gmac_device gs_gmac_dev;
/**
* MAC address to use.
@@ -167,32 +173,30 @@ static gmac_dev_tx_cb_t gmac_rx_cb = NULL;
*/
void GMAC_Handler(void)
{
-#if 1
- volatile uint32_t ul_isr;
-
+#if LWIP_GMAC_TASK
/* Get interrupt status. */
- ul_isr = gmac_get_interrupt_status(GMAC);
+ const uint32_t ul_isr = gmac_get_interrupt_status(GMAC);
/* RX interrupts. */
- if ((ul_isr & GMAC_INT_GROUP) != 0 && gmac_rx_cb != NULL)
+ if (ul_isr & GMAC_INT_GROUP)
{
- gmac_rx_cb(ul_isr);
+ ethernetTask.GiveFromISR();
}
-#elif NO_SYS == 1
- NVIC_DisableIRQ(GMAC_IRQn);
#else
+# if 1
volatile uint32_t ul_isr;
- portBASE_TYPE xGMACTaskWoken = pdFALSE;
/* Get interrupt status. */
ul_isr = gmac_get_interrupt_status(GMAC);
/* RX interrupts. */
- if (ul_isr & GMAC_INT_GROUP) {
- xSemaphoreGiveFromISR(gs_gmac_dev.rx_sem, &xGMACTaskWoken);
+ if ((ul_isr & GMAC_INT_GROUP) != 0 && gmac_rx_cb != NULL)
+ {
+ gmac_rx_cb(ul_isr);
}
-
- portEND_SWITCHING_ISR(xGMACTaskWoken);
+# else
+ NVIC_DisableIRQ(GMAC_IRQn);
+# endif
#endif
}
@@ -340,7 +344,7 @@ static void gmac_low_level_init(struct netif *netif)
#endif
/* Init MAC PHY driver. */
- if (ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz()) != GMAC_OK) {
+ if (ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, SystemCoreClock) != GMAC_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("gmac_low_level_init: PHY init ERROR!\n"));
return;
}
@@ -376,7 +380,7 @@ static void gmac_low_level_init(struct netif *netif)
*/
static err_t gmac_low_level_output(struct netif *netif, struct pbuf *p)
{
- struct gmac_device *ps_gmac_dev = netif->state;
+ struct gmac_device *ps_gmac_dev = static_cast<gmac_device *>(netif->state);
struct pbuf *q = NULL;
uint8_t *buffer = 0;
@@ -398,6 +402,9 @@ static err_t gmac_low_level_output(struct netif *netif, struct pbuf *p)
gmac_enable_transmit(GMAC, true);
}
+ //TODO check buffer is free!!!
+ //TODO what if message is too long?
+
buffer = (uint8_t*)ps_gmac_dev->tx_desc[ps_gmac_dev->us_tx_idx].addr;
/* Copy pbuf chain into TX buffer. */
@@ -437,7 +444,7 @@ static err_t gmac_low_level_output(struct netif *netif, struct pbuf *p)
*/
static struct pbuf *gmac_low_level_input(struct netif *netif)
{
- struct gmac_device *ps_gmac_dev = netif->state;
+ struct gmac_device *ps_gmac_dev = static_cast<gmac_device *>(netif->state);
struct pbuf *p = 0;
uint32_t length = 0;
uint32_t ul_index = 0;
@@ -497,14 +504,14 @@ static struct pbuf *gmac_low_level_input(struct netif *netif)
ps_gmac_dev->us_rx_idx = (ps_gmac_dev->us_rx_idx + 1) % GMAC_RX_BUFFERS;
#if LWIP_STATS
- lwip_rx_count += length;
+ lwip_rx_count += length;
#endif
}
return p;
}
-#if NO_SYS == 0
+#if LWIP_GMAC_TASK
/**
* \brief GMAC task function. This function waits for the notification
* semaphore from the interrupt, processes the incoming packet and then
@@ -512,16 +519,16 @@ static struct pbuf *gmac_low_level_input(struct netif *netif)
*
* \param pvParameters A pointer to the gmac_device instance.
*/
-static void gmac_task(void *pvParameters)
+extern "C" void gmac_task(void *pvParameters)
{
- struct gmac_device *ps_gmac_dev = pvParameters;
+ gmac_device * const ps_gmac_dev = static_cast<gmac_device*>(pvParameters);
while (1) {
- /* Wait for the RX notification semaphore. */
- sys_arch_sem_wait(&ps_gmac_dev->rx_sem, 0);
+ /* Process the incoming packets */
+ while (ethernetif_input(ps_gmac_dev->netif)) { }
- /* Process the incoming packet. */
- ethernetif_input(ps_gmac_dev->netif);
+ /* Wait for the RX notification from the ISR */
+ TaskBase::Take();
}
}
#endif
@@ -548,7 +555,7 @@ bool ethernetif_input(struct netif *netif)
}
/* Points to packet payload, which starts with an Ethernet header. */
- ethhdr = p->payload;
+ ethhdr = static_cast<struct eth_hdr*>(p->payload);
switch (htons(ethhdr->type)) {
case ETHTYPE_IP:
@@ -618,23 +625,8 @@ err_t ethernetif_init(struct netif *netif)
/* Initialize the hardware */
gmac_low_level_init(netif);
-#if NO_SYS == 0
- err_t err;
- sys_thread_t id;
-
- /* Incoming packet notification semaphore. */
- err = sys_sem_new(&gs_gmac_dev.rx_sem, 0);
- LWIP_ASSERT("ethernetif_init: GMAC RX semaphore allocation ERROR!\n",
- (err == ERR_OK));
- if (err == ERR_MEM)
- return ERR_MEM;
-
- id = sys_thread_new("GMAC", gmac_task, &gs_gmac_dev,
- netifINTERFACE_TASK_STACK_SIZE, netifINTERFACE_TASK_PRIORITY);
- LWIP_ASSERT("ethernetif_init: GMAC Task allocation ERROR!\n",
- (id != 0));
- if (id == 0)
- return ERR_MEM;
+#if LWIP_GMAC_TASK
+ ethernetTask.Create(gmac_task, "ETHERNET", &gs_gmac_dev, TaskPriority::EthernetPriority);
#endif
return ERR_OK;
@@ -783,9 +775,10 @@ void ethernetif_set_mac_address(const uint8_t macAddress[])
}
}
+extern "C" u32_t millis();
+
u32_t sys_now(void)
{
- extern u32_t millis();
return millis();
}
diff --git a/src/Networking/LwipEthernet/Lwip/lwipopts.h b/src/Networking/LwipEthernet/Lwip/lwipopts.h
index cd6e92a9..367f37c8 100644
--- a/src/Networking/LwipEthernet/Lwip/lwipopts.h
+++ b/src/Networking/LwipEthernet/Lwip/lwipopts.h
@@ -56,7 +56,11 @@
* use lwIP facilities.
* Uses Raw API only.
*/
-#define NO_SYS 1
+#ifndef LWIP_GMAC_TASK
+# error LWIP_GMAC_TASK must be defined in compiler settings
+#endif
+
+#define NO_SYS (!LWIP_GMAC_TASK)
/**
* LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface
@@ -271,17 +275,19 @@ extern uint32_t trueRandom(void);
------------------------------------
*/
+#define FreeRtosIdlePriority 0
+
/** The stack sizes allocated to the netif stack: (256 * 4) = 1048 bytes. */
#define netifINTERFACE_TASK_STACK_SIZE 256
/** The priority of the netif stack. */
-#define netifINTERFACE_TASK_PRIORITY (tskIDLE_PRIORITY + 4)
+#define netifINTERFACE_TASK_PRIORITY (FreeRtosIdlePriority + 4) //TODO adjust
/** The stack sizes allocated to the TCPIP stack: (256 * 4) = 1048 bytes. */
#define TCPIP_THREAD_STACKSIZE 256
/** The priority of the TCPIP stack. */
-#define TCPIP_THREAD_PRIO (tskIDLE_PRIORITY + 5)
+#define TCPIP_THREAD_PRIO (FreeRtosIdlePriority + 5) //TODO adjust
/** The mailbox size for the tcpip thread messages */
#define TCPIP_MBOX_SIZE 16
diff --git a/src/Networking/LwipEthernet/Lwip/src/core/sys.c b/src/Networking/LwipEthernet/Lwip/src/core/sys.c
deleted file mode 100644
index d96efc8d..00000000
--- a/src/Networking/LwipEthernet/Lwip/src/core/sys.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- * @file
- * lwIP Operating System abstraction
- *
- */
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * 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. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-/**
- * @defgroup sys_layer Porting (system abstraction layer)
- * @ingroup lwip
- * @verbinclude "sys_arch.txt"
- *
- * @defgroup sys_os OS abstraction layer
- * @ingroup sys_layer
- * No need to implement functions in this section in NO_SYS mode.
- *
- * @defgroup sys_sem Semaphores
- * @ingroup sys_os
- *
- * @defgroup sys_mutex Mutexes
- * @ingroup sys_os
- * Mutexes are recommended to correctly handle priority inversion,
- * especially if you use LWIP_CORE_LOCKING .
- *
- * @defgroup sys_mbox Mailboxes
- * @ingroup sys_os
- *
- * @defgroup sys_time Time
- * @ingroup sys_layer
- *
- * @defgroup sys_prot Critical sections
- * @ingroup sys_layer
- * Used to protect short regions of code against concurrent access.
- * - Your system is a bare-metal system (probably with an RTOS)
- * and interrupts are under your control:
- * Implement this as LockInterrupts() / UnlockInterrupts()
- * - Your system uses an RTOS with deferred interrupt handling from a
- * worker thread: Implement as a global mutex or lock/unlock scheduler
- * - Your system uses a high-level OS with e.g. POSIX signals:
- * Implement as a global mutex
- *
- * @defgroup sys_misc Misc
- * @ingroup sys_os
- */
-
-#include <Lwip/src/include/lwip/opt.h>
-#include <Lwip/src/include/lwip/sys.h>
-
-/* Most of the functions defined in sys.h must be implemented in the
- * architecture-dependent file sys_arch.c */
-
-#if !NO_SYS
-
-#ifndef sys_msleep
-/**
- * Sleep for some ms. Timeouts are NOT processed while sleeping.
- *
- * @param ms number of milliseconds to sleep
- */
-void
-sys_msleep(u32_t ms)
-{
- if (ms > 0) {
- sys_sem_t delaysem;
- err_t err = sys_sem_new(&delaysem, 0);
- if (err == ERR_OK) {
- sys_arch_sem_wait(&delaysem, ms);
- sys_sem_free(&delaysem);
- }
- }
-}
-#endif /* sys_msleep */
-
-#endif /* !NO_SYS */
diff --git a/src/Networking/LwipEthernet/Lwip/src/core/sys.cpp b/src/Networking/LwipEthernet/Lwip/src/core/sys.cpp
new file mode 100644
index 00000000..fed46104
--- /dev/null
+++ b/src/Networking/LwipEthernet/Lwip/src/core/sys.cpp
@@ -0,0 +1,255 @@
+/**
+ * @file
+ * lwIP Operating System abstraction
+ *
+ */
+
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+/**
+ * @defgroup sys_layer Porting (system abstraction layer)
+ * @ingroup lwip
+ * @verbinclude "sys_arch.txt"
+ *
+ * @defgroup sys_os OS abstraction layer
+ * @ingroup sys_layer
+ * No need to implement functions in this section in NO_SYS mode.
+ *
+ * @defgroup sys_sem Semaphores
+ * @ingroup sys_os
+ *
+ * @defgroup sys_mutex Mutexes
+ * @ingroup sys_os
+ * Mutexes are recommended to correctly handle priority inversion,
+ * especially if you use LWIP_CORE_LOCKING .
+ *
+ * @defgroup sys_mbox Mailboxes
+ * @ingroup sys_os
+ *
+ * @defgroup sys_time Time
+ * @ingroup sys_layer
+ *
+ * @defgroup sys_prot Critical sections
+ * @ingroup sys_layer
+ * Used to protect short regions of code against concurrent access.
+ * - Your system is a bare-metal system (probably with an RTOS)
+ * and interrupts are under your control:
+ * Implement this as LockInterrupts() / UnlockInterrupts()
+ * - Your system uses an RTOS with deferred interrupt handling from a
+ * worker thread: Implement as a global mutex or lock/unlock scheduler
+ * - Your system uses a high-level OS with e.g. POSIX signals:
+ * Implement as a global mutex
+ *
+ * @defgroup sys_misc Misc
+ * @ingroup sys_os
+ */
+
+extern "C" {
+
+#include <Lwip/src/include/lwip/opt.h>
+#include <Lwip/src/include/lwip/sys.h>
+
+}
+
+#if !NO_SYS
+
+#include <RTOSIface/RTOSIface.h>
+
+extern void delay(uint32_t ms);
+extern uint32_t millis();
+
+extern "C" {
+
+/* Most of the functions defined in sys.h must be implemented in the
+ * architecture-dependent file sys_arch.c */
+
+/* sys_init() must be called before anything else. */
+void sys_init()
+{
+ // nothing needed yet
+}
+
+/**
+ * @ingroup sys_mutex
+ * Create a new mutex.
+ * Note that mutexes are expected to not be taken recursively by the lwIP code,
+ * so both implementation types (recursive or non-recursive) should work.
+ * @param mutex pointer to the mutex to create
+ * @return ERR_OK if successful, another err_t otherwise
+ */
+err_t sys_mutex_new(sys_mutex_t *mutex)
+{
+ mutex->m = new Mutex;
+ mutex->m->Create("LWIP"); // note, this will give duplicate mutex names but we can't help that
+ return ERR_OK;
+}
+
+/**
+ * @ingroup sys_mutex
+ * Lock a mutex
+ * @param mutex the mutex to lock
+ */
+void sys_mutex_lock(sys_mutex_t *mutex)
+{
+ mutex->m->Take();
+}
+
+/**
+ * @ingroup sys_mutex
+ * Unlock a mutex
+ * @param mutex the mutex to unlock
+ */
+void sys_mutex_unlock(sys_mutex_t *mutex)
+{
+ mutex->m->Release();
+}
+
+/* Mailbox functions. */
+
+/**
+ * @ingroup sys_mbox
+ * Create a new mbox of specified size
+ * @param mbox pointer to the mbox to create
+ * @param size (minimum) number of messages in this mbox
+ * @return ERR_OK if successful, another err_t otherwise
+ */
+err_t sys_mbox_new(sys_mbox_t *mbox, int size)
+{
+ auto q = new Queue<void *>;
+ q->Create("LWIP", size);
+ mbox->m = q;
+ return (q->IsValid()) ? ERR_OK : ERR_MEM;
+}
+
+/**
+ * @ingroup sys_mbox
+ * Post a message to an mbox - may not fail
+ * -> blocks if full, only used from tasks not from ISR
+ * @param mbox mbox to posts the message
+ * @param msg message to post (ATTENTION: can be NULL)
+ */
+void sys_mbox_post(sys_mbox_t *mbox, void *msg)
+{
+ static_cast<Queue<void*>*>(mbox->m)->PutToBack(msg, Mutex::TimeoutUnlimited);
+}
+
+/**
+ * @ingroup sys_mbox
+ * Try to post a message to an mbox - may fail if full or ISR
+ * @param mbox mbox to posts the message
+ * @param msg message to post (ATTENTION: can be NULL)
+ */
+err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
+{
+ return (static_cast<Queue<void*>*>(mbox->m)->PutToBack(msg, 0)) ? ERR_OK : ERR_WOULDBLOCK;
+}
+
+/**
+ * @ingroup sys_mbox
+ * Wait for a new message to arrive in the mbox
+ * @param mbox mbox to get a message from
+ * @param msg pointer where the message is stored
+ * @param timeout maximum time (in milliseconds) to wait for a message (0 = wait forever)
+ * @return time (in milliseconds) waited for a message, may be 0 if not waited
+ or SYS_ARCH_TIMEOUT on timeout
+ * The returned time has to be accurate to prevent timer jitter!
+ */
+u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
+{
+ const uint32_t now = millis();
+ return ((static_cast<Queue<void*>*>(mbox->m)->Get(*msg, timeout)))
+ ? millis() - now
+ : SYS_ARCH_TIMEOUT;
+}
+
+/**
+ * @ingroup sys_mbox
+ * Wait for a new message to arrive in the mbox
+ * @param mbox mbox to get a message from
+ * @param msg pointer where the message is stored
+ * @return 0 (milliseconds) if a message has been received
+ * or SYS_MBOX_EMPTY if the mailbox is empty
+ */
+u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
+{
+ return ((static_cast<Queue<void*>*>(mbox->m)->Get(*msg, 0)))
+ ? 0
+ : SYS_MBOX_EMPTY;
+}
+
+/**
+ * @ingroup sys_mbox
+ * Delete an mbox
+ * @param mbox mbox to delete
+ */
+void sys_mbox_free(sys_mbox_t *mbox);
+
+/**
+ * @ingroup sys_mbox
+ * Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid
+ */
+int sys_mbox_valid(sys_mbox_t *mbox);
+
+/**
+ * @ingroup sys_mbox
+ * Set an mbox invalid so that sys_mbox_valid returns 0
+ */
+void sys_mbox_set_invalid(sys_mbox_t *mbox);
+
+#ifndef sys_mbox_valid_val
+/**
+ * Same as sys_mbox_valid() but taking a value, not a pointer
+ */
+#define sys_mbox_valid_val(mbox) sys_mbox_valid(&(mbox))
+#endif
+#ifndef sys_mbox_set_invalid_val
+/**
+ * Same as sys_mbox_set_invalid() but taking a value, not a pointer
+ */
+#define sys_mbox_set_invalid_val(mbox) sys_mbox_set_invalid(&(mbox))
+#endif
+
+
+/**
+ * Sleep for some ms. Timeouts are NOT processed while sleeping.
+ *
+ * @param ms number of milliseconds to sleep
+ */
+void sys_msleep(u32_t ms)
+{
+ delay(ms);
+}
+
+}
+
+#endif /* !NO_SYS */
diff --git a/src/Networking/LwipEthernet/Lwip/src/include/arch/cc.h b/src/Networking/LwipEthernet/Lwip/src/include/arch/cc.h
index e7a123b5..c9132ea7 100644
--- a/src/Networking/LwipEthernet/Lwip/src/include/arch/cc.h
+++ b/src/Networking/LwipEthernet/Lwip/src/include/arch/cc.h
@@ -96,7 +96,7 @@ typedef uintptr_t mem_ptr_t;
to let sys.h use binary semaphores instead of mutexes - as before in 1.3.2
Refer CHANGELOG
*/
-#define LWIP_COMPAT_MUTEX 1
+#define LWIP_COMPAT_MUTEX 0
/* Make lwip/arch.h define the codes which are used throughout */
#define LWIP_PROVIDE_ERRNO
diff --git a/src/Networking/LwipEthernet/Lwip/src/include/arch/sys_arch.h b/src/Networking/LwipEthernet/Lwip/src/include/arch/sys_arch.h
index b8a2a709..d077feed 100644
--- a/src/Networking/LwipEthernet/Lwip/src/include/arch/sys_arch.h
+++ b/src/Networking/LwipEthernet/Lwip/src/include/arch/sys_arch.h
@@ -8,8 +8,16 @@ typedef void * sys_prot_t;
typedef void * sys_sem_t;
-typedef void * sys_mbox_t;
+typedef struct
+{
+ struct QueueBase *m;
+} sys_mbox_t;
typedef void * sys_thread_t;
+typedef struct
+{
+ struct Mutex *m;
+} sys_mutex_t;
+
#endif /* __ARCH_SYS_ARCH_H__ */
diff --git a/src/Networking/LwipEthernet/Lwip/src/include/lwip/sys.h b/src/Networking/LwipEthernet/Lwip/src/include/lwip/sys.h
index a3e4f0aa..3bfa245f 100644
--- a/src/Networking/LwipEthernet/Lwip/src/include/lwip/sys.h
+++ b/src/Networking/LwipEthernet/Lwip/src/include/lwip/sys.h
@@ -267,8 +267,6 @@ err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg);
* The returned time has to be accurate to prevent timer jitter!
*/
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout);
-/* Allow port to override with a macro, e.g. special timeout for sys_arch_mbox_fetch() */
-#ifndef sys_arch_mbox_tryfetch
/**
* @ingroup sys_mbox
* Wait for a new message to arrive in the mbox
@@ -278,32 +276,27 @@ u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout);
* or SYS_MBOX_EMPTY if the mailbox is empty
*/
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg);
-#endif
-/**
- * For now, we map straight to sys_arch implementation.
- */
+
#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg)
+#define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0)
+
/**
* @ingroup sys_mbox
* Delete an mbox
* @param mbox mbox to delete
*/
void sys_mbox_free(sys_mbox_t *mbox);
-#define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0)
-#ifndef sys_mbox_valid
/**
* @ingroup sys_mbox
* Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid
*/
int sys_mbox_valid(sys_mbox_t *mbox);
-#endif
-#ifndef sys_mbox_set_invalid
/**
* @ingroup sys_mbox
* Set an mbox invalid so that sys_mbox_valid returns 0
*/
void sys_mbox_set_invalid(sys_mbox_t *mbox);
-#endif
+
#ifndef sys_mbox_valid_val
/**
* Same as sys_mbox_valid() but taking a value, not a pointer
diff --git a/src/Networking/LwipEthernet/LwipEthernetInterface.cpp b/src/Networking/LwipEthernet/LwipEthernetInterface.cpp
index f0f00961..c9e14533 100644
--- a/src/Networking/LwipEthernet/LwipEthernetInterface.cpp
+++ b/src/Networking/LwipEthernet/LwipEthernetInterface.cpp
@@ -49,7 +49,10 @@ static LwipEthernetInterface *ethernetInterface;
extern "C"
{
static volatile bool lwipLocked = false;
+
+#if !LWIP_GMAC_TASK
static volatile bool resetCallback = false;
+#endif
// Lock functions for LwIP (LwIP isn't thread-safe when working with the raw API)
bool LockLWIP()
@@ -70,6 +73,8 @@ void UnlockLWIP()
// Callback functions for the GMAC driver and for LwIP
+#if !LWIP_GMAC_TASK
+
// Called from ISR
static void ethernet_rx_callback(uint32_t ul_status)
{
@@ -87,15 +92,20 @@ static void ethernet_rx_callback(uint32_t ul_status)
}
}
+#endif
+
// Task function to keep the GMAC and LwIP running
void DoEthernetTask()
{
ethernet_task();
+
+#if !LWIP_GMAC_TASK
if (resetCallback)
{
resetCallback = false;
ethernet_set_rx_callback(&ethernet_rx_callback);
}
+#endif
}
// Callback functions for LWIP (may be called from ISR)
@@ -385,7 +395,9 @@ void LwipEthernetInterface::Start()
initialised = true;
}
+#if !LWIP_GMAC_TASK
resetCallback = true; // reset EMAC RX callback on next Spin call
+#endif
state = NetworkState::establishingLink;
}
@@ -395,7 +407,9 @@ void LwipEthernetInterface::Stop()
if (state != NetworkState::disabled)
{
netif_set_down(&gs_net_if);
+#if !LWIP_GMAC_TASK
resetCallback = false;
+#endif
ethernet_set_rx_callback(nullptr);
#if defined(DUET3)
@@ -520,11 +534,13 @@ void LwipEthernetInterface::Spin(bool full)
void LwipEthernetInterface::Interrupt()
{
+#if !LWIP_GMAC_TASK
if (initialised && LockLWIP())
{
ethernet_timers_update();
UnlockLWIP();
}
+#endif
}
void LwipEthernetInterface::Diagnostics(MessageType mtype)
diff --git a/src/Networking/Network.cpp b/src/Networking/Network.cpp
index 7fb550b6..879db063 100644
--- a/src/Networking/Network.cpp
+++ b/src/Networking/Network.cpp
@@ -28,14 +28,15 @@
#include "RTOSPlusTCPEthernet/RTOSPlusTCPEthernetInterface.h"
#endif
-#include "Platform.h"
-#include "RepRap.h"
+#include <Platform.h>
+#include <RepRap.h>
#include "HttpResponder.h"
#include "FtpResponder.h"
#include "TelnetResponder.h"
-#include "General/IP4String.h"
-#include "Version.h"
-#include "Movement/StepTimer.h"
+#include <General/IP4String.h>
+#include <Version.h>
+#include <Movement/StepTimer.h>
+#include <TaskPriorities.h>
#ifdef __LPC17xx__
constexpr size_t NetworkStackWords = 470;
diff --git a/src/Platform.cpp b/src/Platform.cpp
index feb79196..7ee138c1 100644
--- a/src/Platform.cpp
+++ b/src/Platform.cpp
@@ -91,6 +91,10 @@ extern uint32_t _estack; // defined in the linker script
# error Missing feature definition
#endif
+#if HAS_LWIP_NETWORKING && !defined(LWIP_GMAC_TASK)
+# error LWIP_GMAC_TASK must be defined in compiler settings
+#endif
+
#if HAS_VOLTAGE_MONITOR
inline constexpr float AdcReadingToPowerVoltage(uint16_t adcVal)
@@ -1683,7 +1687,7 @@ void Platform::SoftwareReset(uint16_t reason, const uint32_t *stk)
//*****************************************************************************************************************
// Interrupts
-#if HAS_LWIP_NETWORKING
+#if HAS_LWIP_NETWORKING && !LWIP_GMAC_TASK
void NETWORK_TC_HANDLER()
{
@@ -1731,16 +1735,17 @@ void Platform::InitialiseInterrupts()
StepTimer::Init(); // initialise the step pulse timer
#if HAS_LWIP_NETWORKING
+# if !LWIP_GMAC_TASK
pmc_enable_periph_clk(NETWORK_TC_ID);
-# if SAME70
+# if SAME70
// Timer interrupt to keep the networking timers running (called at 18Hz, which is almost as low as we can get because the timer is 16-bit)
tc_init(NETWORK_TC, NETWORK_TC_CHAN, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4);
const uint32_t rc = (SystemPeripheralClock()/128)/18; // 128 because we selected TIMER_CLOCK4 above (16-bit counter)
-# else
+# else
// Timer interrupt to keep the networking timers running (called at 16Hz)
tc_init(NETWORK_TC, NETWORK_TC_CHAN, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK2);
const uint32_t rc = (VARIANT_MCK/8)/16; // 8 because we selected TIMER_CLOCK2 above (32-bit counter)
-# endif
+# endif
tc_write_ra(NETWORK_TC, NETWORK_TC_CHAN, rc/2); // 50% high, 50% low
tc_write_rc(NETWORK_TC, NETWORK_TC_CHAN, rc);
tc_start(NETWORK_TC, NETWORK_TC_CHAN);
@@ -1748,6 +1753,7 @@ void Platform::InitialiseInterrupts()
NETWORK_TC->TC_CHANNEL[NETWORK_TC_CHAN].TC_IDR = ~TC_IER_CPCS;
NVIC_SetPriority(NETWORK_TC_IRQN, NvicPriorityNetworkTick);
NVIC_EnableIRQ(NETWORK_TC_IRQN);
+# endif
// Set up the Ethernet interface priority here to because we have access to the priority definitions
# if SAME70
diff --git a/src/RepRap.cpp b/src/RepRap.cpp
index 9ab227ac..c2f0037c 100644
--- a/src/RepRap.cpp
+++ b/src/RepRap.cpp
@@ -1266,8 +1266,8 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source)
response->catf(",\"endstops\":%" PRIu32, endstops);
// Firmware name, machine geometry and number of axes
- response->catf(",\"firmwareName\":\"%s\",\"geometry\":\"%s\",\"axes\":%u,\"totalAxes\":%u,\"axisNames\":\"%s\"",
- FIRMWARE_NAME, move->GetGeometryString(), numVisibleAxes, numTotalAxes, gCodes->GetAxisLetters());
+ response->catf(",\"firmwareName\":\"%s\",\"firmwareVersion\":\"%s\",\"geometry\":\"%s\",\"axes\":%u,\"totalAxes\":%u,\"axisNames\":\"%s\"",
+ FIRMWARE_NAME, VERSION, move->GetGeometryString(), numVisibleAxes, numTotalAxes, gCodes->GetAxisLetters());
#if HAS_MASS_STORAGE
// Total and mounted volumes
diff --git a/src/RepRapFirmware.h b/src/RepRapFirmware.h
index 842e0626..1c9c6adf 100644
--- a/src/RepRapFirmware.h
+++ b/src/RepRapFirmware.h
@@ -41,6 +41,12 @@ Licence: GPL
# define SAME51 (defined(__SAME51N19A__) && __SAME51N19A__)
#endif
+#if SAME70
+# define __nocache __attribute__((section(".ram_nocache")))
+#else
+# define __nocache // nothing
+#endif
+
// Definitions needed by Pins.h and/or Configuration.h
// Logical pins used for general output, servos, CCN and laser control
typedef uint8_t LogicalPin; // type used to represent logical pin numbers
@@ -275,15 +281,6 @@ void ListDrivers(const StringRef& str, DriversBitmap drivers);
// Functions to change the base priority, to shut out interrupts up to a priority level
-// From section 3.12.7 of http://infocenter.arm.com/help/topic/com.arm.doc.dui0553b/DUI0553.pdf:
-// When you write to BASEPRI_MAX, the instruction writes to BASEPRI only if either:
-// - Rn is non-zero and the current BASEPRI value is 0
-// - Rn is non-zero and less than the current BASEPRI value
-__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value)
-{
- __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory");
-}
-
// Get the base priority and shut out interrupts lower than or equal to a specified priority
inline uint32_t ChangeBasePriority(uint32_t prio)
{
@@ -384,22 +381,6 @@ constexpr float RadiansToDegrees = 180.0/3.141592653589793;
typedef uint32_t FilePosition;
const FilePosition noFilePosition = 0xFFFFFFFF;
-// Task priorities
-namespace TaskPriority
-{
- static constexpr int SpinPriority = 1; // priority for tasks that rarely block
- static constexpr int HeatPriority = 2;
- static constexpr int DhtPriority = 2;
- static constexpr int TmcPriority = 2;
- static constexpr int AinPriority = 2;
- static constexpr int HeightFollowingPriority = 2;
- static constexpr int DueXPriority = 3;
- static constexpr int LaserPriority = 3;
- static constexpr int CanSenderPriority = 3;
- static constexpr int CanReceiverPriority = 3;
- static constexpr int CanClockPriority = 3;
-}
-
//-------------------------------------------------------------------------------------------------
// Interrupt priorities - must be chosen with care! 0 is the highest priority, 15 is the lowest.
// This interacts with FreeRTOS config constant configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY which is currently defined as 3 for the SAME70 and 5 for the SAM4x.
diff --git a/src/TaskPriorities.h b/src/TaskPriorities.h
new file mode 100644
index 00000000..e0ad3df4
--- /dev/null
+++ b/src/TaskPriorities.h
@@ -0,0 +1,29 @@
+/*
+ * TaskPriorities.h
+ *
+ * Created on: 23 Oct 2019
+ * Author: David
+ */
+
+#ifndef SRC_TASKPRIORITIES_H_
+#define SRC_TASKPRIORITIES_H_
+
+// Task priorities
+namespace TaskPriority
+{
+ static constexpr int IdlePriority = 0;
+ static constexpr int SpinPriority = 1; // priority for tasks that rarely block
+ static constexpr int HeatPriority = 2;
+ static constexpr int DhtPriority = 2;
+ static constexpr int TmcPriority = 2;
+ static constexpr int AinPriority = 2;
+ static constexpr int HeightFollowingPriority = 2;
+ static constexpr int DueXPriority = 3;
+ static constexpr int LaserPriority = 3;
+ static constexpr int CanSenderPriority = 3;
+ static constexpr int CanReceiverPriority = 3;
+ static constexpr int CanClockPriority = 3;
+ static constexpr int EthernetPriority = 3;
+}
+
+#endif /* SRC_TASKPRIORITIES_H_ */
diff --git a/src/Tasks.cpp b/src/Tasks.cpp
index e41c520d..1c3b22ac 100644
--- a/src/Tasks.cpp
+++ b/src/Tasks.cpp
@@ -14,11 +14,16 @@
#include "FreeRTOS.h"
#include "task.h"
+#include <TaskPriorities.h>
#if USE_CACHE
# include "cmcc/cmcc.h"
#endif
+#if SAME70
+# include <mpu_armv7.h>
+#endif
+
const uint8_t memPattern = 0xA5;
extern "C" char *sbrk(int i);
@@ -88,16 +93,8 @@ extern "C" void __malloc_unlock (struct _reent *_r)
}
// Application entry point
-extern "C" void AppMain()
+extern "C" [[noreturn]] void AppMain()
{
- // Fill the free memory with a pattern so that we can check for stack usage and memory corruption
- char* heapend = sbrk(0);
- register const char * stack_ptr asm ("sp");
- while (heapend + 16 < stack_ptr)
- {
- *heapend++ = memPattern;
- }
-
pinMode(DiagPin, OUTPUT_LOW); // set up diag LED for debugging and turn it off
// Check the integrity of the firmware by checking the firmware CRC
@@ -123,10 +120,79 @@ extern "C" void AppMain()
}
}
+ // Fill the free memory with a pattern so that we can check for stack usage and memory corruption
+ char* heapend = sbrk(0);
+ register const char * stack_ptr asm ("sp");
+ while (heapend + 16 < stack_ptr)
+ {
+ *heapend++ = memPattern;
+ }
+
// Trap integer divide-by-zero.
// We could also trap unaligned memory access, if we change the gcc options to not generate code that uses unaligned memory access.
SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;
+#if 0 //SAME70
+ // Set up the MPU so that we can have a non-cacheable RAM region, and so that we can trap accesses to non-existent memory
+ // Where regions overlap, the region with the highest region number takes priority
+ constexpr ARM_MPU_Region_t regionTable[] =
+ {
+ // Flash memory: read-only, execute allowed, cacheable
+ {
+ ARM_MPU_RBAR(0, IFLASH_ADDR),
+ ARM_MPU_RASR_EX(0u, ARM_MPU_AP_RO, ARM_MPU_ACCESS_NORMAL(ARM_MPU_CACHEP_WB_WRA, ARM_MPU_CACHEP_WB_WRA, 1u), 0u, ARM_MPU_REGION_SIZE_1MB)
+ },
+ // First 256kb RAM, read-write, cacheable, execute disabled. Parts of this are is overridden later.
+ {
+ ARM_MPU_RBAR(1, IRAM_ADDR),
+ ARM_MPU_RASR_EX(1u, ARM_MPU_AP_FULL, ARM_MPU_ACCESS_NORMAL(ARM_MPU_CACHEP_WB_WRA, ARM_MPU_CACHEP_WB_WRA, 1u), 0u, ARM_MPU_REGION_SIZE_256KB)
+ },
+ // Final 128kb RAM, read-write, cacheable, execute disabled
+ {
+ ARM_MPU_RBAR(3, IRAM_ADDR + 0x00040000),
+ ARM_MPU_RASR_EX(1u, ARM_MPU_AP_FULL, ARM_MPU_ACCESS_NORMAL(ARM_MPU_CACHEP_WB_WRA, ARM_MPU_CACHEP_WB_WRA, 1u), 0u, ARM_MPU_REGION_SIZE_128KB)
+ },
+ // Non-cachable RAM. This must be before normal RAM because it includes CAN buffers which must be within first 64kb.
+ // Read write, execute disabled, non-cacheable
+ {
+ ARM_MPU_RBAR(4, IRAM_ADDR),
+ ARM_MPU_RASR_EX(1u, ARM_MPU_AP_FULL, ARM_MPU_ACCESS_ORDERED, 0, ARM_MPU_REGION_SIZE_64KB)
+ },
+ // RAMFUNC memory. Read-only (the code has already been written to it), execution allowed. The initialised data memory follows, so it must be RW.
+ // 256 bytes is enough at present (check the linker memory map if adding more RAMFUNCs).
+ {
+ ARM_MPU_RBAR(5, IRAM_ADDR + 0x00010000),
+ ARM_MPU_RASR_EX(0u, ARM_MPU_AP_FULL, ARM_MPU_ACCESS_NORMAL(ARM_MPU_CACHEP_WB_WRA, ARM_MPU_CACHEP_WB_WRA, 1u), 0u, ARM_MPU_REGION_SIZE_256B)
+ },
+ // Peripherals
+ {
+ ARM_MPU_RBAR(6, 0x40000000),
+ ARM_MPU_RASR_EX(1u, ARM_MPU_AP_FULL, ARM_MPU_ACCESS_DEVICE(1u), 0u, ARM_MPU_REGION_SIZE_512MB),
+ },
+ // USBHS
+ {
+ ARM_MPU_RBAR(7, 0xA0100000),
+ ARM_MPU_RASR_EX(1u, ARM_MPU_AP_FULL, ARM_MPU_ACCESS_DEVICE(1u), 0u, ARM_MPU_REGION_SIZE_1MB),
+ }
+ };
+
+ // Ensure MPU is disabled
+ ARM_MPU_Disable();
+
+ // Clear all regions
+ const uint32_t numRegions = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
+ for (unsigned int region = 0; region < numRegions; ++region)
+ {
+ ARM_MPU_ClrRegion(region);
+ }
+
+ // Load regions from our table
+ ARM_MPU_Load(regionTable, ARRAY_SIZE(regionTable));
+
+ // Enable the MPU, disabling the default map but allowing exception handlers to use it
+ ARM_MPU_Enable(0x01);
+#endif
+
#ifdef __LPC17xx__
// Setup LEDs, start off
pinMode(LED_PLAY, OUTPUT_LOW);
@@ -163,6 +229,7 @@ extern "C" void AppMain()
// Create the startup task
mainTask.Create(MainTask, "MAIN", nullptr, TaskPriority::SpinPriority);
vTaskStartScheduler(); // doesn't return
+ for (;;) { } // kep gcc happy
}
extern "C" [[noreturn]] void MainTask(void *pvParameters)
diff --git a/src/Version.h b/src/Version.h
index 8a80bc39..3c2ecab8 100644
--- a/src/Version.h
+++ b/src/Version.h
@@ -10,7 +10,7 @@
#ifndef VERSION
-# define MAIN_VERSION "3.0beta11"
+# define MAIN_VERSION "3.0beta11+1"
# ifdef USE_CAN0
# define VERSION_SUFFIX " (CAN0)"
# else
@@ -20,7 +20,7 @@
#endif
#ifndef DATE
-# define DATE "2019-10-22b1"
+# define DATE "2019-10-26b1"
#endif
#define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman, printm3d"