1
0
Fork 0
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:
Michael Keller 2018-12-30 16:53:00 +13:00 committed by GitHub
commit be797d1027
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
82 changed files with 1051 additions and 188 deletions

View file

@ -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),