mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-14 03:50:02 +03:00
Merge pull request #6837 from jflyper/bfdev-poc-dma-channel-spec
Introduce per peripheral dma channel spec option
This commit is contained in:
commit
be797d1027
82 changed files with 1051 additions and 188 deletions
|
@ -62,6 +62,7 @@ extern uint8_t __config_end;
|
|||
#include "drivers/adc.h"
|
||||
#include "drivers/buf_writer.h"
|
||||
#include "drivers/bus_spi.h"
|
||||
#include "drivers/dma_reqmap.h"
|
||||
#include "drivers/camera_control.h"
|
||||
#include "drivers/compass/compass.h"
|
||||
#include "drivers/display.h"
|
||||
|
@ -135,6 +136,8 @@ extern uint8_t __config_end;
|
|||
#include "pg/rx.h"
|
||||
#include "pg/rx_spi.h"
|
||||
#include "pg/rx_pwm.h"
|
||||
#include "pg/serial_uart.h"
|
||||
#include "pg/sdio.h"
|
||||
#include "pg/timerio.h"
|
||||
#include "pg/usb.h"
|
||||
|
||||
|
@ -4193,7 +4196,225 @@ static void cliDma(char* cmdLine)
|
|||
UNUSED(cmdLine);
|
||||
printDma();
|
||||
}
|
||||
#endif /* USE_RESOURCE_MGMT */
|
||||
|
||||
#ifdef USE_DMA_SPEC
|
||||
|
||||
typedef struct dmaoptEntry_s {
|
||||
char *device;
|
||||
dmaPeripheral_e peripheral;
|
||||
pgn_t pgn;
|
||||
uint8_t stride;
|
||||
uint8_t offset;
|
||||
uint8_t maxIndex;
|
||||
} dmaoptEntry_t;
|
||||
|
||||
// Handy macros for keeping the table tidy.
|
||||
// DEFS : Single entry
|
||||
// DEFA : Array of uint8_t (stride = 1)
|
||||
// DEFW : Wider stride case; array of structs.
|
||||
|
||||
#define DEFS(device, peripheral, pgn, type, member) \
|
||||
{ device, peripheral, pgn, 0, offsetof(type, member), 0 }
|
||||
|
||||
#define DEFA(device, peripheral, pgn, type, member, max) \
|
||||
{ device, peripheral, pgn, sizeof(uint8_t), offsetof(type, member), max }
|
||||
|
||||
#define DEFW(device, peripheral, pgn, type, member, max) \
|
||||
{ device, peripheral, pgn, sizeof(type), offsetof(type, member), max }
|
||||
|
||||
dmaoptEntry_t dmaoptEntryTable[] = {
|
||||
DEFW("SPI_TX", DMA_PERIPH_SPI_TX, PG_SPI_PIN_CONFIG, spiPinConfig_t, txDmaopt, SPIDEV_COUNT),
|
||||
DEFW("SPI_RX", DMA_PERIPH_SPI_RX, PG_SPI_PIN_CONFIG, spiPinConfig_t, rxDmaopt, SPIDEV_COUNT),
|
||||
DEFA("ADC", DMA_PERIPH_ADC, PG_ADC_CONFIG, adcConfig_t, dmaopt, ADCDEV_COUNT),
|
||||
DEFS("SDIO", DMA_PERIPH_SDIO, PG_SDIO_CONFIG, sdioConfig_t, dmaopt),
|
||||
DEFA("UART_TX", DMA_PERIPH_UART_TX, PG_SERIAL_UART_CONFIG, serialUartConfig_t, txDmaopt, UARTDEV_CONFIG_MAX),
|
||||
DEFA("UART_RX", DMA_PERIPH_UART_RX, PG_SERIAL_UART_CONFIG, serialUartConfig_t, rxDmaopt, UARTDEV_CONFIG_MAX),
|
||||
};
|
||||
|
||||
#undef DEFS
|
||||
#undef DEFA
|
||||
#undef DEFW
|
||||
|
||||
#define DMA_OPT_UI_INDEX(i) ((i) + 1)
|
||||
#define DMA_OPT_STRING_BUFSIZE 5
|
||||
|
||||
static void dmaoptToString(int optval, char *buf)
|
||||
{
|
||||
if (optval == -1) {
|
||||
memcpy(buf, "NONE", DMA_OPT_STRING_BUFSIZE);
|
||||
} else {
|
||||
tfp_sprintf(buf, "%d", optval);
|
||||
}
|
||||
}
|
||||
|
||||
static void printPeripheralDmaopt(dmaoptEntry_t *entry, int index, uint8_t dumpMask)
|
||||
{
|
||||
const pgRegistry_t* pg = pgFind(entry->pgn);
|
||||
const void *currentConfig;
|
||||
const void *defaultConfig;
|
||||
|
||||
if (configIsInCopy) {
|
||||
currentConfig = pg->copy;
|
||||
defaultConfig = pg->address;
|
||||
} else {
|
||||
currentConfig = pg->address;
|
||||
defaultConfig = NULL;
|
||||
}
|
||||
|
||||
dmaoptValue_t currentOpt = *(dmaoptValue_t *)((uint8_t *)currentConfig + entry->stride * index + entry->offset);
|
||||
dmaoptValue_t defaultOpt;
|
||||
|
||||
if (defaultConfig) {
|
||||
defaultOpt = *(dmaoptValue_t *)((uint8_t *)defaultConfig + entry->stride * index + entry->offset);
|
||||
} else {
|
||||
defaultOpt = DMA_OPT_UNUSED;
|
||||
}
|
||||
|
||||
bool equalsDefault = currentOpt == defaultOpt;
|
||||
|
||||
if (defaultConfig) {
|
||||
if (defaultOpt != DMA_OPT_UNUSED) {
|
||||
const dmaChannelSpec_t *dmaChannelSpec = dmaGetChannelSpec(entry->peripheral, index, defaultOpt);
|
||||
dmaCode_t dmaCode = 0;
|
||||
if (dmaChannelSpec) {
|
||||
dmaCode = dmaChannelSpec->code;
|
||||
}
|
||||
cliDefaultPrintLinef(dumpMask, equalsDefault,
|
||||
"dmaopt %s %d %d # DMA%d Stream %d Channel %d",
|
||||
entry->device, DMA_OPT_UI_INDEX(index), defaultOpt, DMA_CODE_CONTROLLER(dmaCode), DMA_CODE_STREAM(dmaCode), DMA_CODE_CHANNEL(dmaCode));
|
||||
} else {
|
||||
cliDefaultPrintLinef(dumpMask, equalsDefault,
|
||||
"dmaopt %s %d NONE",
|
||||
entry->device, DMA_OPT_UI_INDEX(index));
|
||||
}
|
||||
}
|
||||
|
||||
if (currentOpt != DMA_OPT_UNUSED) {
|
||||
const dmaChannelSpec_t *dmaChannelSpec = dmaGetChannelSpec(entry->peripheral, index, currentOpt);
|
||||
dmaCode_t dmaCode = 0;
|
||||
if (dmaChannelSpec) {
|
||||
dmaCode = dmaChannelSpec->code;
|
||||
}
|
||||
cliDumpPrintLinef(dumpMask, equalsDefault,
|
||||
"dmaopt %s %d %d # DMA%d Stream %d Channel %d",
|
||||
entry->device, DMA_OPT_UI_INDEX(index), currentOpt, DMA_CODE_CONTROLLER(dmaCode), DMA_CODE_STREAM(dmaCode), DMA_CODE_CHANNEL(dmaCode));
|
||||
} else {
|
||||
if (!(dumpMask & HIDE_UNUSED)) {
|
||||
cliDumpPrintLinef(dumpMask, equalsDefault,
|
||||
"dmaopt %s %d NONE",
|
||||
entry->device, DMA_OPT_UI_INDEX(index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void printDmaopt(uint8_t dumpMask)
|
||||
{
|
||||
UNUSED(dumpMask); // XXX For now
|
||||
|
||||
for (size_t i = 0; i < ARRAYLEN(dmaoptEntryTable); i++) {
|
||||
dmaoptEntry_t *entry = &dmaoptEntryTable[i];
|
||||
for (int index = 0; index < entry->maxIndex; index++) {
|
||||
printPeripheralDmaopt(entry, index, dumpMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cliDmaopt(char *cmdline)
|
||||
{
|
||||
char *pch = NULL;
|
||||
char *saveptr;
|
||||
|
||||
// Peripheral name or command option
|
||||
pch = strtok_r(cmdline, " ", &saveptr);
|
||||
|
||||
if (!pch) {
|
||||
printDmaopt(DUMP_MASTER | HIDE_UNUSED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp(pch, "all") == 0) {
|
||||
printDmaopt(DUMP_MASTER);
|
||||
return;
|
||||
}
|
||||
|
||||
dmaoptEntry_t *entry = NULL;
|
||||
for (unsigned i = 0; i < ARRAYLEN(dmaoptEntryTable); i++) {
|
||||
if (strcasecmp(pch, dmaoptEntryTable[i].device) == 0) {
|
||||
entry = &dmaoptEntryTable[i];
|
||||
}
|
||||
}
|
||||
if (!entry) {
|
||||
cliPrintLinef("bad device %s", pch);
|
||||
return;
|
||||
}
|
||||
|
||||
// Index
|
||||
pch = strtok_r(NULL, " ", &saveptr);
|
||||
int index = atoi(pch) - 1;
|
||||
if (index < 0 || index >= entry->maxIndex) {
|
||||
cliPrintLinef("bad index %s", pch);
|
||||
return;
|
||||
}
|
||||
|
||||
const pgRegistry_t* pg = pgFind(entry->pgn);
|
||||
const void *currentConfig;
|
||||
if (configIsInCopy) {
|
||||
currentConfig = pg->copy;
|
||||
} else {
|
||||
currentConfig = pg->address;
|
||||
}
|
||||
dmaoptValue_t *optaddr = (dmaoptValue_t *)((uint8_t *)currentConfig + entry->stride * index + entry->offset);
|
||||
|
||||
// opt or list
|
||||
pch = strtok_r(NULL, " ", &saveptr);
|
||||
|
||||
if (!pch) {
|
||||
if (*optaddr == -1) {
|
||||
cliPrintLinef("%s %d NONE", entry->device, index + 1);
|
||||
} else {
|
||||
cliPrintLinef("%s %d %d", entry->device, index + 1, *optaddr);
|
||||
}
|
||||
return;
|
||||
} else if (strcasecmp(pch, "list") == 0) {
|
||||
// Show possible opts
|
||||
const dmaChannelSpec_t *dmaChannelSpec;
|
||||
for (int opt = 0; (dmaChannelSpec = dmaGetChannelSpec(entry->peripheral, index, opt)); opt++) {
|
||||
cliPrintLinef("# %d: DMA%d Stream %d channel %d", opt, DMA_CODE_CONTROLLER(dmaChannelSpec->code), DMA_CODE_STREAM(dmaChannelSpec->code), dmaChannelSpec->channel);
|
||||
}
|
||||
return;
|
||||
} else if (pch) {
|
||||
int optval;
|
||||
|
||||
if (strcasecmp(pch, "none") == 0) {
|
||||
optval = -1;
|
||||
} else {
|
||||
optval = atoi(pch);
|
||||
if (optval < 0) { // XXX Check against opt max? How?
|
||||
cliPrintLinef("bad optnum %s", pch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dmaoptValue_t orgval = *optaddr;
|
||||
|
||||
char optvalString[5];
|
||||
char orgvalString[5];
|
||||
dmaoptToString(optval, optvalString);
|
||||
dmaoptToString(orgval, orgvalString);
|
||||
|
||||
if (optval != orgval) {
|
||||
*optaddr = optval;
|
||||
|
||||
cliPrintLinef("dmaopt %s %d: changed from %s to %s", entry->device, DMA_OPT_UI_INDEX(index), orgvalString, optvalString);
|
||||
} else {
|
||||
cliPrintLinef("dmaopt %s %d: no change", entry->device, DMA_OPT_UI_INDEX(index), orgvalString);
|
||||
}
|
||||
} else {
|
||||
cliPrintLinef("bad option %s", pch);
|
||||
}
|
||||
}
|
||||
#endif // USE_DMA_SPEC
|
||||
#endif // USE_RESOURCE_MGMT
|
||||
|
||||
#ifdef USE_TIMER_MGMT
|
||||
|
||||
|
@ -4358,6 +4579,10 @@ static void printConfig(char *cmdline, bool doDiff)
|
|||
#ifdef USE_RESOURCE_MGMT
|
||||
cliPrintHashLine("resources");
|
||||
printResource(dumpMask);
|
||||
#ifdef USE_DMA_SPEC
|
||||
cliPrintHashLine("dmaopt");
|
||||
printDmaopt(dumpMask);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef USE_QUAD_MIXER_ONLY
|
||||
|
@ -4515,6 +4740,7 @@ static void cliMsc(char *cmdline)
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
#ifndef MINIMAL_CLI
|
||||
|
@ -4568,6 +4794,9 @@ const clicmd_t cmdTable[] = {
|
|||
CLI_COMMAND_DEF("diff", "list configuration changes from default", "[master|profile|rates|all] {defaults}", cliDiff),
|
||||
#ifdef USE_RESOURCE_MGMT
|
||||
CLI_COMMAND_DEF("dma", "list dma utilisation", NULL, cliDma),
|
||||
#ifdef USE_DMA_SPEC
|
||||
CLI_COMMAND_DEF("dmaopt", "assign dma spec to a device", "<device> <index> <optnum>", cliDmaopt),
|
||||
#endif
|
||||
#endif
|
||||
#ifdef USE_DSHOT
|
||||
CLI_COMMAND_DEF("dshotprog", "program DShot ESC(s)", "<index> <command>+", cliDshotProg),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue