Skip to content

Commit

Permalink
DMA/cache interaction fixes
Browse files Browse the repository at this point in the history
Ported DMA/cache interaction fixes from v3-dev branch
Removed SAME70XPLD build configuration
Fixed DWC disconnects due to JSON parse errors when a bad GCode file was parsed as having infinite object height
Fixed minimum radius calculation for SCARA kinematics
Lock movement before adding or deleting tools
Bug fix for resurrection when the print was sliced in absolute extrusion mode
When configuring a filament monitor on a DuetNG CONN_LCD endstop pin, enable the pullup resistor
Pulsed filament monitors no longer display current position, and not longer include calibration data in the M122 report
  • Loading branch information
dc42 committed Nov 27, 2019
1 parent e80367b commit bcb169f
Show file tree
Hide file tree
Showing 16 changed files with 336 additions and 254 deletions.
174 changes: 1 addition & 173 deletions .cproject

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion src/FilamentMonitors/FilamentMonitor.cpp
Expand Up @@ -58,7 +58,13 @@ bool FilamentMonitor::ConfigurePin(GCodeBuffer& gb, const StringRef& reply, Inte
reply.copy("unsuitable endstop number");
return true;
}
setPullup(pin, false); // disable the pullup resistor to provide greater noise immunity when using a Duet3D laser of magnetic filament monitor

// Disable the pullup resistor except on Duet WiFi/Ethernet CONN_LCD endstop inputs, to provide greater noise immunity when using a Duet3D laser of magnetic filament monitor
#ifdef DUET_NG
setPullup(pin, endstop >= 10);
#else
setPullup(pin, false);
#endif
}
else if (seen)
{
Expand Down
22 changes: 1 addition & 21 deletions src/FilamentMonitors/PulsedFilamentMonitor.cpp
Expand Up @@ -95,7 +95,6 @@ bool PulsedFilamentMonitor::Configure(GCodeBuffer& gb, const StringRef& reply, b
}
else
{
reply.catf("current position %.1f, ", (double)GetCurrentPosition());
if (calibrationStarted && fabsf(totalMovementMeasured) > 1.0 && totalExtrusionCommanded > 20.0)
{
const float measuredMmPerPulse = totalExtrusionCommanded/totalMovementMeasured;
Expand Down Expand Up @@ -160,12 +159,6 @@ void PulsedFilamentMonitor::Poll()
}
}

// Return the current wheel angle
float PulsedFilamentMonitor::GetCurrentPosition() const
{
return (float)sensorValue;
}

// Call the following at intervals to check the status. This is only called when extrusion is in progress or imminent.
// 'filamentConsumed' is the net amount of extrusion since the last call to this function.
// 'isPrinting' is true unless a non-printing extruder move was in progress
Expand Down Expand Up @@ -281,20 +274,7 @@ void PulsedFilamentMonitor::Diagnostics(MessageType mtype, unsigned int extruder
{
Poll();
const char* const statusText = (samplesReceived < 2) ? "no data received" : "ok";
reprap.GetPlatform().MessageF(mtype, "Extruder %u sensor: position %.2f, %s, ", extruder, (double)GetCurrentPosition(), statusText);
if (calibrationStarted && fabsf(totalMovementMeasured) > 1.0 && totalExtrusionCommanded > 20.0)
{
const float measuredMmPerRev = totalExtrusionCommanded/totalMovementMeasured;
const float normalRatio = 1.0/measuredMmPerRev;
const int measuredPosTolerance = lrintf(100.0 * (((normalRatio > 0.0) ? maxMovementRatio : minMovementRatio) - normalRatio)/normalRatio);
const int measuredNegTolerance = lrintf(100.0 * (normalRatio - ((normalRatio > 0.0) ? minMovementRatio : maxMovementRatio))/normalRatio);
reprap.GetPlatform().MessageF(mtype,"measured sensitivity %.3fmm/pulse +%d%% -%d%%\n",
(double)measuredMmPerRev, measuredPosTolerance, measuredNegTolerance);
}
else
{
reprap.GetPlatform().Message(mtype, "no calibration data\n");
}
reprap.GetPlatform().MessageF(mtype, "Extruder %u sensor: %s\n", extruder, statusText);
}

// End
1 change: 0 additions & 1 deletion src/FilamentMonitors/PulsedFilamentMonitor.h
Expand Up @@ -30,7 +30,6 @@ class PulsedFilamentMonitor : public FilamentMonitor
void Init();
void Reset();
void Poll();
float GetCurrentPosition() const;
FilamentSensorStatus CheckFilament(float amountCommanded, float amountMeasured, bool overdue);

// Configuration parameters
Expand Down
33 changes: 22 additions & 11 deletions src/GCodes/GCodes.cpp
Expand Up @@ -3660,17 +3660,6 @@ bool GCodes::QueueFileToPrint(const char* fileName, const StringRef& reply)
FileStore * const f = platform.OpenFile(platform.GetGCodeDir(), fileName, OpenMode::read);
if (f != nullptr)
{
fileGCode->SetToolNumberAdjust(0); // clear tool number adjustment
fileGCode->MachineState().volumetricExtrusion = false; // default to non-volumetric extrusion

// Reset all extruder positions when starting a new print
virtualExtruderPosition = 0.0;
for (size_t extruder = 0; extruder < MaxExtruders; extruder++)
{
rawExtruderTotalByDrive[extruder] = 0.0;
}
rawExtruderTotal = 0.0;
reprap.GetMove().ResetExtruderPositions();

fileToPrint.Set(f);
fileOffsetToPrint = 0;
Expand All @@ -3685,8 +3674,25 @@ bool GCodes::QueueFileToPrint(const char* fileName, const StringRef& reply)
// Start printing the file already selected
void GCodes::StartPrinting(bool fromStart)
{
if (fromStart)
{
fileGCode->MachineState().volumetricExtrusion = false; // default to non-volumetric extrusion
virtualExtruderPosition = 0.0;
}

fileGCode->SetToolNumberAdjust(0); // clear tool number adjustment

// Reset all extruder positions when starting a new print
for (size_t extruder = 0; extruder < MaxExtruders; extruder++)
{
rawExtruderTotalByDrive[extruder] = 0.0;
}
rawExtruderTotal = 0.0;
reprap.GetMove().ResetExtruderPositions();

fileGCode->OriginalMachineState().fileState.MoveFrom(fileToPrint);
fileInput->Reset(fileGCode->OriginalMachineState().fileState);

lastFilamentError = FilamentSensorStatus::ok;
lastPrintingMoveHeight = -1.0;
reprap.GetPrintMonitor().StartedPrint();
Expand Down Expand Up @@ -3973,6 +3979,11 @@ GCodeResult GCodes::ManageTool(GCodeBuffer& gb, const StringRef& reply)

if (seen)
{
if (!LockMovementAndWaitForStandstill(gb))
{
return GCodeResult::notFinished;
}

// Add or delete tool, so start by deleting the old one with this number, if any
reprap.DeleteTool(reprap.GetTool(toolNumber));

Expand Down
216 changes: 216 additions & 0 deletions src/Hardware/Cache.cpp
@@ -0,0 +1,216 @@
/*
* Cache.cpp
*
* Created on: 22 Nov 2019
* Author: David
*/

#include <Hardware/Cache.h>

#if USE_CACHE

#if SAME70
# include <core_cm7.h>

extern uint32_t _nocache_ram_start;
extern uint32_t _nocache_ram_end;

# if USE_MPU
# include <mpu_armv7.h>

// Macro ARM_MPU_RASR_EX is incorrectly defined in CMSIS 5.4.0, see https://github.com/ARM-software/CMSIS_5/releases. Redefine it here.

# undef ARM_MPU_RASR_EX

/**
* MPU Region Attribute and Size Register Value
*
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_.
* \param SubRegionDisable Sub-region disable field.
* \param Size Region size of the region to be configured, for example 4K, 8K.
*/
# define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \
((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \
(((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \
(((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \
(((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \
(((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \
(((MPU_RASR_ENABLE_Msk))))

# endif

#endif

#if SAM4E
# include <cmcc/cmcc.h>
#endif

static bool enabled = false;

void Cache::Init()
{
#if SAME70

# if USE_MPU
// 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 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(2, 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(3, 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(4, 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(5, 0x40000000),
ARM_MPU_RASR_EX(1u, ARM_MPU_AP_FULL, ARM_MPU_ACCESS_DEVICE(1u), 0u, ARM_MPU_REGION_SIZE_16MB)
},
// USBHS
{
ARM_MPU_RBAR(6, 0xA0100000),
ARM_MPU_RASR_EX(1u, ARM_MPU_AP_FULL, ARM_MPU_ACCESS_DEVICE(1u), 0u, ARM_MPU_REGION_SIZE_1MB)
},
// ROM
{
ARM_MPU_RBAR(7, IROM_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_4MB)
},
// ARM Private Peripheral Bus
{
ARM_MPU_RBAR(8, 0xE0000000),
ARM_MPU_RASR_EX(1u, ARM_MPU_AP_FULL, ARM_MPU_ACCESS_ORDERED, 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

#elif SAM4E
cmcc_config g_cmcc_cfg;
cmcc_get_config_defaults(&g_cmcc_cfg);
cmcc_init(CMCC, &g_cmcc_cfg);
#endif
}

void Cache::Enable()
{
if (!enabled)
{
enabled = true;
#if SAME70
SCB_EnableICache();
SCB_EnableDCache();

#elif SAM4E
cmcc_invalidate_all(CMCC);
cmcc_enable(CMCC);
#endif
}
}

void Cache::Disable()
{
if (enabled)
{
#if SAME70
SCB_DisableICache();
SCB_DisableDCache();
#elif SAM4E
cmcc_disable(CMCC);
#endif
enabled = false;
}
}

#if SAME70

void Cache::Flush(const volatile void *start, size_t length)
{
if (enabled)
{
// We assume that the DMA buffer is entirely inside or entirely outside the non-cached RAM area
if (start < (void*)&_nocache_ram_start || start >= (void*)&_nocache_ram_end)
{
const uint32_t startAddr = reinterpret_cast<uint32_t>(start);
SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t*>(startAddr & ~3), length + (startAddr & 3));
}
}
}

#endif

void Cache::Invalidate(const volatile void *start, size_t length)
{
if (enabled)
{
#if SAME70
// We assume that the DMA buffer is entirely inside or entirely outside the non-cached RAM area
if (start < (void*)&_nocache_ram_start || start >= (void*)&_nocache_ram_end)
{
// Caution! if any part of the cache line is dirty, the written data will be lost!
const uint32_t startAddr = reinterpret_cast<uint32_t>(start);
SCB_InvalidateDCache_by_Addr(reinterpret_cast<uint32_t*>(startAddr & ~3), length + (startAddr & 3));
}
#elif SAM4E
// The cache is only 2kb on the SAM4E so we just invalidate the whole cache
cmcc_invalidate_all(CMCC);
#endif
}
}

#if SAM4E

uint32_t Cache::GetHitCount()
{
return cmcc_get_monitor_cnt(CMCC);
}

#endif

#endif

// Entry points that can be called from ASF C code
void CacheFlushBeforeDMAReceive(const volatile void *start, size_t length) { Cache::FlushBeforeDMAReceive(start, length); }
void CacheInvalidateAfterDMAReceive(const volatile void *start, size_t length) { Cache::InvalidateAfterDMAReceive(start, length); }
void CacheFlushBeforeDMASend(const volatile void *start, size_t length) { Cache::FlushBeforeDMASend(start, length); }

// End
54 changes: 54 additions & 0 deletions src/Hardware/Cache.h
@@ -0,0 +1,54 @@
/*
* Cache.h
*
* Created on: 22 Nov 2019
* Author: David
*/

#ifndef SRC_HARDWARE_CACHE_H_
#define SRC_HARDWARE_CACHE_H_

#include <RepRapFirmware.h>

namespace Cache
{
void Init();
void Enable();
void Disable();
void Flush(const volatile void *start, size_t length);
void Invalidate(const volatile void *start, size_t length);

inline void FlushBeforeDMAReceive(const volatile void *start, size_t length) { Flush(start, length); }
inline void InvalidateAfterDMAReceive(const volatile void *start, size_t length) { Invalidate(start, length); }
inline void FlushBeforeDMASend(const volatile void *start, size_t length) { Flush(start, length); }

#if SAM4E
uint32_t GetHitCount();
#endif
};

// Entry points that can be called from ASF C code
extern "C" void CacheFlushBeforeDMAReceive(const volatile void *start, size_t length);
extern "C" void CacheInvalidateAfterDMAReceive(const volatile void *start, size_t length);
extern "C" void CacheFlushBeforeDMASend(const volatile void *start, size_t length);

#if USE_CACHE

# if SAM4E

// The SAM4E cache is write-through, so no need to flush it
inline void Cache::Flush(const volatile void *start, size_t length) { }

# endif

#else

inline void Cache::Init() {}
inline void Cache::Enable() {}
inline void Cache::Disable() {}
inline void Cache::Flush(const volatile void *start, size_t length) {}
inline void Cache::Invalidate(const volatile void *start, size_t length) {}

#endif

#endif /* SRC_HARDWARE_CACHE_H_ */

0 comments on commit bcb169f

Please sign in to comment.