diff options
author | David Crocker <dcrocker@eschertech.com> | 2019-10-26 11:46:31 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2019-10-26 11:46:31 +0300 |
commit | 587f49d5699a6a0fc3cb8307e17dd5c2fa43f73b (patch) | |
tree | 311cc1342502b74cad2808ee6bf4e9cb66a7ac4c /src | |
parent | c25d73194252791ceb479ced79ffc77b31c810fe (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)
Diffstat (limited to 'src')
25 files changed, 496 insertions, 228 deletions
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(ðernet_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" |