Создание собственной системы стабилизации
Может библиотеки заменить? вроде STM32F4xx_StdPeriph_Driver по свежее уже есть?
Пару раз натыкался на то что он выкидывал нужный кусок кода. Помогала установка пустой строки в области кода. Так и не понял почему так случалось.
да есть такое…
Так как нелётная погода и настроение вообще аховое, незнал чем заняццо, ну ничего не получается сегодня, решил под бубунтой 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. Закрываем всё это дело и двойным кликом запускаем экзешник (тут есть нюанс - попросил обновится и перестал работать, так что я всё это убил и распаковал заново) и вуаля, под винду лазать больше не надо:)
Вот старая версия 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;
и вообще там есть режим ФИФО, его и надо пользовать.
Если будет желание и возможность, завтра перепишу.
Может библиотеки заменить? вроде STM32F4xx_StdPeriph_Driver по свежее уже есть?
нее, библиотеки тут не при чем
Может библиотеки заменить? вроде STM32F4xx_StdPeriph_Driver по свежее уже есть?
а итог один - тормоза в цыкле а у Саши вообще не запустился…
я на дискавери-F4 пробовал + GY-86… т.е. мот какая специфика, типа на PA9,PA10 уже чего нить навешено… хотя простой примерчик (USART без DMA) из тырнета заработал…
Может библиотеки заменить? вроде STM32F4xx_StdPeriph_Driver по свежее уже есть?
в одном из примеров видел версию 1.0.2, хотя на stm оф. сайте сходу ее не нашел…
особо плохо что закоментина строка
умолчательные значения да совпадают
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR; // смотрел в примерах - оно один раз только выбирается, зачем два раза?
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
Там оно работает, я проверял, но вот вопрос с dma или без?
но вот вопрос с 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
Видишь кругом задержки:
while (DMA_GetCmdStatus(u->TxDMAStream) != DISABLE) {
};
также я в старом драйвере делал…
мне тут подумалось, там же вий 2.1 протокол, может уже чё поменяли? или 2.2 ? блин уже почти год кодятнику - как время летит…
Найдите 10 отличий как говорится : code.google.com/p/aq32plus/…/drv_telemetry.c
прикол что у товарищей то работает, и у меня работало 😃
как там говорят: “дьявол в деталях”… а может именно с дискавери платой какая особенность… хз…
кстати попробуй проект открыть мой (точнее твой, но адаптированный под мпу6050 😃), может там в настройках самого проекта что нить не то… собери мне хекс-у и почтой кинь… проверю…
Часиков в 12 ночи по нашему…
как там говорят: “дьявол в деталях”…
это да
а может именно с дискавери платой какая особенность…
это нет
там вполне структурировано и не коряво с виду написано…
Да, компоновка настроек неплохая, и код написан для абстрактного порта, описанного в структуре. Но сами алгоритмы ничем не отличаются.
это нет
а оказалось да 😃 бомба в дискавери-Ф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
},
...
};
а цыфирку то 115200 зачем там переменная speed есть через cli можно любую скорость ставить…
перевесил USART1 на PB6, PB7 и все пошло
для baseflight это критично, для прошивки через терминал загоняется R - ппроц спускается до лодыря, а лодырь у тебя на других лапах усарт ищет 😃
перевесил USART1 на PB6, PB7
на новой плате он там:) но по другим причинам…
перевесил USART1 на PB6, PB7 и все пошло, но пока мучился уже успел портануть USART+DMA из MWArmF4
)))) нудык! этаж не дискавери, этаж надо смотреть
на новой плате он там но по другим причинам…
По этим же причинам, VBUS там.
По этим же причинам, VBUS там.
А нафига они там кондёр то повесили? я на старой плате закоротил, теперь если шиться через usart1 припрёт (лодырь залить с полным стиранием) только шнурок от usb отцепить дабы питание на pa9 не шло - и прекрасно работает… гы у тебя похоже не получалось через usart1 лодырь залить по той же причине 😃 - я считаю косяк проца в этом (неудобство для пользователя) не ну конечно есть DFU через USB - но чёт я так и не понял как через него всю флеш стереть😵
Там же по моему даже питание на плату с того USB не идёт? (discovery)
вот и вывод - хочешь USB, либо делай лодырь, либо вешай 1.5К на VBUS - D+ и используй программно свободную лапу…
А нафига они там кондёр то повесили?
Дык, usb та там ОТГ, нужно ж в некоторых демках от него внешнее устройства питается.
я считаю косяк проца в этом (неудобство для пользователя)
да нее, не косяк, тут либо-либо. если есть USB то нах усарт? Если нет USB? тогда пожалуста usart.
но чёт я так и не понял как через него всю флеш стереть
То что всё стереть нельзя, дык это в демо софте. Если сильно надо протокол открытый.
А кстати, зачем надо? У нас с тобой проблема прошивки не в этом была.
вот и вывод - хочешь USB, либо делай лодырь,
Сергей, из чего такой вывод? При формировании ДФУ из нормального HEX это нафиг не надо.
Лодырь для Ф4 нужен только для одного, чтоб шится шифрованной прошивкой, это всё… Других применений собственного лодыря придумать не могу.
То что всё стереть нельзя, дык это в демо софте. Если сильно надо протокол открытый.
А кстати, зачем надо? У нас с тобой проблема прошивки не в этом была.
Сергей, из чего такой вывод? При формировании ДФУ из нормального HEX это нафиг не надо.
Лодырь для Ф4 нужен только для одного, чтоб шится шифрованной прошивкой, это всё… Других применений собственного лодыря придумать не могу.
Через демку не сотрёшь - а это однозначный косяк при перезаписи!!! т.е. как выход надо делать свою софтину DFU, или каждому в довесок к плате St-Link собирать? ну или как вариант покупать discovery ибо отдельно программатор как-то не по вкусной цене. Выход для простого пользователя - лодырь (ну тот-же арду - залился планера и привет - новая прошивка) да была бы USB демка такая-же как uploader по Usart да цены б ей небыло и вопросов бы не возникало USB или Usart. Ну вот зачем простому пользователю лишние телодвижения, в той же baseflightGUI всё встроено загоняет проц в режим лодыря и запускает прошивальшик без дёрганий втыкания BOOT0…
При формировании ДФУ из нормального HEX это нафиг не надо.
Кстати надо поработать над техникой 😃 по идее можно заставить компилятор сразу создавать DFU займусь новым лодырем (ну под новую плату) поэкспериментирую…
А кстати, зачем надо? У нас с тобой проблема прошивки не в этом была.
А вот я пробовал залить арду (vrbrain) а потом обратно baseflight - и усё не стартует…
А вот я пробовал залить арду (vrbrain) а потом обратно baseflight - и усё не стартует…
Серёг, это косяк НЕ ПРОЦЕССОРА, это КОСЯК прошивки. Либо она заливается не в те адреса, либо что то ищет в не размеченной компиллером области и находит что-то не то.
Было бы не плохо вычислить что её надо, как это сделать не знаю.
Через демку не сотрёшь - а это однозначный косяк при перезаписи!!! т.е. как выход надо делать свою софтину DFU
Че за демка и что тут стираете? Чем дфу тестер не устраивает?
Стер всё им и прошился им-же
либо что то ищет в не размеченной компиллером области и находит что-то не то. Было бы не плохо вычислить что её надо, как это сделать не знаю.
Конечно ищет 😃 у неё ж там виртуалка 😃 так вот в том то и проблема что если мы что-то меняем в DFU через USB то только в том месте куда прошиву льём… при чём оно просто заменяет данные, а не стирает а потом записывает 😦
Че за демка и что тут стираете? Чем дфу тестер не устраивает?
через USB нативный…