[hal] Add support for DMA to Java (#3158)

This commit is contained in:
Thad House
2021-06-14 19:56:42 -07:00
committed by GitHub
parent 85144e47ff
commit 4a36f86c81
39 changed files with 2013 additions and 97 deletions

View File

@@ -11,6 +11,7 @@
#include <type_traits>
#include "AnalogInternal.h"
#include "ConstantsInternal.h"
#include "DigitalInternal.h"
#include "EncoderInternal.h"
#include "HALInternal.h"
@@ -103,19 +104,25 @@ HAL_DMAHandle HAL_InitializeDMA(int32_t* status) {
return HAL_kInvalidHandle;
}
dma->aDMA->writeConfig_ExternalClock(false, status);
if (*status != 0) {
dmaHandles->Free(handle);
return HAL_kInvalidHandle;
std::memset(&dma->captureStore, 0, sizeof(dma->captureStore));
tDMA::tConfig config;
std::memset(&config, 0, sizeof(config));
config.Pause = true;
dma->aDMA->writeConfig(config, status);
dma->aDMA->writeRate(1, status);
tDMA::tExternalTriggers newTrigger;
std::memset(&newTrigger, 0, sizeof(newTrigger));
for (unsigned char reg = 0; reg < tDMA::kNumExternalTriggersRegisters;
reg++) {
for (unsigned char bit = 0; bit < tDMA::kNumExternalTriggersElements;
bit++) {
dma->aDMA->writeExternalTriggers(reg, bit, newTrigger, status);
}
}
HAL_SetDMARate(handle, 1, status);
if (*status != 0) {
dmaHandles->Free(handle);
return HAL_kInvalidHandle;
}
HAL_SetDMAPause(handle, false, status);
return handle;
}
@@ -139,20 +146,44 @@ void HAL_SetDMAPause(HAL_DMAHandle handle, HAL_Bool pause, int32_t* status) {
return;
}
if (!dma->manager) {
*status = HAL_INVALID_DMA_STATE;
return;
}
dma->aDMA->writeConfig_Pause(pause, status);
}
void HAL_SetDMARate(HAL_DMAHandle handle, int32_t cycles, int32_t* status) {
void HAL_SetDMATimedTrigger(HAL_DMAHandle handle, double seconds,
int32_t* status) {
constexpr double baseMultipler = kSystemClockTicksPerMicrosecond * 1000000;
uint32_t cycles = static_cast<uint32_t>(baseMultipler * seconds);
HAL_SetDMATimedTriggerCycles(handle, cycles, status);
}
void HAL_SetDMATimedTriggerCycles(HAL_DMAHandle handle, uint32_t cycles,
int32_t* status) {
auto dma = dmaHandles->Get(handle);
if (!dma) {
*status = HAL_HANDLE_ERROR;
return;
}
if (dma->manager) {
*status = HAL_INVALID_DMA_ADDITION;
return;
}
if (cycles < 1) {
cycles = 1;
}
dma->aDMA->writeRate(static_cast<uint32_t>(cycles), status);
dma->aDMA->writeConfig_ExternalClock(false, status);
if (*status != 0) {
return;
}
dma->aDMA->writeRate(cycles, status);
}
void HAL_AddDMAEncoder(HAL_DMAHandle handle, HAL_EncoderHandle encoderHandle,
@@ -477,20 +508,20 @@ void HAL_AddDMAAnalogAccumulator(HAL_DMAHandle handle,
}
}
void HAL_SetDMAExternalTrigger(HAL_DMAHandle handle,
HAL_Handle digitalSourceHandle,
HAL_AnalogTriggerType analogTriggerType,
HAL_Bool rising, HAL_Bool falling,
int32_t* status) {
int32_t HAL_SetDMAExternalTrigger(HAL_DMAHandle handle,
HAL_Handle digitalSourceHandle,
HAL_AnalogTriggerType analogTriggerType,
HAL_Bool rising, HAL_Bool falling,
int32_t* status) {
auto dma = dmaHandles->Get(handle);
if (!dma) {
*status = HAL_HANDLE_ERROR;
return;
return 0;
}
if (dma->manager) {
*status = HAL_INVALID_DMA_ADDITION;
return;
return 0;
}
int index = 0;
@@ -504,21 +535,21 @@ void HAL_SetDMAExternalTrigger(HAL_DMAHandle handle,
if (index == 8) {
*status = NO_AVAILABLE_RESOURCES;
return;
return 0;
}
dma->captureStore.triggerChannels |= (1 << index);
auto channelIndex = index;
auto isExternalClock = dma->aDMA->readConfig_ExternalClock(status);
if (*status == 0 && !isExternalClock) {
dma->aDMA->writeConfig_ExternalClock(true, status);
if (*status != 0) {
return;
}
} else if (*status != 0) {
return;
dma->aDMA->writeConfig_ExternalClock(true, status);
if (*status != 0) {
return 0;
}
dma->aDMA->writeRate(1, status);
if (*status != 0) {
return 0;
}
uint8_t pin = 0;
@@ -532,7 +563,7 @@ void HAL_SetDMAExternalTrigger(HAL_DMAHandle handle,
hal::SetLastError(status,
"Digital Source unabled to be mapped properly. Likely "
"invalid handle passed.");
return;
return 0;
}
tDMA::tExternalTriggers newTrigger;
@@ -544,6 +575,55 @@ void HAL_SetDMAExternalTrigger(HAL_DMAHandle handle,
dma->aDMA->writeExternalTriggers(channelIndex / 4, channelIndex % 4,
newTrigger, status);
return index;
}
void HAL_ClearDMASensors(HAL_DMAHandle handle, int32_t* status) {
auto dma = dmaHandles->Get(handle);
if (!dma) {
*status = HAL_HANDLE_ERROR;
return;
}
if (dma->manager) {
*status = HAL_INVALID_DMA_STATE;
return;
}
bool existingExternal = dma->aDMA->readConfig_ExternalClock(status);
if (*status != 0) {
return;
}
tDMA::tConfig config;
std::memset(&config, 0, sizeof(config));
config.Pause = true;
config.ExternalClock = existingExternal;
dma->aDMA->writeConfig(config, status);
}
void HAL_ClearDMAExternalTriggers(HAL_DMAHandle handle, int32_t* status) {
auto dma = dmaHandles->Get(handle);
if (!dma) {
*status = HAL_HANDLE_ERROR;
return;
}
if (dma->manager) {
*status = HAL_INVALID_DMA_STATE;
return;
}
dma->captureStore.triggerChannels = 0;
tDMA::tExternalTriggers newTrigger;
std::memset(&newTrigger, 0, sizeof(newTrigger));
for (unsigned char reg = 0; reg < tDMA::kNumExternalTriggersRegisters;
reg++) {
for (unsigned char bit = 0; bit < tDMA::kNumExternalTriggersElements;
bit++) {
dma->aDMA->writeExternalTriggers(reg, bit, newTrigger, status);
}
}
}
void HAL_StartDMA(HAL_DMAHandle handle, int32_t queueDepth, int32_t* status) {
@@ -554,7 +634,7 @@ void HAL_StartDMA(HAL_DMAHandle handle, int32_t queueDepth, int32_t* status) {
}
if (dma->manager) {
*status = INCOMPATIBLE_STATE;
*status = HAL_INVALID_DMA_STATE;
return;
}
@@ -598,12 +678,15 @@ void HAL_StartDMA(HAL_DMAHandle handle, int32_t queueDepth, int32_t* status) {
dma->captureStore.captureSize = accum_size + 1;
}
dma->manager = std::make_unique<tDMAManager>(
g_DMA_index, queueDepth * dma->captureStore.captureSize, status);
uint32_t byteDepth = queueDepth * dma->captureStore.captureSize;
dma->manager = std::make_unique<tDMAManager>(g_DMA_index, byteDepth, status);
if (*status != 0) {
return;
}
dma->aDMA->writeConfig_Pause(false, status);
dma->manager->start(status);
dma->manager->stop(status);
dma->manager->start(status);
@@ -617,6 +700,8 @@ void HAL_StopDMA(HAL_DMAHandle handle, int32_t* status) {
}
if (dma->manager) {
dma->aDMA->writeConfig_Pause(true, status);
*status = 0;
dma->manager->stop(status);
dma->manager = nullptr;
}
@@ -629,7 +714,7 @@ void* HAL_GetDMADirectPointer(HAL_DMAHandle handle) {
enum HAL_DMAReadStatus HAL_ReadDMADirect(void* dmaPointer,
HAL_DMASample* dmaSample,
int32_t timeoutMs,
double timeoutSeconds,
int32_t* remainingOut,
int32_t* status) {
DMA* dma = static_cast<DMA*>(dmaPointer);
@@ -637,12 +722,13 @@ enum HAL_DMAReadStatus HAL_ReadDMADirect(void* dmaPointer,
size_t remainingBytes = 0;
if (!dma->manager) {
*status = INCOMPATIBLE_STATE;
*status = HAL_INVALID_DMA_STATE;
return HAL_DMA_ERROR;
}
dma->manager->read(dmaSample->readBuffer, dma->captureStore.captureSize,
timeoutMs, &remainingBytes, status);
static_cast<uint32_t>(timeoutSeconds * 1000),
&remainingBytes, status);
*remainingOut = remainingBytes / dma->captureStore.captureSize;
@@ -667,15 +753,16 @@ enum HAL_DMAReadStatus HAL_ReadDMADirect(void* dmaPointer,
}
enum HAL_DMAReadStatus HAL_ReadDMA(HAL_DMAHandle handle,
HAL_DMASample* dmaSample, int32_t timeoutMs,
int32_t* remainingOut, int32_t* status) {
HAL_DMASample* dmaSample,
double timeoutSeconds, int32_t* remainingOut,
int32_t* status) {
auto dma = dmaHandles->Get(handle);
if (!dma) {
*status = HAL_HANDLE_ERROR;
return HAL_DMA_ERROR;
}
return HAL_ReadDMADirect(dma.get(), dmaSample, timeoutMs, remainingOut,
return HAL_ReadDMADirect(dma.get(), dmaSample, timeoutSeconds, remainingOut,
status);
}