[Taranis] We cannot receive S.PORT through DMA, the associated stream is already used by the DAC

This commit is contained in:
Bertrand Songis
2016-03-19 12:01:36 +01:00
parent b8068438fb
commit f622d7cf6d
6 changed files with 74 additions and 77 deletions
+1 -1
View File
@@ -441,6 +441,7 @@ if(CPU_FAMILY STREQUAL STM32)
foreach(FILE ${STM32USB_SRC})
set(FIRMWARE_SRC ${FIRMWARE_SRC} ${STM32USB_DIR}/${FILE})
endforeach()
set(SRC ${SRC} sbus.cpp)
endif()
if(ARCH STREQUAL ARM)
@@ -510,7 +511,6 @@ if(ARCH STREQUAL ARM)
main_arm.cpp
tasks_arm.cpp
audio_arm.cpp
sbus.cpp
telemetry/telemetry.cpp
telemetry/frsky.cpp
telemetry/frsky_d_arm.cpp
+40 -46
View File
@@ -27,23 +27,20 @@ void setSampleRate(uint32_t frequency)
{
register uint32_t timer = (PERI1_FREQUENCY * TIMER_MULT_APB1) / frequency - 1 ; // MCK/8 and 100 000 Hz
TIM6->CR1 &= ~TIM_CR1_CEN ;
TIM6->CNT = 0 ;
TIM6->ARR = limit<uint32_t>(2, timer, 65535) ;
TIM6->CR1 |= TIM_CR1_CEN ;
AUDIO_TIMER->CR1 &= ~TIM_CR1_CEN ;
AUDIO_TIMER->CNT = 0 ;
AUDIO_TIMER->ARR = limit<uint32_t>(2, timer, 65535) ;
AUDIO_TIMER->CR1 |= TIM_CR1_CEN ;
}
// Start TIMER6 at 100000Hz, used for DAC trigger
void dacTimerInit()
{
// Now for timer 6
RCC->APB1ENR |= RCC_APB1ENR_TIM6EN ; // Enable clock
TIM6->PSC = 0 ; // Max speed
TIM6->ARR = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 100000 - 1 ; // 10 uS, 100 kHz
TIM6->CR2 = 0 ;
TIM6->CR2 = 0x20 ;
TIM6->CR1 = TIM_CR1_CEN ;
AUDIO_TIMER->PSC = 0 ; // Max speed
AUDIO_TIMER->ARR = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 100000 - 1 ; // 10 uS, 100 kHz
AUDIO_TIMER->CR2 = 0 ;
AUDIO_TIMER->CR2 = 0x20 ;
AUDIO_TIMER->CR1 = TIM_CR1_CEN ;
}
// Configure DAC0 (or DAC1 for REVA)
@@ -53,39 +50,36 @@ void dacInit()
{
dacTimerInit();
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN ; // Enable portA clock
configure_pins( GPIO_Pin_4, PIN_ANALOG | PIN_PORTA ) ;
RCC->APB1ENR |= RCC_APB1ENR_DACEN ; // Enable clock
RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN ; // Enable DMA1 clock
// Chan 7, 16-bit wide, Medium priority, memory increments
DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA
DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits
DMA1_Stream5->CR = DMA_SxCR_CHSEL_0 | DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_2 | DMA_SxCR_PL_0 |
AUDIO_DMA_Stream->CR &= ~DMA_SxCR_EN ; // Disable DMA
AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits
AUDIO_DMA_Stream->CR = DMA_SxCR_CHSEL_0 | DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_2 | DMA_SxCR_PL_0 |
DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_CIRC ;
DMA1_Stream5->PAR = CONVERT_PTR_UINT(&DAC->DHR12R1);
// DMA1_Stream5->M0AR = CONVERT_PTR_UINT(Sine_values);
DMA1_Stream5->FCR = 0x05 ; //DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0 ;
// DMA1_Stream5->NDTR = 100 ;
AUDIO_DMA_Stream->PAR = CONVERT_PTR_UINT(&DAC->DHR12R1);
// AUDIO_DMA_Stream->M0AR = CONVERT_PTR_UINT(Sine_values);
AUDIO_DMA_Stream->FCR = 0x05 ; //DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0 ;
// AUDIO_DMA_Stream->NDTR = 100 ;
DAC->DHR12R1 = 2010 ;
DAC->SR = DAC_SR_DMAUDR1 ; // Write 1 to clear flag
DAC->CR = DAC_CR_TEN1 | DAC_CR_EN1 ; // Enable DAC
NVIC_EnableIRQ(TIM6_DAC_IRQn); // TODO needed?
NVIC_SetPriority(TIM6_DAC_IRQn, 7);
NVIC_EnableIRQ(DMA1_Stream5_IRQn);
NVIC_SetPriority(DMA1_Stream5_IRQn, 7);
NVIC_EnableIRQ(AUDIO_TIM_IRQn); // TODO needed?
NVIC_SetPriority(AUDIO_TIM_IRQn, 7);
NVIC_EnableIRQ(AUDIO_DMA_Stream_IRQn);
NVIC_SetPriority(AUDIO_DMA_Stream_IRQn, 7);
}
bool audioPushBuffer(AudioBuffer * buffer)
{
if (dacIdle) {
dacIdle = false;
DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA channel
DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits
DMA1_Stream5->M0AR = CONVERT_PTR_UINT(buffer->data);
DMA1_Stream5->NDTR = buffer->size;
DMA1_Stream5->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE ; // Enable DMA channel and interrupt
AUDIO_DMA_Stream->CR &= ~DMA_SxCR_EN ; // Disable DMA channel
AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits
AUDIO_DMA_Stream->M0AR = CONVERT_PTR_UINT(buffer->data);
AUDIO_DMA_Stream->NDTR = buffer->size;
AUDIO_DMA_Stream->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE ; // Enable DMA channel and interrupt
DAC->SR = DAC_SR_DMAUDR1 ; // Write 1 to clear flag
DAC->CR |= DAC_CR_EN1 | DAC_CR_DMAEN1 ; // Enable DAC
return true;
@@ -97,15 +91,15 @@ bool audioPushBuffer(AudioBuffer * buffer)
void dacStart()
{
DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits
DMA1_Stream5->CR |= DMA_SxCR_CIRC | DMA_SxCR_EN ; // Enable DMA channel
AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits
AUDIO_DMA_Stream->CR |= DMA_SxCR_CIRC | DMA_SxCR_EN ; // Enable DMA channel
DAC->SR = DAC_SR_DMAUDR1 ; // Write 1 to clear flag
DAC->CR |= DAC_CR_EN1 | DAC_CR_DMAEN1 ; // Enable DAC
}
void dacStop()
{
DMA1_Stream5->CR &= ~DMA_SxCR_CIRC ;
AUDIO_DMA_Stream->CR &= ~DMA_SxCR_CIRC ;
}
@@ -118,13 +112,13 @@ void audioInit()
void audioEnd()
{
DAC->CR = 0 ;
TIM6->CR1 = 0 ;
AUDIO_TIMER->CR1 = 0 ;
// Also need to turn off any possible interrupts
NVIC_DisableIRQ(TIM6_DAC_IRQn) ;
NVIC_DisableIRQ(DMA1_Stream5_IRQn) ;
NVIC_DisableIRQ(AUDIO_TIM_IRQn) ;
NVIC_DisableIRQ(AUDIO_DMA_Stream_IRQn) ;
}
extern "C" void TIM6_DAC_IRQHandler()
extern "C" void AUDIO_TIM_IRQHandler()
{
DAC->CR &= ~DAC_CR_DMAEN1 ; // Stop DMA requests
#if !defined(REV9E)
@@ -133,18 +127,18 @@ extern "C" void TIM6_DAC_IRQHandler()
DAC->SR = DAC_SR_DMAUDR1 ; // Write 1 to clear flag
}
extern "C" void DMA1_Stream5_IRQHandler()
extern "C" void AUDIO_DMA_Stream_IRQHandler()
{
DMA1_Stream5->CR &= ~DMA_SxCR_TCIE ; // Stop interrupt
DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear flags
DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA channel
AUDIO_DMA_Stream->CR &= ~DMA_SxCR_TCIE ; // Stop interrupt
AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear flags
AUDIO_DMA_Stream->CR &= ~DMA_SxCR_EN ; // Disable DMA channel
AudioBuffer * nextBuffer = audioQueue.getNextFilledBuffer();
if (nextBuffer) {
DMA1_Stream5->M0AR = CONVERT_PTR_UINT(nextBuffer->data);
DMA1_Stream5->NDTR = nextBuffer->size;
DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits
DMA1_Stream5->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE ; // Enable DMA channel
AUDIO_DMA_Stream->M0AR = CONVERT_PTR_UINT(nextBuffer->data);
AUDIO_DMA_Stream->NDTR = nextBuffer->size;
AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits
AUDIO_DMA_Stream->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE ; // Enable DMA channel
DAC->SR = DAC_SR_DMAUDR1; // Write 1 to clear flag
}
else {
+2 -2
View File
@@ -121,8 +121,8 @@ extern "C" void INTERRUPT_5MS_IRQHandler()
void boardInit()
{
RCC_AHB1PeriphClockCmd(PWR_RCC_AHB1Periph | KEYS_RCC_AHB1Periph | LCD_RCC_AHB1Periph | BACKLIGHT_RCC_AHB1Periph | ADC_RCC_AHB1Periph | I2C_RCC_AHB1Periph | SD_RCC_AHB1Periph | HAPTIC_RCC_AHB1Periph | INTMODULE_RCC_AHB1Periph | EXTMODULE_RCC_AHB1Periph | TELEMETRY_RCC_AHB1Periph | SERIAL_RCC_AHB1Periph | TRAINER_RCC_AHB1Periph | HEARTBEAT_RCC_AHB1Periph, ENABLE);
RCC_APB1PeriphClockCmd(LCD_RCC_APB1Periph | BACKLIGHT_RCC_APB1Periph | INTERRUPT_5MS_APB1Periph | TIMER_2MHz_APB1Periph | I2C_RCC_APB1Periph | SD_RCC_APB1Periph | TRAINER_RCC_APB1Periph | TELEMETRY_RCC_APB1Periph | SERIAL_RCC_APB1Periph, ENABLE);
RCC_AHB1PeriphClockCmd(PWR_RCC_AHB1Periph | KEYS_RCC_AHB1Periph | LCD_RCC_AHB1Periph | AUDIO_RCC_AHB1Periph | BACKLIGHT_RCC_AHB1Periph | ADC_RCC_AHB1Periph | I2C_RCC_AHB1Periph | SD_RCC_AHB1Periph | HAPTIC_RCC_AHB1Periph | INTMODULE_RCC_AHB1Periph | EXTMODULE_RCC_AHB1Periph | TELEMETRY_RCC_AHB1Periph | SERIAL_RCC_AHB1Periph | TRAINER_RCC_AHB1Periph | HEARTBEAT_RCC_AHB1Periph, ENABLE);
RCC_APB1PeriphClockCmd(LCD_RCC_APB1Periph | AUDIO_RCC_APB1Periph | BACKLIGHT_RCC_APB1Periph | INTERRUPT_5MS_APB1Periph | TIMER_2MHz_APB1Periph | I2C_RCC_APB1Periph | SD_RCC_APB1Periph | TRAINER_RCC_APB1Periph | TELEMETRY_RCC_APB1Periph | SERIAL_RCC_APB1Periph, ENABLE);
RCC_APB2PeriphClockCmd(BACKLIGHT_RCC_APB2Periph | ADC_RCC_APB2Periph | HAPTIC_RCC_APB2Periph | INTMODULE_RCC_APB2Periph | EXTMODULE_RCC_APB2Periph | HEARTBEAT_RCC_APB2Periph, ENABLE);
#if !defined(REV9E)
+1 -1
View File
@@ -397,7 +397,7 @@ void checkTrainerSettings(void);
#if defined(__cplusplus)
#include "fifo.h"
#include "dmafifo.h"
extern DMAFifo<512> telemetryFifo; // TODO I don't think we really need 512bytes here!
extern Fifo<uint8_t, 32> telemetryFifo;
extern DMAFifo<32> serial2RxFifo;
extern Fifo<uint8_t, 32> sbusFifo;
#endif
+13 -2
View File
@@ -390,13 +390,13 @@
#define TELEMETRY_GPIO_PinSource_RX GPIO_PinSource6
#define TELEMETRY_GPIO_AF GPIO_AF_USART2
#define TELEMETRY_USART USART2
#define TELEMETRY_DMA_Stream_RX DMA1_Stream5
#define TELEMETRY_DMA_Channel_RX DMA_Channel_4
#define TELEMETRY_DMA_Stream_TX DMA1_Stream6
#define TELEMETRY_DMA_Channel_TX DMA_Channel_4
#define TELEMETRY_DMA_TX_Stream_IRQ DMA1_Stream6_IRQn
#define TELEMETRY_DMA_TX_IRQHandler DMA1_Stream6_IRQHandler
#define TELEMETRY_DMA_TX_FLAG_TC DMA_IT_TCIF6
#define TELEMETRY_USART_IRQHandler USART2_IRQHandler
#define TELEMETRY_USART_IRQn USART2_IRQn
// Heartbeat
#define HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOC
@@ -537,6 +537,17 @@
#define SD_DMA_Channel_SPI DMA_Channel_0
#endif
// Audio
#define AUDIO_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_DMA1)
#define AUDIO_RCC_APB1Periph (RCC_APB1Periph_TIM6 | RCC_APB1Periph_DAC)
#define AUDIO_DMA_Stream DMA1_Stream5
#define AUDIO_DMA_Stream_IRQn DMA1_Stream5_IRQn
#define AUDIO_TIM_IRQn TIM6_DAC_IRQn
#define AUDIO_TIM_IRQHandler TIM6_DAC_IRQHandler
#define AUDIO_DMA_Stream_IRQHandler DMA1_Stream5_IRQHandler
#define AUDIO_TIMER TIM6
#define AUDIO_DMA DMA1
// Haptic
#if defined(REVPLUS)
#define HAPTIC_RCC_AHB1Periph RCC_AHB1Periph_GPIOB
+17 -25
View File
@@ -20,7 +20,7 @@
#include "opentx.h"
DMAFifo<512> telemetryFifo __DMA (TELEMETRY_DMA_Stream_RX);
Fifo<uint8_t, 32> telemetryFifo;
void telemetryPortInit(uint32_t baudrate)
{
@@ -61,32 +61,11 @@ void telemetryPortInit(uint32_t baudrate)
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(TELEMETRY_USART, &USART_InitStructure);
DMA_InitTypeDef DMA_InitStructure;
telemetryFifo.clear();
USART_ITConfig(TELEMETRY_USART, USART_IT_RXNE, DISABLE);
USART_ITConfig(TELEMETRY_USART, USART_IT_TXE, DISABLE);
DMA_InitStructure.DMA_Channel = TELEMETRY_DMA_Channel_RX;
DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&TELEMETRY_USART->DR);
DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(telemetryFifo.buffer());
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = telemetryFifo.size();
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(TELEMETRY_DMA_Stream_RX, &DMA_InitStructure);
USART_DMACmd(TELEMETRY_USART, USART_DMAReq_Rx, ENABLE);
USART_Cmd(TELEMETRY_USART, ENABLE);
DMA_Cmd(TELEMETRY_DMA_Stream_RX, ENABLE);
USART_ITConfig(TELEMETRY_USART, USART_IT_RXNE, ENABLE);
NVIC_SetPriority(TELEMETRY_USART_IRQn, 6);
NVIC_EnableIRQ(TELEMETRY_USART_IRQn);
}
void telemetryPortSetDirectionOutput()
@@ -140,6 +119,19 @@ extern "C" void TELEMETRY_DMA_TX_IRQHandler(void)
}
}
#define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE)
extern "C" void TELEMETRY_USART_IRQHandler(void)
{
uint32_t status = TELEMETRY_USART->SR;
while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
uint8_t data = TELEMETRY_USART->DR;
if (!(status & USART_FLAG_ERRORS)) {
telemetryFifo.push(data);
}
status = TELEMETRY_USART->SR;
}
}
// TODO we should have telemetry in an higher layer, functions above should move to a sport_driver.cpp
int telemetryGetByte(uint8_t * byte)
{