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

SergDoc
Stiger:

кстати, vis.asta, я так понял, что тоже AVR использует,

нет 32f4…

SergDoc

отпишусь - провёл эксперимент - после передачи показаний с гир акселя и магнитометра поставил точку останова, эта гадость сериалит мне уже абы что с переполнением, вот и вешается - буду разбиратся…

SergDoc

тут вся периферия F1 и F4 , у меня так сказать найдите 10 отличий, но блин этот код работает(проверял), а мой нет, что за беда не знаю, ибо затыкается не только уарт затыкается и i2c- просто перестаёт считывать данные с датчиков, да и с гиры тоже (с акселя данные есть всегда), попробовать что-ли туда прикрутить SPI и посмотреть что будет, правда с наскоку чёт не удалось собрать проект, но я особо не упирался не смотрел…

SergDoc
SergDoc:

тут вся периферия F1 и F4

под эклипсом собрал, изначально он под Atollic, попробую адаптировать под своё железо посмотрю что будет, а то запёрся совсем…

SergDoc

воевал с версией 2_2 симптомы теже плюс cycleTime взбесился, что-то с математикой не то ибо если отключаю fpu Uart даже не пытается запустится - странно, наверно я где-то проект неправильно настраиваю. В проекте что лежит в git мелкоплата отрабатывает за 2600 новая за 730, а на “чистом” вие (без Калмана ) новая завелась на 3500😵

SergDoc

запустил эту же версию на мелкоплате - цикл тотже 3500 странно… ладно дело сейчас не в этом, блин что я делаю не так при переносе на F4:)

rual
SergDoc:

запустил эту же версию на мелкоплате - цикл тотже 3500 странно

У Ф4 частота выше настолько же, на сколько он быстрее. Если формирование millis() и micros() не испарвлено , то твои миллисекунды будут быстрее на соотношение частот процев 😃

SergDoc
rual:

Если формирование millis() и micros() не испарвлено

Исправлено и в отладчике смотрел - всё правильно, боюсь что-то или в прерываниях или в настройке самого проекта намудрил…

SergDoc

А теперь на пальцах, для особоодарённых - тоесть меня 😃


// cycles per microsecond
static volatile uint32_t usTicks = 0;
// current uptime for 1kHz systick timer. will rollover after 49 days. hopefully we won't care.
static volatile uint32_t sysTickUptime = 0;

static void cycleCounterInit(void)
{
    RCC_ClocksTypeDef clocks;
    RCC_GetClocksFreq(&clocks);
    usTicks = clocks.SYSCLK_Frequency / 1000000; // ну тут, если не путаю, 8 - на обеих платах одинаково - от кварца в 8мГц отталкиваемся?
}

// SysTick
void SysTick_Handler(void)  // откуда вызывается прерывание? незнаю :(
{
    sysTickUptime++; // а один ли кГц?
}

// Return system uptime in microseconds (rollover in 70minutes)
uint32_t micros(void)
{
    register uint32_t ms, cycle_cnt;
    do {
        ms = sysTickUptime;
        cycle_cnt = SysTick->VAL;
    } while (ms != sysTickUptime);
    return (ms * 1000) + (168000 - cycle_cnt) / 168; // тот же кГц умноженый на 1000 вернули с поправкой на что? тактовую проца?
}

// Return system uptime in milliseconds (rollover in 49 days)
uint32_t millis(void)
{
    return sysTickUptime; // ну и вернули тот-же кГц ?
}
RaJa

[QUOTE=SergDoc;4177128]А теперь на пальцах, для особоодарённых - тоесть меня 😃
Сергей, вы столько уже провели времени в компиляторах, что давно бы уже разобрались с устройством и выбрали одну среду, а адаптировали под нее только чистую логику из других проектов. Вместо этого вы тратите многие часы борясь с чужими глюками 😃
clocks.SYSCLK_Frequency - это точно частота кварца, а не системной шины? Вообще частота кварца программно вроде недоступна. Только после прескалеров.

SergDoc

вроде как-то так:
RCC_Clocks->SYSCLK_Frequency = HSE_VALUE; // HSE_VALUE=8000000

RaJa
SergDoc:

вроде как-то так:
RCC_Clocks->SYSCLK_Frequency = HSE_VALUE; // HSE_VALUE=8000000

Итак, если коротко - HSI - это 8 МГЦ, внутренний RC генератор.
HSE - Это внешний генератор, в данном случае кварц.
SYSCLK - это системная частота. Она получается умножением кварца на PLL коэффициент. Скорее всего в вашем случае это 168МГц.
вот описание
То есть делить нужно не на 8М, а на 8М*PLLCLK. Так что подсказали вам похоже правильно - коэффициент неверный использовался.

SergDoc

ну да чёт не догнал сразу, о вот надо для 103-го нарыть такую и сравнить, а то я пользовался уже готовым system_stm32f10x.c , а тут сам собирал system_stm32f4xx.c

вот блин а к 103-му то и нет такой фишки 😦

небольшей разбор полётов:
это отсюда

#define DWT_CYCCNT	((volatile uint32 *)0xE0001004)
///////////////////////////////////////////////////////////////////////////////

uint32 uSClock(void) {
	// TODO: no check for wraparound

	register uint32 PrevTick, Tick, mS;
	__disable_irq();
	Tick = *DWT_CYCCNT;
	PrevTick = sysTickCycleCounter;
	mS = sysTickUptime;
	__enable_irq();
	return ((mS * 1000) + (Tick - PrevTick) / TicksuS);

} // uSClock

у меня же получается:

uint32_t micros(void)
{
    register uint32_t ms, cycle_cnt;
    do {
        ms = sysTickUptime;
        cycle_cnt = SysTick->VAL; // значение SysTick = 0хЕ000E010 ?   SysTick->VAL = 0x00028831 ?
    } while (ms != sysTickUptime);
    return (ms * 1000) + (168000 - cycle_cnt) / 168;  // а не нормально должно быть (ms*1000)+12 получается
}

остаётся вопрос по sysTickUptime …

SergDoc

systick вырабатывает прерывание 1000 раз в секунду, значит всё верно 😦

oleg70

Наткнулся на странную проблему SPI+DMA в режиме “CIRCULAR”, нужно последовательно вывести массив данных из 28-ти полуслов из памяти в SPI, все выводится НО если бит “0” во втором с конца массива элементе равен единице, передача зависает…,
т.е. передаю в 26-ом элементе 0x0001 - виснет, а при любом другом значении в этом элементе, буфер передается без проблем…
Пробовал менять длину буфера, но эффект тот же… (Прям мистика какая то! может я косяк линейки F303 нарыл?😃)
Кстати в фирменном архиве что то нет примеров про SPI, SPI+DMA?

SergDoc

А что именно виснет? я тоже ДМА с подвисоном не победил 😦

rual
oleg70:

Кстати в фирменном архиве что то нет примеров про SPI, SPI+DMA?

Странно, циркуляр не пробловал для СПИ (у меня каждый считанный пакет по новой перезаряжается), у меня вполне уверенно работает

uint8_t DUSbuffer[10];
/*  íàñòðîéêà ÏÄÏ ÄÓÑ */
void DUS_DMA_Init(void)
{
 DMA_InitTypeDef DMA_InitStruct;
 EXTI_InitTypeDef EXTI_InitStructure;

   /* Íàñòðîéêà ÏÄÏ äëÿ ÄÓÑ */
 SPI_Cmd (L3GD20_SPI, ENABLE);           /* ðàçðåøàåì ðàáîòó ÑÏÈ */

 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

 /* çàïîëíÿåì ñòðóêòóðó ÏÄÏ ïî óìîë÷àíèþ */
 DMA_StructInit(&DMA_InitStruct);
 DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;     /* ïîñòîÿííûé àäðåñ ïåðåôèðèè */
  DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;/* ðàçìåðíîñòü óñ-âà - áàéò */
 DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;        /* ñ÷åò÷èê áóôåðà óâåëè÷èâàåòñÿ */
 DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;     /* ðàçìåðíîñòü áóôåðà - áàéò */
  DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;             /* íîðìàëüíûé ðåæèì  */
 DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;              /* ìåæäó ïåðåôèðèåé è ÎÇÓ */
 DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&L3GD20_SPI->DR; /* çàäàäåì àäðåñ ïðèåìíèêà äàííûõ  */
 DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&DUSbuffer[0];    /* çàäàåì àäðåñ èñòî÷íèêà äàííûõ  */
 DMA_InitStruct.DMA_BufferSize = 9;                 /* óêàçûâàåì ÷èñëî ïåðåñûëàåìûõ äàííûõ */
 /* ïðèìåíÿåì ñòðóêòóðó äëÿ çàïèñè */
 DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;         /* ïðèîðåòåò çàïèñè ñðåäíèé */
 DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;           /* ïîðò - ïðèåìíèê */
 DMA_Init(DUS_DMA_Wr, &DMA_InitStruct);
 /* ïðèìåíÿåì ñòðóêòóðó äëÿ ÷òåíèÿ */
 DMA_InitStruct.DMA_Priority = DMA_Priority_High;          /* ïðèîðåòåò ÷òåíèÿ âûñîêèé   */
 DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;           /* ïîðò - èñòî÷íèê */
 DMA_Init(DUS_DMA_Rd, &DMA_InitStruct);
 /* ðàçðåøèòü çàïðîñ ÏÄÏ äëÿ ÑÏÈ */
 SPI_I2S_DMACmd(L3GD20_SPI, SPI_I2S_DMAReq_Rx, ENABLE);
 SPI_I2S_DMACmd(L3GD20_SPI, SPI_I2S_DMAReq_Tx, ENABLE);

 /* òàêòèðóåì ïîðò */
 RCC_AHBPeriphClockCmd(L3GD20_SPI_INT2_GPIO_CLK, ENABLE);
 /* êîíôèãóðàöèÿ ïîäêëþ÷åíèÿ ê ïîðòàì */
 SYSCFG_EXTILineConfig(L3GD20_SPI_INT2_EXTI_PORT_SOURCE,L3GD20_SPI_INT2_EXTI_PIN_SOURCE);
 /* çàïðîñ ïðåðûâàíèÿ ïî ãîòîâíîñòè äàííûõ ÄÓÑ*/
 EXTI_ClearITPendingBit(L3GD20_SPI_INT2_EXTI_LINE);
  EXTI_InitStructure.EXTI_Line = L3GD20_SPI_INT2_EXTI_LINE;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
}
/* ðàçðåøàåì ðàáîòó ïåòëè ÄÓÑ */
void DUS_PetlyaInit(void)
{
 /* ïåðåíàñòðîèì ÏÄÏ ÄÓÑà*/
 DUS_DMA_Init();
 /* ðàçðåøàåì ïðåðûâàíèÿ îò ÏÄÏ äëÿ êàíàëà ÷òåíèÿ */
 DMA_ITConfig(DUS_DMA_Rd, DMA_IT_TC, ENABLE);
 /* ðàçðåøèòü çàïðîñ ÏÄÏ äëÿ ÑÏÈ */
 SPI_I2S_DMACmd(L3GD20_SPI, SPI_I2S_DMAReq_Rx, ENABLE);
 SPI_I2S_DMACmd(L3GD20_SPI, SPI_I2S_DMAReq_Tx, ENABLE);
 /* ðàçðåøàåì ðàáîòó ÏÄÏ */
 DMA_Cmd (DUS_DMA_Rd, ENABLE);            /* ñíà÷àëà ðàçðåøàåì ÷òåíèå(!!!!) */
 DMA_Cmd (DUS_DMA_Wr, ENABLE);
 /* íàñòðîéêà ïðåðûâàíèÿ ïîñëå ÏÄÏ */
 NVIC_EnableIRQ(DMA1_Channel2_IRQn);
  NVIC_SetPriority(DMA1_Channel2_IRQn, 2);
 /* íàñòðîéêà ïðåðûâàíèÿ ïî ëèíèè ãîòîâíîñòè ÄÓÑ */
 NVIC_EnableIRQ(L3GD20_SPI_INT2_EXTI_IRQn);
  NVIC_SetPriority(L3GD20_SPI_INT2_EXTI_IRQn, 2);
 /* òîëêíåì ïåòëþ ÄÓÑ */
 DUS_Zapros();
}
/* çàïðåòèòü ðàáîòó ïåòëè ÄÓÑ */
void DUS_PetlyaDeInit(void)
{
 __IO uint32_t L3GD20Timeout = L3GD20_FLAG_TIMEOUT;
 /* çàïðåòèì ïðåðûâàíèÿ ïî ëèíèè ãîòîâíîñòè ÄÓÑ */
 NVIC_DisableIRQ(L3GD20_SPI_INT2_EXTI_IRQn);

 /* äîæäåìñÿ îêîí÷àíèÿ ÏÄÏ */
 while (GPIO_ReadInputDataBit(L3GD20_SPI_CS_GPIO_PORT,L3GD20_SPI_CS_PIN)==Bit_RESET){
    if((L3GD20Timeout--) == 0)  L3GD20_TIMEOUT_UserCallback();
  }

 /* çàïðåòèì ðàáîòó ÏÄÏ */
 DMA_Cmd (DUS_DMA_Wr, DISABLE);  /* ñíà÷àëà çàïðåòèì çàïèñü(!!!!) */
 DMA_Cmd (DUS_DMA_Rd, DISABLE);
 /* çàïðåòèì ïðåðûâàíèÿ ïîñëå ÏÄÏ */
 NVIC_DisableIRQ(DMA1_Channel2_IRQn);
}
/* çàïðîñ äàííûõ ÏÄÏ */
void DUS_Zapros(void)
{
 if (DMA_GetCurrDataCounter(DUS_DMA_Rd)){
  /* çàïðåòèì ïðåðûâàíèÿ ïî ëèíèè ãîòîâíîñòè ÄÓÑ */
  NVIC_DisableIRQ(L3GD20_SPI_INT2_EXTI_IRQn);
  return;
 }
 /* óñòàíîâèì âûáîð âåäîìîãî óñ-âà */
 L3GD20_CS_LOW();
 /* ñáðîñèì ôëàã çàâåðøåíèÿ öèêëà ÏÄÏ */
 DMA_ClearFlag(DMA1_FLAG_GL2);DMA_ClearFlag(DMA1_FLAG_GL3);
 /* íàñòðîèì àäðåñ è ðåæèì ïåðåäà÷è */
 DUSbuffer[0]= L3GD20_OUT_TEMP_ADDR|READWRITE_CMD|MULTIPLEBYTE_CMD;
 /* ïåðåçàðÿäêà ÏÄÏ */
 DMA_SetCurrDataCounter(DUS_DMA_Rd,9);
 DMA_SetCurrDataCounter(DUS_DMA_Wr,9);
 /* ðàçðåøàåì ðàáîòó ÏÄÏ */
 DMA_Cmd (DUS_DMA_Rd, ENABLE);            /* ñíà÷àëà ðàçðåøàåì ÷òåíèå(!!!!) */
 DMA_Cmd (DUS_DMA_Wr, ENABLE);
}
void DUS_EndDMASPITrans_ISR(void)
{
 /* çàïðåòèì ðàáîòó ÏÄÏ */
 DMA_Cmd (DUS_DMA_Wr, DISABLE);  /* ñíà÷àëà çàïðåòèì çàïèñü(!!!!) */
 DMA_Cmd (DUS_DMA_Rd, DISABLE);
 /* ñíèìåì âûáîð óñ-âà ñ  âåäîìîãî */
 L3GD20_CS_HIGH();
 /* îáíîâëÿåì äàííûå óc-â ÈÍÑ */
 DUSDataRdy();
 NVIC_EnableIRQ(L3GD20_SPI_INT2_EXTI_IRQn);
}
void  DUS_TolkPetlu(void)
{ /* ïðèíóäèòåëüíûé çàïóñê ïî âíåøíèì ñèãíàëàì */
 //if (GPIO_ReadInputData(GPIO_IMU) & IMU_DRDY_G)
      EXTI_GenerateSWInterrupt(L3GD20_SPI_INT2_EXTI_IRQn);
//    if (GPIO_ReadInputData(GPIO_IMU) & IMU_DRDY_A)
//       EXTI_GenerateSWInterrupt(EXTI_Line0);
}
oleg70
rual:

циркуляр не пробловал

У Вас “DMA_Mode_Normal” и “DMA_BufferSize = 9;” , если я правильно понимаю, то после одного “толчка” DMA, он передаст один байт из девяти и после девяти таких “толчков” выдаст флаг “трансфер комплит”…
А в “DMA_Mode_Circular” после одного “толчка” DMA автоматом сольет все 9 байт и поставит флаг…
Так вот виснет у меня на 26-м (при условии “1” мл.разр.!!!) из 28…
Прям чушь какая то, задача достаточно примитивная, а тут просто ступор, это я OSD делаю (видеостроку вывожу в порт), сначала понять не мог, а когда разобрался что дело в 1-ом бите (!) да еще именно в во втором с конца байте, тут мне совсем поплохело…(не могу понять логику происходящего)

oleg70

Затупил… , в “нормал” моде весь буфер передается с одного толчка, просто надо каждый раз количество байт ставить заново…
Но суть проблемы не изменилась… Ладно еще, в моей задаче можно этот “чудо бит” обойти (всего лишь картинка), а если важные данные пересылать пакетно ? ?