Vicolaships
Пт 20 апреля 2018 г., 16:50
Привет, я пытаюсь настроить раба SPI с полнодууплексными передачами DMA на синей таблетке.
Я хочу иметь возможность получать 2 байта (2x 8 бит), не управляя каждым байтом, я хочу, чтобы DMA сделал это для меня и вызвало прерывание, когда два байта переданы. Мне также нужно, чтобы передача была полной дуплексной, раб должен ответить на мастер (в этом примере должен получить мастер: 123 и 87).
С кодом ниже ничего не происходит, когда я передаю 2 байта, прерывание не стреляет. Мастер получает ответ, где все биты нули. Я уверен, что кабели правильно подключены, потому что простой раб SPI как ViewTopic.PHP?F = 18&T = 3525 Работа.
Я хочу иметь возможность получать 2 байта (2x 8 бит), не управляя каждым байтом, я хочу, чтобы DMA сделал это для меня и вызвало прерывание, когда два байта переданы. Мне также нужно, чтобы передача была полной дуплексной, раб должен ответить на мастер (в этом примере должен получить мастер: 123 и 87).
С кодом ниже ничего не происходит, когда я передаю 2 байта, прерывание не стреляет. Мастер получает ответ, где все биты нули. Я уверен, что кабели правильно подключены, потому что простой раб SPI как ViewTopic.PHP?F = 18&T = 3525 Работа.
#include
#include
#include
#define DATA_BUFFER_SIZE 2
// Tx / Rx buffer
volatile uint8_t data_buffer[DATA_BUFFER_SIZE];
// If true a transfer is complete: data_bufer contains new and valid data
volatile bool dma_transfer_complete(false);
// DMA interrupt handler
void rxDMAirq(void)
{
if (dma_get_irq_cause(DMA1, DMA_CH2) == DMA_TRANSFER_COMPLETE)
dma_transfer_complete = true;
}
void setupDMA(void)
{
dma_init(DMA1);
// DMA tube configuration for SPI1 Rx - channel 2
dma_tube_config tube_cfg =
{
&SPI1->regs->DR, // Source of data
DMA_SIZE_8BITS, // Source transfer size
&data_buffer, // Destination of data
DMA_SIZE_8BITS, // Destination transfer size
DATA_BUFFER_SIZE, // Number of data to transfer
// Flags: auto increment destination address, circular buffer, set tube full IRQ, very high priority
(DMA_CFG_DST_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE), // FIXME Do I need DMA_CCR_PL_VERY_HIGH?
0, // Un-used
DMA_REQ_SRC_SPI1_RX, // Hardware DMA request source
};
// Configure DMA channel
// SPI1 Rx channel is nr. 2
const int ret(dma_tube_cfg(DMA1, DMA_CH2, &tube_cfg));
if (ret != DMA_TUBE_CFG_SUCCESS)
{
while (1)
{
Serial.print("DMA configuration error: ");
Serial.println(ret, HEX);
Serial.println("Reset is needed!");
delay(100);
}
}
dma_attach_interrupt(DMA1, DMA_CH2, rxDMAirq);
dma_enable(DMA1, DMA_CH2);
}
void setupSPI(void)
{
// MOSI, MISO, SCK PINs are set by the library
pinMode(BOARD_SPI_DEFAULT_SS, INPUT); // SS
// The clock value is not used
// SPI1 is selected by default
SPI.beginTransactionSlave(SPISettings(18000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT));
}
void setup()
{
Serial.begin(115200);
delay(100);
// Data that will be sent
data_buffer[0] = 123;
data_buffer[1] = 87;
setupSPI();
setupDMA();
}
unsigned count_1(0);
unsigned count_2(0);
void loop()
{
if (dma_transfer_complete)
{
dma_transfer_complete = false;
Serial.println("DMA transfer complete");
Serial.print("data_buffer[0] = ");
Serial.println((unsigned)data_buffer[0]);
Serial.print("data_buffer[1] = ");
Serial.println((unsigned)data_buffer[1]);
// Data that will be sent (for next transfer)
// Assumes that a transfer has not yet been initiated
data_buffer[0] = 123;
data_buffer[1] = 87;
}
delayMicroseconds(10);
if (++count_1 > 50000)
{
count_1 = 0;
Serial.print("Waiting... ");
Serial.println(++count_2);
}
}
Vicolaships
Вт 24 апреля 2018 г., 19:40
Я хочу вернуться к своему базовому примеру: ViewTopic.PHP?P = 13036#P13036
Я только изменил длину буфера (records_per_buffer = 2, records_per_block = 8) и размер данных передачи SPI от 16 битов до 8 бит, передача никогда не завершается, у вас есть идея, почему? Мастер отправил 8 раз 8 -битный кадр SPI.
Я только изменил длину буфера (records_per_buffer = 2, records_per_block = 8) и размер данных передачи SPI от 16 битов до 8 бит, передача никогда не завершается, у вас есть идея, почему? Мастер отправил 8 раз 8 -битный кадр SPI.
/*
Storage of multiple 8bit data received over SPI1 to SD card over SPI2.
*/
#include
#include
// SD card chip select pin
#define CHIP_SELECT PB12
#define TOTAL_BLOCKS 10 // number of blocks to record
// size of data block which will be written in one shot to card
#define BLOCK_SIZE 512 // bytes
// size of data buffer where the ADC sampled data will be transferred over DMA
#define DATA_BUFFER_SIZE (2*BLOCK_SIZE) // bytes
#define RECORD_SIZE 2 // 8 bits
#define RECORDS_PER_BLOCK 8 // uint8_t
#define RECORDS_PER_BUFFER 2 // uint8_t
// the data buffer to store values
uint8_t data_buffer[RECORDS_PER_BUFFER];
uint32_t total_blocks;
uint32_t total_records;
uint8_t * pCache;
// set by HW when a complete DMA transfer was finished.
volatile uint8_t dma_irq_full_complete;
// set by HW when a DMA transfer is at its half.
volatile uint8_t dma_irq_half_complete;
// set by SW when overrun occurs
volatile uint8_t overrun;
// signalling for lower and upper buffer status
volatile uint8_t buff0_stored, buff1_stored, buff_index;
void setupParameters(void)
{
// init some relevant values
total_blocks = TOTAL_BLOCKS;
// the SW can only record an even number of blocks, so we need to adjust it
if ( (total_blocks&1) ) total_blocks++;
total_records = (total_blocks*RECORDS_PER_BLOCK);
}
void DMA_Init(void)
{
dma_irq_full_complete = 0;
dma_irq_half_complete = 0;
overrun = 0;
buff0_stored = buff1_stored = 1; // avoid overrun detection
buff_index = 0;
dma_clear_isr_bits(DMA1, DMA_CH2);
// for test only: fill ADC buffer with dummy data
for (int i = 0; iregs->DR, // data source address
DMA_SIZE_8BITS, // source transfer size
&data_buffer, // data destination address
DMA_SIZE_8BITS, // destination transfer size
RECORDS_PER_BUFFER, // nr. of data to transfer
// tube flags: auto increment dest addr, circular buffer, set tube full IRQ, very high prio:
( DMA_CFG_DST_INC | DMA_CFG_CIRC | DMA_CFG_HALF_CMPLT_IE | DMA_CFG_CMPLT_IE | DMA_CCR_PL_VERY_HIGH ),
0, // unused
DMA_REQ_SRC_SPI1_RX, // Hardware DMA request source
};
// configure DMA channel
int ret = dma_tube_cfg(DMA1, DMA_CH2, &my_tube_cfg); // SPI1 Rx channel is nr. 2
if (ret > 0)
{
Serial1.print("DMA configuration error: ");
Serial1.println(ret,HEX);
Serial1.println("Stopped, reset is needed!");
while (1);
}
dma_attach_interrupt(DMA1, DMA_CH2, DMA_Rx_irq); // attach an interrupt handler.
dma_enable(DMA1, DMA_CH2); // Enable the DMA tube. It will now begin serving requests.
}
/*****************************************************************************/
SPIClass SPI_2(2);
uint32_t app_cr1;
/*****************************************************************************/
void SPI_setup(void)
{
// use SPI 1 for recording, SPI 2 is used by SD card
SPI.setModule(1);
SPI.beginTransactionSlave(SPISettings(18000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT));
SPI.setModule(2); // FIXME Remove?
}
void setup()
{
Serial.begin(115200);
Serial.println("8bit data received over SPI1 in slave mode is stored to SD-card over SPI2.");
delay (10);
}
void setupModules()
{
// Set-up involved hardware modules
SPI_setup();
DMA_Setup();
}
void loop()
{
setupParameters();
setupModules();
Serial1.print("Total_blocks = ");
Serial1.println(total_blocks);
uint32_t t_out; // time-out
uint32_t bl, val = 0;
for( bl = 0; bl < total_blocks; ++bl)
{
// time-out to avoid hangup if something goes wrong
t_out = 1000000;
// each ADC sequence is sampled triggered by TIMER3 event.
while ( (--t_out)>0 ) {
// check DMA recording status and push data to card if either half buffer is full
if ( dma_irq_half_complete ) {
dma_irq_half_complete = 0;
buff0_stored = 1;
break;
}
if ( dma_irq_full_complete ) {
dma_irq_full_complete = 0;
buff1_stored = 1;
break;
}
//if ( spi_is_rx_nonempty(SPI1) ) { spi_rx_reg(SPI1); val++; }
}
// only for debug purposes:
if ( t_out==0 ) {
Serial1.println(F("\n!!!! TIME_OUT !!!"));
break;
}
}
}
victor_pv
Вт 24 апреля 2018 г., 21:29
Я не мог видеть в коде, что вы включите просьбы о периферийном DMA SPI.
Помимо настройки контроллера DMA, вам необходимо настроить периферийную систему SPI для генерации запросов DMA.
Если вы проверите библиотеку SPI, имя функции для этого есть, я забыл имя.
Помимо настройки контроллера DMA, вам необходимо настроить периферийную систему SPI для генерации запросов DMA.
Если вы проверите библиотеку SPI, имя функции для этого есть, я забыл имя.
Vicolaships
Ср 25 апреля 2018 г., 16:50
[victor_pv - Вт 24 апреля 2018 г., 21:29] - Я не мог видеть в коде, что вы включите просьбы о периферийном DMA SPI.
dma_init(DMA1);
// DMA tube configuration for SPI1 Rx - channel 2
dma_tube_config tube_cfg =
{
&SPI1->regs->DR, // Source of data
DMA_SIZE_8BITS, // Source transfer size
&data_buffer, // Destination of data
DMA_SIZE_8BITS, // Destination transfer size
DATA_BUFFER_SIZE, // Number of data to transfer
// Flags: auto increment destination address, circular buffer, set tube full IRQ, very high priority
(DMA_CFG_DST_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE), // FIXME Do I need DMA_CCR_PL_VERY_HIGH?
0, // Un-used
DMA_REQ_SRC_SPI1_RX, // Hardware DMA request source
};
// Configure DMA channel
// SPI1 Rx channel is nr. 2
const int ret(dma_tube_cfg(DMA1, DMA_CH2, &tube_cfg));
if (ret != DMA_TUBE_CFG_SUCCESS)
{
while (1)
{
Serial.print("DMA configuration error: ");
Serial.println(ret, HEX);
Serial.println("Reset is needed!");
delay(100);
}
}
victor_pv
Чт 26 апреля 2018 11:14
Периферийное устройство DMA будет выполнять передачу только тогда, когда периферийная передача SPI запрашивает передачу DMA, поэтому, помимо установки контроллера DMA, в SPI CR есть флаг, чтобы включить запросы SPI с периферийного устройства SPI. Как только этот флаг будет установлен, периферийное устройство SPI запрашивает новую передачу контроллеру DMA каждый раз, когда устанавливаются флаги RXNE или TXE.
Стивестронг
Пт 27 апреля 2018 г. 8:26 утра
Чтобы настроить доступ DMA, вам лучше взглянуть на эти строки: https: // github.com/rogerclarkmelbourne/ ... #L396-L421.
Конечно, часть RX должна работать в рабов.
Конечно, часть RX должна работать в рабов.
Vicolaships
Пт 27 апреля 2018 г. 13:00
Спасибо за любезную помощь, я получил это работает благодаря вашим двум сообщениям! Были очевидно, что я не понимал, теперь я думаю, что знаю достаточно
Вот самый простой пример, который я мог бы приступить к работе:
Вот самый простой пример, который я мог бы приступить к работе:
#include
#include
#include
#define DATA_BUFFER_SIZE 2
// Rx and Tx buffers
volatile uint8_t rx_buffer[DATA_BUFFER_SIZE];
volatile uint8_t tx_buffer[DATA_BUFFER_SIZE];
// If true a transfer is complete: rx_bufer contains new and valid data
// tx_buffer has been completely sent
volatile bool dma_transfer_complete(false);
// DMA interrupt handler
void rxDMAirq(void)
{
if (dma_get_irq_cause(DMA1, DMA_CH2) == DMA_TRANSFER_COMPLETE)
dma_transfer_complete = true;
}
void setupDMA(void)
{
// SPI is on DMA1
dma_init (DMA1);
// DMA tube configuration for SPI1 Rx
dma_tube_config rx_tube_cfg =
{
&SPI1->regs->DR, // Source of data
DMA_SIZE_8BITS, // Source transfer size
&rx_buffer, // Destination of data
DMA_SIZE_8BITS, // Destination transfer size
DATA_BUFFER_SIZE, // Number of data to transfer
// Flags: auto increment destination address, circular buffer, set tube full IRQ, very high priority
(DMA_CFG_DST_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE | DMA_CCR_PL_VERY_HIGH),
0, // Un-used
DMA_REQ_SRC_SPI1_RX, // Hardware DMA request source
};
// SPI1 Rx is channel 2
const int ret_rx(dma_tube_cfg(DMA1, DMA_CH2, &rx_tube_cfg));
if (ret_rx != DMA_TUBE_CFG_SUCCESS)
{
while (1)
{
Serial.print("Rx DMA configuration error: ");
Serial.println(ret_rx, HEX);
Serial.println("Reset is needed!");
delay(100);
}
}
// DMA tube configuration for SPI1 Tx
dma_tube_config tx_tube_cfg =
{
&tx_buffer, // Source of data
DMA_SIZE_8BITS, // Source transfer size
&SPI1->regs->DR, // Destination of data
DMA_SIZE_8BITS, // Destination transfer size
DATA_BUFFER_SIZE, // Number of data to transfer
// Flags: auto increment source address, circular buffer, set tube full IRQ, low priority
(DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE | DMA_CCR_PL_LOW),
0, // Un-used
DMA_REQ_SRC_SPI1_TX, // Hardware DMA request source
};
// SPI1 Tx is channel 3
const int ret_tx(dma_tube_cfg(DMA1, DMA_CH3, &tx_tube_cfg));
if (ret_tx != DMA_TUBE_CFG_SUCCESS)
{
while (1)
{
Serial.print("Tx DMA configuration error: ");
Serial.println(ret_tx, HEX);
Serial.println("Reset is needed!");
delay(100);
}
}
// Clear RX register in case we already received SPI data
spi_rx_reg(SPI.dev());
// SPI DMA requests for Rx and Tx
spi_rx_dma_enable(SPI.dev());
spi_tx_dma_enable(SPI.dev());
// Attach interrupt to catch end of DMA transfer
dma_attach_interrupt(DMA1, DMA_CH2, rxDMAirq);
// Enable DMA configurations
dma_enable(DMA1, DMA_CH2); // Rx
dma_enable(DMA1, DMA_CH3); // Tx
}
void setupSPI(void)
{
// MOSI, MISO, SCK PINs are set by the library
pinMode(BOARD_SPI_DEFAULT_SS, INPUT); // SS
// The clock value is not used
// SPI1 is selected by default
SPI.beginTransactionSlave(SPISettings(0, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT));
}
void setup()
{
Serial.begin(115200);
delay(100);
// Data that will be sent
tx_buffer[0] = 20;
tx_buffer[1] = 18;
setupSPI();
setupDMA();
}
unsigned count_1(0);
unsigned count_2(0);
void loop()
{
if (dma_transfer_complete)
{
dma_transfer_complete = false;
Serial.println("DMA transfer complete");
Serial.print("data_buffer[0] = ");
Serial.println((unsigned)rx_buffer[0]);
Serial.print("data_buffer[1] = ");
Serial.println((unsigned)rx_buffer[1]);
// Data that will be sent (for next transfer)
// Assumes that a transfer has not yet been initiated
tx_buffer[0] = 20;
tx_buffer[1] = 18;
}
delayMicroseconds(10);
if (++count_1 > 50000)
{
count_1 = 0;
Serial.print("Waiting... ");
Serial.println(++count_2);
}
}
Rogerclark
Пт 27 апреля 2018 г., 21:35
Спасибо..
Если несколько человек могут проверить это, подумайте, что это должно быть включено в примеры...
Если несколько человек могут проверить это, подумайте, что это должно быть включено в примеры...
victor_pv
SAT 28 апреля 2018 г. 12:55 утра
Отличная работа.
Я думаю, было бы хорошо, если бы функция Dmatransfer, уже в ядре, может быть проверена и сделана совместимой с режимом подчинения, если это не так, это еще больше упростит использование.
Я думаю, было бы хорошо, если бы функция Dmatransfer, уже в ядре, может быть проверена и сделана совместимой с режимом подчинения, если это не так, это еще больше упростит использование.
AG123
SAT 28 апреля 2018 г., 3:53 утра
+5 Это довольно хорошо, спасибо! Теперь STM32duino Blue Pills / Maple Mini может удвоиться как ADC и больше для других досок, таких как R-Pi
Стивестронг
Сб 28 апреля 2018 г. 10:37
У меня есть только одно замечание, не проверяя его: эти строки
// enable SPI DMA requests for Rx and Tx
spi_rx_dma_enable(SPI.dev());
spi_tx_dma_enable(SPI.dev());
Vicolaships
Солнце 29 апреля 2018 г., 7:49
[Стивестронг - Сб 28 апреля 2018 г. 10:37] -
У меня есть только одно замечание, не проверяя его: эти строки
// enable SPI DMA requests for Rx and Tx
spi_rx_dma_enable(SPI.dev());
spi_tx_dma_enable(SPI.dev());
Стивестронг
Пн 30 апреля 2018 г., 18:23
Если вы используете два разных буфера, вы должны изменить адрес буфера.
Я предлагаю не устанавливать DMA в круглом режиме.
Обычно я использую один круглый буфер, размер вдвое больше одного буфера.
В этом случае нет необходимости менять адрес буфера.
Я проверяю основной цикл полного полного и передаю полные флаги DMA и выполняю процесс завершенной половины: когда DMA передает половину, основной уровень обрабатывает дополнительную половину буфера.
Я предлагаю не устанавливать DMA в круглом режиме.
Обычно я использую один круглый буфер, размер вдвое больше одного буфера.
В этом случае нет необходимости менять адрес буфера.
Я проверяю основной цикл полного полного и передаю полные флаги DMA и выполняю процесс завершенной половины: когда DMA передает половину, основной уровень обрабатывает дополнительную половину буфера.
Vicolaships
Сб 30 июня 2018 г., 13:52
[Стивестронг - Пн 30 апреля 2018 г. 18:23] - Если вы используете два разных буфера, вы должны изменить адрес буфера.Для этого вы должны использовать двойной буферный режим DMA, он использует 2 Adreses и Memords Adress and Mogs. Пользователи каждый раз, когда передача завершается (см AN4031 Страница 13, режим двойного буфера).
Я предлагаю не устанавливать DMA в круглом режиме.
Обычно я использую один круглый буфер, размер вдвое больше одного буфера.
В этом случае нет необходимости менять адрес буфера.
Я проверяю основной цикл полного полного и передаю полные флаги DMA и выполняю процесс завершенной половины: когда DMA передает половину, основной уровень обрабатывает дополнительную половину буфера.
Сейчас я сталкиваюсь с новой проблемой. Иногда по неизвестной причине (я думаю, электрический импеданс и тому подобное) моя периферия получает еще одно слово, которое должно. Я могу обнаружить его, потому что я вычисляю суммы Флехтера с обеих сторон (мастер/раб), поэтому я знаю сообщение, если плохо сформировано.
Но как я могу исправить это автоматически? Одним из решений было бы доступ к индексу буфера DMA, и если он не изменяется в течение определенного периода времени (дольше одной полной передачи), сбросьте DMA.
Ты знаешь, как я мог это сделать?
Вот псевдо -код того, что я хотел бы сделать:
uint32_t last(0);
uint32_t dma_check_time(0);
bool dma_check(false);
unsigned dma_check_buffer_id(0);
void loop()
{
// Count time (usec) elapsed since last time
uint32_t right_now(micros());
uint32_t elapsed(right_now - last);
if (last == 0)
elapsed = 0;
last = right_now;
// In case DMA buffer index is not zero: reset DMA buffer index if the DMA buffer index
// do not change after 150 microseconds
//
// This is useful when the peripheral received one word more than expected for whatever reason and
// all messages gets shifted because of that.
if (dma_check)
{
if (right_now - dma_check_time > 150)
{
dma_check = false;
if (dma_check_buffer_id == dma_index)
{
// Reset DMA index
}
}
}
else if (dma_index != 0)
{
dma_check_buffer_id = dma_index;
dma_check_time = right_now;
dma_check = true;
}
}
Стивестронг
SAT 30 июня 2018 г. 16:46
Что касается примечания к заявлению, на которую вы указали, это для F2, F4 и F7, как вы, вероятно, заметили.
Здесь мы говорим о синей таблетке (F1), верно? F1 и F3 не имеют этой функции.
Не зная вашего кода, трудно оценить, что может быть неправильно.
Кстати, я опубликовал здесь несколько рабочих магистра/рабов примеров: http: // stm32duino.com/viewtopic.PHP?f = 9 ... 878#P45041
РЕДАКТИРОВАТЬ
Можно проверить, сколько переводов имеет DMA еще для завершения:
Здесь мы говорим о синей таблетке (F1), верно? F1 и F3 не имеют этой функции.
Не зная вашего кода, трудно оценить, что может быть неправильно.
Кстати, я опубликовал здесь несколько рабочих магистра/рабов примеров: http: // stm32duino.com/viewtopic.PHP?f = 9 ... 878#P45041
РЕДАКТИРОВАТЬ
Можно проверить, сколько переводов имеет DMA еще для завершения:
dma_get_count(,);
Vicolaships
Пн, 2 июля 2018 г. 8:19
[Стивестронг - Сб 30 июня 2018 г., 16:46] - Что касается примечания к заявлению, на которую вы указали, это для F2, F4 и F7, как вы, вероятно, заметили.
Здесь мы говорим о синей таблетке (F1), верно? F1 и F3 не имеют этой функции.
Не зная вашего кода, трудно оценить, что может быть неправильно.
Кстати, я опубликовал здесь несколько рабочих магистра/рабов примеров: http: // stm32duino.com/viewtopic.PHP?f = 9 ... 878#P45041
РЕДАКТИРОВАТЬ
Можно проверить, сколько переводов имеет DMA еще для завершения:dma_get_count(
, );
Стивестронг
Пн, 02 июля 2018 г. 8:28 утра
UPS, извините, кажется, что это только в моем репо: https: // github.com/stevstrong/arduino_s ... #L541-L543
Вы можете импортировать эту часть в своих файлах.
Я только что сделал пиар: https: // github.com/rogerclarkmelbourne/ ... 2/Pull/534
Вы можете импортировать эту часть в своих файлах.
Я только что сделал пиар: https: // github.com/rogerclarkmelbourne/ ... 2/Pull/534
Стивестронг
Вт. 3 июля 2018 г. 9:31
PR был совершен, поэтому вы можете использовать эту функцию.
Vicolaships
SAT 07 июля 2018 г., 17:31
Большое спасибо, я получил его работу благодаря этому дополнению
Я до сих пор не знаю, почему это происходит, но, по крайней мере, я могу обнаружить его и сбросить SPI / DMA, тогда все снова работает нормально.
Функции setupdma и setupspi:
Я до сих пор не знаю, почему это происходит, но, по крайней мере, я могу обнаружить его и сбросить SPI / DMA, тогда все снова работает нормально.
Функции setupdma и setupspi:
void setupDMA(void)
{
// SPI is on DMA1
dma_init(DMA1);
// Disable in case already enabled
spi_tx_dma_disable(SPI.dev());
spi_rx_dma_disable(SPI.dev());
// Disable in case it was already enabled
dma_disable(DMA1, DMA_CH2);
dma_disable(DMA1, DMA_CH3);
dma_detach_interrupt(DMA1, DMA_CH2);
// DMA tube configuration for SPI1 Rx
dma_tube_config rx_tube_cfg =
{
&SPI1->regs->DR, // Source of data
DMA_SIZE_8BITS, // Source transfer size
&rx_buffer, // Destination of data
DMA_SIZE_8BITS, // Destination transfer size
BUFFER_SIZE, // Number of data to transfer
// Flags: auto increment destination address, circular buffer, set tube full IRQ, very high priority
(DMA_CFG_DST_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE | DMA_CCR_PL_VERY_HIGH),
0, // Un-used
DMA_REQ_SRC_SPI1_RX, // Hardware DMA request source
};
// SPI1 Rx is channel 2
const int ret_rx(dma_tube_cfg(DMA1, DMA_CH2, &rx_tube_cfg));
if (ret_rx != DMA_TUBE_CFG_SUCCESS)
{
while (1)
{
#ifdef SERIAL_DEBUG
Serial.print("Rx DMA configuration error: ");
Serial.println(ret_rx, HEX);
Serial.println("Reset is needed!");
#endif
delay(500);
}
}
// DMA tube configuration for SPI1 Tx
dma_tube_config tx_tube_cfg =
{
&tx_buffer, // Source of data
DMA_SIZE_8BITS, // Source transfer size
&SPI1->regs->DR, // Destination of data
DMA_SIZE_8BITS, // Destination transfer size
BUFFER_SIZE, // Number of data to transfer
// Flags: auto increment source address, circular buffer, set tube full IRQ, very high priority
(DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE | DMA_CCR_PL_VERY_HIGH),
0, // Un-used
DMA_REQ_SRC_SPI1_TX, // Hardware DMA request source
};
// SPI1 Tx is channel 3
const int ret_tx(dma_tube_cfg(DMA1, DMA_CH3, &tx_tube_cfg));
if (ret_tx != DMA_TUBE_CFG_SUCCESS)
{
while (1)
{
#ifdef SERIAL_DEBUG
Serial.print("Tx DMA configuration error: ");
Serial.println(ret_tx, HEX);
Serial.println("Reset is needed!");
#endif
delay(500);
}
}
// Attach interrupt to catch end of DMA transfer
dma_attach_interrupt(DMA1, DMA_CH2, rxDMAirq);
// Enable DMA configurations
dma_enable(DMA1, DMA_CH2); // Rx
dma_enable(DMA1, DMA_CH3); // Tx
// SPI DMA requests for Rx and Tx
spi_rx_dma_enable(SPI.dev());
spi_tx_dma_enable(SPI.dev());
#ifdef SERIAL_DEBUG
Serial.print("setupDMA | Rx count = ");
Serial.print((unsigned) dma_get_count(DMA1, DMA_CH2));
Serial.print(" | Tx DMA count = ");
Serial.println((unsigned) dma_get_count(DMA1, DMA_CH3));
#endif
}
void setupSPI(void)
{
// MOSI, MISO, SCK PINs are set by the library
pinMode(BOARD_SPI_DEFAULT_SS, INPUT); // SS
// The clock value is not used
// SPI1 is selected by default
SPI.beginTransactionSlave(SPISettings(0, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT));
// Clear RX register in case we already received SPI data
spi_rx_reg(SPI.dev());
}
Rogerclark
Вторник 04 декабря 2018 г., 19:23
Спасибо, что опубликовали это.
Я пытаюсь изменить работу радио-радио UHF (BAOFENG UV-82) для получения цифровых сигналов, и мне нужно перехватить команды SPI, отправляемые в чип, через SPI.
Этот код выглядит действительно полезным для этого проекта.
На самом деле я, наверное, выиграл’T Используйте версию DMA, так как мне нужно слушать каждую отдельную команду, и немедленно отвечать .
Но функциональность SPI подчинка - действительно полезная функция.
Я пытаюсь изменить работу радио-радио UHF (BAOFENG UV-82) для получения цифровых сигналов, и мне нужно перехватить команды SPI, отправляемые в чип, через SPI.
Этот код выглядит действительно полезным для этого проекта.
На самом деле я, наверное, выиграл’T Используйте версию DMA, так как мне нужно слушать каждую отдельную команду, и немедленно отвечать .
Но функциональность SPI подчинка - действительно полезная функция.