|
发表于 2022-10-23 21:35:23
|
显示全部楼层
Ardupilot 串口代码学习
1.usb串口初始化
void Copter::init_ardupilot()
{
//初始化USB------------------initialise serial port
serial_manager.init_console(); //usb终端初始化
}
1
2
3
4
5
void AP_SerialManager::init_console()
{
//初始化终端立即设定字节和波特率-----------initialise console immediately at default size and baud
state[0].uart = hal.uartA; // serial0, uartA, always console
state[0].uart->begin(AP_SERIALMANAGER_CONSOLE_BAUD, //波特率---115200
AP_SERIALMANAGER_CONSOLE_BUFSIZE_RX, //接收缓冲区---128
AP_SERIALMANAGER_CONSOLE_BUFSIZE_TX); //发送缓冲区---128
}
1
2
3
4
5
6
7
8
void UARTDriver::begin(uint32_t b, uint16_t rxS, uint16_t txS)
{
thread_init(); //线程初始化
if (sdef.serial == nullptr)
{
return;
}
uint16_t min_tx_buffer = 4096;
uint16_t min_rx_buffer = 1024;
// on PX4 we have enough memory to have a larger transmit and
// receive buffer for all ports. This means we don't get delays
// while waiting to write GPS config packets
if (txS < min_tx_buffer)
{
txS = min_tx_buffer;
}
if (rxS < min_rx_buffer)
{
rxS = min_rx_buffer;
}
/*
allocate the read buffer
we allocate buffers before we successfully open the device as we
want to allocate in the early stages of boot, and cause minimum
thrashing of the heap once we are up. The ttyACM0 driver may not
connect for some time after boot
*/
while (_in_timer)
{
hal.scheduler->delay(1);
}
if (rxS != _readbuf.get_size())
{
_initialised = false;
_readbuf.set_size(rxS);
}
bool clear_buffers = false;
if (b != 0)
{
// clear buffers on baudrate change, but not on the console (which is usually USB)
if (_baudrate != b && hal.console != this)
{
clear_buffers = true;
}
_baudrate = b;
}
if (clear_buffers)
{
_readbuf.clear();
}
if (rx_bounce_buf == nullptr) {
rx_bounce_buf = (uint8_t *)hal.util->malloc_type(RX_BOUNCE_BUFSIZE, AP_HAL::Util::MEM_DMA_SAFE);
}
if (tx_bounce_buf == nullptr) {
tx_bounce_buf = (uint8_t *)hal.util->malloc_type(TX_BOUNCE_BUFSIZE, AP_HAL::Util::MEM_DMA_SAFE);
chVTObjectInit(&tx_timeout);
tx_bounce_buf_ready = true;
}
/*
allocate the write buffer
*/
while (_in_timer)
{
hal.scheduler->delay(1);
}
if (txS != _writebuf.get_size())
{
_initialised = false;
_writebuf.set_size(txS);
}
if (clear_buffers)
{
_writebuf.clear();
}
if (sdef.is_usb)
{
#ifdef HAVE_USB_SERIAL
/*
* Initializes a serial-over-USB CDC driver.
*/
if (!_device_initialised)
{
sduObjectInit((SerialUSBDriver*)sdef.serial);
sduStart((SerialUSBDriver*)sdef.serial, &serusbcfg);
/*
* Activates the USB driver and then the USB bus pull-up on D+.
* Note, a delay is inserted in order to not have to disconnect the cable
* after a reset.
*/
usbDisconnectBus(serusbcfg.usbp);
hal.scheduler->delay_microseconds(1500);
usbStart(serusbcfg.usbp, &usbcfg);
usbConnectBus(serusbcfg.usbp);
_device_initialised = true;
}
#endif
} else
{
#if HAL_USE_SERIAL == TRUE
if (_baudrate != 0) {
bool was_initialised = _device_initialised;
//setup Rx DMA
if(!_device_initialised) {
if(sdef.dma_rx) {
rxdma = STM32_DMA_STREAM(sdef.dma_rx_stream_id);
chSysLock();
bool dma_allocated = dmaStreamAllocate(rxdma,
12, //IRQ Priority
(stm32_dmaisr_t)rxbuff_full_irq,
(void *)this);
osalDbgAssert(!dma_allocated, "stream already allocated");
chSysUnlock();
#if defined(STM32F7)
dmaStreamSetPeripheral(rxdma, &((SerialDriver*)sdef.serial)->usart->RDR);
#else
dmaStreamSetPeripheral(rxdma, &((SerialDriver*)sdef.serial)->usart->DR);
#endif // STM32F7
}
if (sdef.dma_tx) {
// we only allow for sharing of the TX DMA channel, not the RX
// DMA channel, as the RX side is active all the time, so
// cannot be shared
dma_handle = new Shared_DMA(sdef.dma_tx_stream_id,
SHARED_DMA_NONE,
FUNCTOR_BIND_MEMBER(&UARTDriver::dma_tx_allocate, void, Shared_DMA *),
FUNCTOR_BIND_MEMBER(&UARTDriver::dma_tx_deallocate, void, Shared_DMA *));
}
_device_initialised = true;
}
sercfg.speed = _baudrate;
if (!sdef.dma_tx && !sdef.dma_rx) {
sercfg.cr1 = 0;
sercfg.cr3 = 0;
} else {
if (sdef.dma_rx) {
sercfg.cr1 = USART_CR1_IDLEIE;
sercfg.cr3 = USART_CR3_DMAR;
}
if (sdef.dma_tx) {
sercfg.cr3 |= USART_CR3_DMAT;
}
}
sercfg.cr2 = USART_CR2_STOP1_BITS;
sercfg.irq_cb = rx_irq_cb;
sercfg.ctx = (void*)this;
sdStart((SerialDriver*)sdef.serial, &sercfg);
if(sdef.dma_rx) {
//Configure serial driver to skip handling RX packets
//because we will handle them via DMA
((SerialDriver*)sdef.serial)->usart->CR1 &= ~USART_CR1_RXNEIE;
//Start DMA
if(!was_initialised) {
uint32_t dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
dmamode |= STM32_DMA_CR_CHSEL(STM32_DMA_GETCHANNEL(sdef.dma_rx_stream_id,
sdef.dma_rx_channel_id));
dmamode |= STM32_DMA_CR_PL(0);
dmaStreamSetMemory0(rxdma, rx_bounce_buf);
dmaStreamSetTransactionSize(rxdma, RX_BOUNCE_BUFSIZE);
dmaStreamSetMode(rxdma, dmamode | STM32_DMA_CR_DIR_P2M |
STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE);
dmaStreamEnable(rxdma);
}
}
}
#endif // HAL_USE_SERIAL
}
if (_writebuf.get_size() && _readbuf.get_size()) {
_initialised = true;
}
_uart_owner_thd = chThdGetSelfX();
// setup flow control
set_flow_control(_flow_control);
if (serial_num == 0 && _initialised) {
#ifndef HAL_STDOUT_SERIAL
// setup hal.console to take printf() output
vprintf_console_hook = hal_console_vprintf;
#endif
}
}
————————————————
版权声明:本文为CSDN博主「魔城烟雨」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lixiaoweimashixiao/article/details/88596684 |
|