Создание собственной системы стабилизации

SergDoc
rual:

Не вижу проблемы

Тогда я вобще не понимаю в чём беда? Mahowik сказат что у него не та, не другая версия драйвера вообще по tx не запустилась…
хотел сегодня вылететь, даже с планшетом договорился, а тут мокрый снег с дождём и ветер 😦

rual
SergDoc:

Тогда я вобще не понимаю в чём беда?

Вот я действительно не понял что за беда происходит, когда нужно временно отключить ПДП, а потом возобновить. Не могу нормально ПОВТОРНО инициализировать поток, хотя остановку ПДП делаю по руководству, дожидаюсь снятия бита DMA_SxCR_EN.

DMA_Cmd (DMA2_Stream3, DISABLE);
while(DMA_GetCmdStatus(DMA2_Stream3) != DISABLE);

Может у вас с этим же проблема?

Показывай код.

SergDoc

Вот старая версия github.com/SergDoc/…/drv_uart.c
Вот новая github.com/SergDoc/…/drv_uart.c
а итог один - тормоза в цыкле 😦 а у Саши вообще не запустился…
или тут надо:

 /* Î÷èùàåì áèò îáðàáîòêè ïðåðûâàíèÿ */

    DMA_ClearITPendingBit(DMA2_Stream7,DMA_IT_TCIF7);
    DMA_Cmd(DMA2_Stream7, DISABLE);
while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE) {
                   };//добавить?
    if (txBufferHead != txBufferTail)
                               uartTxDMA();
                else
        txDMAEmpty = true;
        }

хоть ты плату снимай…

Не наверно пока новую не соберу снимать не буду, а потом уже на старой буду эксперименты экспериментировать:)

Drinker:

Товарищ серг поведал, что в хавк должна быть вставлена симка.

Логи можно и неразбирая скачать через терминал в планнене…

Drinker
SergDoc:

Логи можно и неразбирая скачать через терминал в планнене…

Попробую. Спасибо. Только ткни куда тыкать.

И чего-то я запуталсо - две версии планнера есть что-ли? На сцайте у 3др версия 2.0, у меня какаято старая и по виду не похожая.

Alexey_1811
SergDoc:

а итог один - тормоза в цыкле а у Саши вообще не запустился… или тут надо:

Попробуйте напрямую с регистрами работать. Говорят в STM32F4xx_StdPeriph_Driver косяки проскакивают.

SergDoc

Есть apm planner (Qt)
и есть Mission planner (net) но по сути они похожи, во вкладке терминал выбрать PX4/PIXHAWK > connect > скачать лог , у меня винда на этом ноуте тормознутая, так что не удивляйтесь - там видно несколько раз тыкался в connect

Alexey_1811:

Говорят в STM32F4xx_StdPeriph_Driver косяки проскакивают

Скорей всего 😦

rual
Alexey_1811:

Говорят в STM32F4xx_StdPeriph_Driver косяки проскакивают.

Пока не встречал, правда один раз пытался на индусов всё свалить… не вышло😁 Библиотеками надо уметь пользоваться, код открытый - читай не хочу 😉

Ещё кейл всё сильно оптимизирует, так что работу с периферией построчно не отладить.

Alexey_1811
rual:

Ещё кейл всё сильно оптимизирует, так что работу с периферией построчно не отладить.

Пару раз натыкался на то что он выкидывал нужный кусок кода. Помогала установка пустой строки в области кода. Так и не понял почему так случалось.

SergDoc

Может библиотеки заменить? вроде STM32F4xx_StdPeriph_Driver по свежее уже есть?

Alexey_1811:

Пару раз натыкался на то что он выкидывал нужный кусок кода. Помогала установка пустой строки в области кода. Так и не понял почему так случалось.

да есть такое…

SergDoc

Так как нелётная погода и настроение вообще аховое, незнал чем заняццо, ну ничего не получается сегодня, решил под бубунтой Mission Planner запустить:
И так что для этого надо?
установить mono runtime

Mono — это платформа для выполнения и разработки программ на основе стандартов ECMA/ISO. Mono — реализация стандарта с открытым исходным кодом от Novell. Mono предоставляет полную среду CLR (Common Language Runtime), включая компилятор и среду выполнения, с помощью которых можно создавать и исполнять байт-код CIL (Common Intermediate Language), а также библиотеку классов.

Этот пакет содержит виртуальную машину, JIT-компилятор и AOT-генератор кода «mono». «mono» выполняет приложения для CLI (Common Language Infrastructure). В настоящий момент Mono поддерживает только архитектуры X86, PowerPC, ARM, SPARC, S/390, AMD64 и IA64. Опционально этот пакет настраивает поддержку BINFMT.

как это сделать?
в консоли набираем:

sudo apt-get install mono-runtime libmono-winforms2.0-cil libmono-corlib2.0-cil libmono-system-web4.0-cil libmono-system-management4.0-cil

после установки лезем сюда и скачиваем сам планнер в архиве!!! не msi.
распаковываем его куда-нибудь (папки без пробелов в названии и не кириллицей)
далее лезем в ту папку находим ArdupilotMegaPlanner10.exe правой клавишей ->свойства -> права ставим галочку - на разрешения запуска как приложение, открыть с помощью -> mono-runtime. Закрываем всё это дело и двойным кликом запускаем экзешник (тут есть нюанс - попросил обновится и перестал работать, так что я всё это убил и распаковал заново) и вуаля, под винду лазать больше не надо:)

rual
SergDoc:

Вот старая версия github.com/SergDoc/Nev_Multi...src/drv_uart.c
Вот новая github.com/SergDoc/Nev_Multi...src/drv_uart.c
а итог один - тормоза в цыкле а у Саши вообще не запустился…

Странно… как работает новая версия я понять не могу, ибо не вижу инициализации потока ПДП

//DMA_InitStructure.DMA_Channel = DMA_Channel_4;
//DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)txBuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
//DMA_InitStructure.DMA_BufferSize = UART_BUFFER_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_Normal;
//DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
//DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
//DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
//DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
//DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

видимо умолчательные значения совпадают с нужными ))) хотя почему круговой режим изменен на нормальный? особо плохо что закоментина строка

//DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;

и вообще там есть режим ФИФО, его и надо пользовать.
Если будет желание и возможность, завтра перепишу.

SergDoc:

Может библиотеки заменить? вроде STM32F4xx_StdPeriph_Driver по свежее уже есть?

нее, библиотеки тут не при чем

mahowik
SergDoc:

Может библиотеки заменить? вроде STM32F4xx_StdPeriph_Driver по свежее уже есть?

SergDoc:

а итог один - тормоза в цыкле а у Саши вообще не запустился…

я на дискавери-F4 пробовал + GY-86… т.е. мот какая специфика, типа на PA9,PA10 уже чего нить навешено… хотя простой примерчик (USART без DMA) из тырнета заработал…

SergDoc:

Может библиотеки заменить? вроде STM32F4xx_StdPeriph_Driver по свежее уже есть?

в одном из примеров видел версию 1.0.2, хотя на stm оф. сайте сходу ее не нашел…

SergDoc
rual:

особо плохо что закоментина строка

умолчательные значения да совпадают
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR; // смотрел в примерах - оно один раз только выбирается, зачем два раза?

mahowik

upd: еще можно глянуть в старом порте вия на F4 code.google.com/p/uavp-mods/downloads/detail?name=…

MWArmF4\src\harness\harness.c
MWArmF4\src\harness\serial.c
там вполне структурировано и не коряво с виду написано…

// Rewritten from AQ original Copyright © 2011 Bill Nesbitt
SergDoc

Там оно работает, я проверял, но вот вопрос с dma или без?

mahowik
SergDoc:

но вот вопрос с dma или без?

с dma, но нюансы я пока не понимаю

pins.c


SerialPortDef SerialPorts[MAX_SERIAL_PORTS] = { // Tx, Rx
    { true, USART1, GPIO_AF_USART1, GPIOA,
        GPIO_Pin_9, GPIO_PinSource9,
        GPIO_Pin_10, GPIO_PinSource10,
        true, USART1_IRQn,
        false, DMA_Channel_4,
        DMA2_Stream7, DMA2_Stream7_IRQn,
        DMA2_Stream5,
        115200
        },

    { false, USART2, GPIO_AF_USART2, GPIOA,
        GPIO_Pin_2, GPIO_PinSource2,
        GPIO_Pin_3, GPIO_PinSource3,
        false, USART2_IRQn,
        false, DMA_Channel_4,
        DMA1_Stream6, DMA1_Stream6_IRQn,
        DMA1_Stream5,
        115200 // SBus 110000
    	}
    };

serial.c



#include "harness.h"

// Rewritten from AQ original Copyright © 2011 Bill Nesbitt

volatile uint8 TxQ[MAX_SERIAL_PORTS][SERIAL_BUFFER_SIZE] __attribute__((aligned(4)));
volatile int16 TxQTail[MAX_SERIAL_PORTS];
volatile int16 TxQHead[MAX_SERIAL_PORTS];
volatile int16 TxQNewHead[MAX_SERIAL_PORTS];

volatile uint8 RxQ[MAX_SERIAL_PORTS][SERIAL_BUFFER_SIZE] __attribute__((aligned(4)));
volatile int16 RxQTail[MAX_SERIAL_PORTS];
volatile int16 RxQHead[MAX_SERIAL_PORTS];
volatile int16 RxQNewHead[MAX_SERIAL_PORTS];

uint8_t TxCheckSum = 0;

void serialTxDMA(uint8 s) {

	SerialPorts[s].TxDMAStream->M0AR = (uint32) &TxQ[s][TxQHead[s]];

	if (TxQTail[s] > TxQHead[s]) { // Tail not wrapped around yet
		DMA_SetCurrDataCounter(SerialPorts[s].TxDMAStream, TxQTail[s]
				- TxQHead[s]);
		TxQNewHead[s] = TxQTail[s];
	} else {// Tail has wrapped do balance from Head to end of Buffer
		DMA_SetCurrDataCounter(SerialPorts[s].TxDMAStream, SERIAL_BUFFER_SIZE
				- TxQHead[s]);
		TxQNewHead[s] = 0;
	}
	DMA_Cmd(SerialPorts[s].TxDMAStream, ENABLE);

} // serialTxDMA

boolean serialAvailable(uint8 s) {
	boolean r;

	if (SerialPorts[s].DMAUsed) {
		RxQTail[s] = SERIAL_BUFFER_SIZE - DMA_GetCurrDataCounter(
				SerialPorts[s].RxDMAStream);
		r = RxQHead[s] != RxQTail[s];
	} else if (SerialPorts[s].InterruptsUsed)
		r = RxQTail[s] != RxQHead[s];
	else {
		r = (USART_GetFlagStatus(SerialPorts[s].USART, USART_FLAG_RXNE) == SET);
	}

	return (r);
} // serialAvailable

uint8 RxChar(uint8 s) {
	uint8 ch;

	if (SerialPorts[s].DMAUsed || SerialPorts[s].InterruptsUsed) {
		ch = RxQ[s][RxQHead[s]];
		RxQHead[s] = (RxQHead[s] + 1) & (SERIAL_BUFFER_SIZE - 1);
	} else
		ch = USART_ReceiveData(SerialPorts[s].USART);

	return (ch);
} // RxChar

uint8 PollRxChar(uint8 s) {
	uint8 ch;

	if (serialAvailable(s)) {
		ch = RxChar(s);
		return (ch);
	} else {
		return (0);
	}
} // PollRxChar

void TxChar(uint8 s, uint8 ch) {
	int16 NewTail;

	TxCheckSum ^= ch;
	if (SerialPorts[s].DMAUsed || SerialPorts[s].InterruptsUsed) {
		NewTail = (TxQTail[s] + 1) & (SERIAL_BUFFER_SIZE - 1);
		while (NewTail == TxQHead[s]) {
		};

		TxQ[s][TxQTail[s]] = ch;
		// tail points to NEXT free slot
		TxQTail[s] = NewTail;

		if (SerialPorts[s].DMAUsed) {
			if (DMA_GetCmdStatus(SerialPorts[s].TxDMAStream) == DISABLE)
				serialTxDMA(s);
		} else {
			// if TXE then interrupt will be pending
			USART_ITConfig(SerialPorts[s].USART, USART_IT_TXE, ENABLE);
		}
	} else {
		while (USART_GetFlagStatus(SerialPorts[s].USART, USART_FLAG_TXE)
				== RESET) {
		};
		USART_SendData(SerialPorts[s].USART, ch);
	}
} // TxChar

void serialISR(uint8 s) {
	uint8 ch;

	if (USART_GetITStatus(SerialPorts[s].USART, USART_IT_RXNE) == SET) {
		ch = USART_ReceiveData(SerialPorts[s].USART);
		RxQ[s][RxQTail[s]] = ch;
		RxQTail[s] = (RxQTail[s] + 1) & (SERIAL_BUFFER_SIZE - 1);

		if (RxQTail[s] == RxQHead[s]) { // full
			//USART_ITConfig(SerialPorts[s].USART, USART_IT_RXNE, DISABLE);
		}
	}

	if (USART_GetITStatus(SerialPorts[s].USART, USART_IT_TXE) == SET) {
		if (TxQTail[s] != TxQHead[s]) {
			ch = TxQ[s][TxQHead[s]];
			USART_SendData(SerialPorts[s].USART, ch);
			TxQHead[s] = (TxQHead[s] + 1) & (SERIAL_BUFFER_SIZE - 1);
		}
		if (TxQHead[s] == TxQTail[s])
			USART_ITConfig(SerialPorts[s].USART, USART_IT_TXE, DISABLE);
	}
} // serialISR

void InitSerial(void) {

	//TODO:	serialPortInit(0, 115200);

} // InitSerial

harness.c


void InitSerialPort(uint8 s) {
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	DMA_InitTypeDef DMA_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	SerialPortDef * u;

	u = &SerialPorts[s];

	if (u->Used) {

		GPIO_StructInit(&GPIO_InitStructure);
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
#ifdef STM32F1
		GPIO_InitStructure.GPIO_Pin = u->TxPin;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
		GPIO_Init(u->Port, &GPIO_InitStructure);

		GPIO_InitStructure.GPIO_Pin = u->RxPin;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
		GPIO_Init(u->Port, &GPIO_InitStructure);
#else
		GPIO_StructInit(&GPIO_InitStructure);
		GPIO_InitStructure.GPIO_Pin = u->TxPin | u->RxPin;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
		//GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
		GPIO_Init(u->Port, &GPIO_InitStructure);

		GPIO_PinAFConfig(u->Port, u->TxPinSource, u->USART_AF);
		GPIO_PinAFConfig(u->Port, u->RxPinSource, u->USART_AF);
#endif
		USART_StructInit(&USART_InitStructure);
		//USART_InitStruct->USART_Parity = USART_Parity_No;
		USART_InitStructure.USART_BaudRate = u->Baud;
		USART_Init(u->USART, &USART_InitStructure);

		NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
		NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
		NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

		TxQTail[s] = TxQHead[s] = TxQNewHead[s] = 0;

		if (u->DMAUsed) {
			// Common
			DMA_StructInit(&DMA_InitStructure);
			DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
			DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
			DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32) &u->USART->DR;
			DMA_InitStructure.DMA_BufferSize = SERIAL_BUFFER_SIZE;

			// Receive DMA
			DMA_DeInit(u->RxDMAStream);

			DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32) &u->USART->DR;
			DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
#ifdef STM32F1
			DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
			DMA_InitStructure.DMA_MemoryBaseAddr = (uint32) RxQ[s];
#else
			while (DMA_GetCmdStatus(u->RxDMAStream) != DISABLE) {
			};
			DMA_InitStructure.DMA_Channel = u->DMAChannel;
			DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
			DMA_InitStructure.DMA_Memory0BaseAddr = (uint32) RxQ[s];
#endif
			DMA_Init(u->RxDMAStream, &DMA_InitStructure);
			DMA_Cmd(u->RxDMAStream, ENABLE);
			USART_DMACmd(u->USART, USART_DMAReq_Rx, ENABLE);

			RxQTail[s] = RxQHead[s] = SERIAL_BUFFER_SIZE
					- DMA_GetCurrDataCounter(u->RxDMAStream);

			// Transmit DMA
			NVIC_InitStructure.NVIC_IRQChannel = u->TxDMAISR;
			NVIC_Init(&NVIC_InitStructure);

			DMA_DeInit(u->TxDMAStream);
#ifdef STM32F1
			DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
#else
			while (DMA_GetCmdStatus(u->TxDMAStream) != DISABLE) {
			};
			DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
			//	DMA_InitStructure.DMA_Memory0BaseAddr = (uint32) TxQ[s];
#endif
			DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
			DMA_Init(u->TxDMAStream, &DMA_InitStructure);

			DMA_SetCurrDataCounter(u->TxDMAStream, 0);
			DMA_ITConfig(u->TxDMAStream, DMA_IT_TC, ENABLE);

			USART_DMACmd(u->USART, USART_DMAReq_Tx, ENABLE);
		} else if (u->InterruptsUsed) {
			RxQTail[s] = RxQHead[s] = 0;
			NVIC_InitStructure.NVIC_IRQChannel = u->ISR;
			NVIC_Init(&NVIC_InitStructure);

			USART_ITConfig(u->USART, USART_IT_RXNE, ENABLE);
		}
		USART_Cmd(u->USART, ENABLE);
	}

} // InitSerialPort
SergDoc

Видишь кругом задержки:
while (DMA_GetCmdStatus(u->TxDMAStream) != DISABLE) {
};
также я в старом драйвере делал…
мне тут подумалось, там же вий 2.1 протокол, может уже чё поменяли? или 2.2 ? блин уже почти год кодятнику - как время летит…
Найдите 10 отличий как говорится : code.google.com/p/aq32plus/…/drv_telemetry.c
прикол что у товарищей то работает, и у меня работало 😃

mahowik

как там говорят: “дьявол в деталях”… а может именно с дискавери платой какая особенность… хз…

кстати попробуй проект открыть мой (точнее твой, но адаптированный под мпу6050 😃), может там в настройках самого проекта что нить не то… собери мне хекс-у и почтой кинь… проверю…

rual
mahowik:

как там говорят: “дьявол в деталях”…

это да

mahowik:

а может именно с дискавери платой какая особенность…

это нет

mahowik:

там вполне структурировано и не коряво с виду написано…

Да, компоновка настроек неплохая, и код написан для абстрактного порта, описанного в структуре. Но сами алгоритмы ничем не отличаются.

mahowik
rual:

это нет

а оказалось да 😃 бомба в дискавери-Ф4 на PA9 висит 😃 че блин сразу не залез в схему, раз догадки были… кондер блин на 4.7мкф на лапе сидит…
micromouseonline.com/…/using-usart1-on-the-stm32f4…
my.st.com/public/STe2ecommunities/…/Flat.aspx?Root…

перевесил USART1 на PB6, PB7 и все пошло, но пока мучился уже успел портануть USART+DMA из MWArmF4 😃
терь покрасивше чуток… конфиг такой вышел

SerialPortDef SerialPorts[MAX_SERIAL_PORTS] = { // Tx, Rx
    { true, USART1, GPIO_AF_USART1, GPIOB,
        GPIO_Pin_6, GPIO_PinSource6, // PB6
        GPIO_Pin_7, GPIO_PinSource7, // PB7
        true, USART1_IRQn,
        false, DMA_Channel_4,
        DMA2_Stream7, DMA2_Stream7_IRQn,
        DMA2_Stream5,
        115200
        },

    ...
    };