PX4IO_serial::~PX4IO_serial() { if (_tx_dma != nullptr) { stm32_dmastop(_tx_dma); stm32_dmafree(_tx_dma); } if (_rx_dma != nullptr) { stm32_dmastop(_rx_dma); stm32_dmafree(_rx_dma); } /* reset the UART */ rCR1 = 0; rCR2 = 0; rCR3 = 0; /* detach our interrupt handler */ up_disable_irq(PX4IO_SERIAL_VECTOR); irq_detach(PX4IO_SERIAL_VECTOR); /* restore the GPIOs */ stm32_unconfiggpio(PX4IO_SERIAL_TX_GPIO); stm32_unconfiggpio(PX4IO_SERIAL_RX_GPIO); /* and kill our semaphores */ sem_destroy(&_completion_semaphore); sem_destroy(&_bus_semaphore); perf_free(_pc_txns); perf_free(_pc_dmasetup); perf_free(_pc_retries); perf_free(_pc_timeouts); perf_free(_pc_crcerrs); perf_free(_pc_dmaerrs); perf_free(_pc_protoerrs); perf_free(_pc_uerrs); perf_free(_pc_idle); perf_free(_pc_badidle); if (g_interface == this) { g_interface = nullptr; } }
PX4IO_serial_f4::PX4IO_serial_f4() : _tx_dma(nullptr), _rx_dma(nullptr), _current_packet(nullptr), _rx_dma_status(_dma_status_inactive), _completion_semaphore(SEM_INITIALIZER(0)), #if 0 _pc_dmasetup(perf_alloc(PC_ELAPSED, "io_dmasetup ")), _pc_dmaerrs(perf_alloc(PC_COUNT, "io_dmaerrs ")) #else _pc_dmasetup(nullptr), _pc_dmaerrs(nullptr) #endif { } PX4IO_serial_f4::~PX4IO_serial_f4() { if (_tx_dma != nullptr) { stm32_dmastop(_tx_dma); stm32_dmafree(_tx_dma); } if (_rx_dma != nullptr) { stm32_dmastop(_rx_dma); stm32_dmafree(_rx_dma); } /* reset the UART */ rCR1 = 0; rCR2 = 0; rCR3 = 0; /* detach our interrupt handler */ up_disable_irq(PX4IO_SERIAL_VECTOR); irq_detach(PX4IO_SERIAL_VECTOR); /* restore the GPIOs */ px4_arch_unconfiggpio(PX4IO_SERIAL_TX_GPIO); px4_arch_unconfiggpio(PX4IO_SERIAL_RX_GPIO); /* Disable APB clock for the USART peripheral */ modifyreg32(PX4IO_SERIAL_RCC_REG, PX4IO_SERIAL_RCC_EN, 0); /* and kill our semaphores */ px4_sem_destroy(&_completion_semaphore); perf_free(_pc_dmasetup); perf_free(_pc_dmaerrs); } int PX4IO_serial_f4::init() { /* initialize base implementation */ int r; if ((r = PX4IO_serial::init(&_io_buffer_storage)) != 0) { return r; } /* allocate DMA */ _tx_dma = stm32_dmachannel(PX4IO_SERIAL_TX_DMAMAP); _rx_dma = stm32_dmachannel(PX4IO_SERIAL_RX_DMAMAP); if ((_tx_dma == nullptr) || (_rx_dma == nullptr)) { return -1; } /* Enable the APB clock for the USART peripheral */ modifyreg32(PX4IO_SERIAL_RCC_REG, 0, PX4IO_SERIAL_RCC_EN); /* configure pins for serial use */ px4_arch_configgpio(PX4IO_SERIAL_TX_GPIO); px4_arch_configgpio(PX4IO_SERIAL_RX_GPIO); /* reset & configure the UART */ rCR1 = 0; rCR2 = 0; rCR3 = 0; /* eat any existing interrupt status */ (void)rSR; (void)rDR; /* configure line speed */ uint32_t usartdiv32 = PX4IO_SERIAL_CLOCK / (PX4IO_SERIAL_BITRATE / 2); uint32_t mantissa = usartdiv32 >> 5; uint32_t fraction = (usartdiv32 - (mantissa << 5) + 1) >> 1; rBRR = (mantissa << USART_BRR_MANT_SHIFT) | (fraction << USART_BRR_FRAC_SHIFT); /* attach serial interrupt handler */ irq_attach(PX4IO_SERIAL_VECTOR, _interrupt, this); up_enable_irq(PX4IO_SERIAL_VECTOR); /* enable UART in DMA mode, enable error and line idle interrupts */ rCR3 = USART_CR3_EIE; rCR1 = USART_CR1_RE | USART_CR1_TE | USART_CR1_UE | USART_CR1_IDLEIE; /* create semaphores */ px4_sem_init(&_completion_semaphore, 0, 0); /* _completion_semaphore use case is a signal */ px4_sem_setprotocol(&_completion_semaphore, SEM_PRIO_NONE); /* XXX this could try talking to IO */ return 0; }
PX4IO_serial_f7::PX4IO_serial_f7() : _tx_dma(nullptr), _rx_dma(nullptr), _current_packet(nullptr), _rx_dma_status(_dma_status_inactive), _completion_semaphore(SEM_INITIALIZER(0)), #if 0 _pc_dmasetup(perf_alloc(PC_ELAPSED, "io_dmasetup ")), _pc_dmaerrs(perf_alloc(PC_COUNT, "io_dmaerrs ")) #else _pc_dmasetup(nullptr), _pc_dmaerrs(nullptr) #endif { } PX4IO_serial_f7::~PX4IO_serial_f7() { if (_tx_dma != nullptr) { stm32_dmastop(_tx_dma); stm32_dmafree(_tx_dma); } if (_rx_dma != nullptr) { stm32_dmastop(_rx_dma); stm32_dmafree(_rx_dma); } /* reset the UART */ rCR1 = 0; rCR2 = 0; rCR3 = 0; /* detach our interrupt handler */ up_disable_irq(PX4IO_SERIAL_VECTOR); irq_detach(PX4IO_SERIAL_VECTOR); /* restore the GPIOs */ px4_arch_unconfiggpio(PX4IO_SERIAL_TX_GPIO); px4_arch_unconfiggpio(PX4IO_SERIAL_RX_GPIO); /* Disable APB clock for the USART peripheral */ modifyreg32(PX4IO_SERIAL_RCC_REG, PX4IO_SERIAL_RCC_EN, 0); /* and kill our semaphores */ px4_sem_destroy(&_completion_semaphore); perf_free(_pc_dmasetup); perf_free(_pc_dmaerrs); } int PX4IO_serial_f7::init() { /* initialize base implementation */ int r; if ((r = PX4IO_serial::init((IOPacket *)ROUND_UP_TO_POW2_CT((uintptr_t)_io_buffer_storage, CACHE_LINE_SIZE))) != 0) { return r; } /* allocate DMA */ _tx_dma = stm32_dmachannel(PX4IO_SERIAL_TX_DMAMAP); _rx_dma = stm32_dmachannel(PX4IO_SERIAL_RX_DMAMAP); if ((_tx_dma == nullptr) || (_rx_dma == nullptr)) { return -1; } /* Enable the APB clock for the USART peripheral */ modifyreg32(PX4IO_SERIAL_RCC_REG, 0, PX4IO_SERIAL_RCC_EN); /* configure pins for serial use */ px4_arch_configgpio(PX4IO_SERIAL_TX_GPIO); px4_arch_configgpio(PX4IO_SERIAL_RX_GPIO); /* reset & configure the UART */ rCR1 = 0; rCR2 = 0; rCR3 = 0; /* clear data that may be in the RDR and clear overrun error: */ if (rISR & USART_ISR_RXNE) { (void)rRDR; } rICR = rISR & rISR_ERR_FLAGS_MASK; /* clear the flags */ /* configure line speed */ uint32_t usartdiv32 = (PX4IO_SERIAL_CLOCK + (PX4IO_SERIAL_BITRATE) / 2) / (PX4IO_SERIAL_BITRATE); rBRR = usartdiv32; /* attach serial interrupt handler */ irq_attach(PX4IO_SERIAL_VECTOR, _interrupt, this); up_enable_irq(PX4IO_SERIAL_VECTOR); /* enable UART in DMA mode, enable error and line idle interrupts */ rCR3 = USART_CR3_EIE; /* TODO: maybe use DDRE */ rCR1 = USART_CR1_RE | USART_CR1_TE | USART_CR1_UE | USART_CR1_IDLEIE; /* TODO: maybe we need to adhere to the procedure as described in the reference manual page 1251 (34.5.2) */ /* create semaphores */ px4_sem_init(&_completion_semaphore, 0, 0); /* _completion_semaphore use case is a signal */ px4_sem_setprotocol(&_completion_semaphore, SEM_PRIO_NONE); /* XXX this could try talking to IO */ return 0; }