STM32VLDISCOVERY. The Грабли, или Для самых начинающих

Предыстория

Пару дней назад случилось со мной счастье — от заморских купцов пришла бандероль. В бандероли обнаружилась отладочная плата STM32VLDISCOVERY, заказанная давеча на ebay. Обошлось счастье примерно в $23, включая доставку в Алматы, заняла оная доставка недели три. К тому времени Keil (4.23) уже стоял под парами, учебный курс с easyelectronics.ru был прочитан, в общем я был готов мигать светодиодиком, даже двумя. Но не тут-то было!

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

Надеюсь, что эта статья будет полезна тем, кто так же как и я, только что столкнулся с новой архитектурой, и не знает с какой стороны к ней подойти.



Отладочная плата

На борту установлены:

  • Контроллер STM32F100RBT6 (128KB Flash, 8KB RAM, up to 24 MHz, подробно здесь).
  • Кварц 8MHz, установлен на цангах, так что можно ставить свой.
  • Кварц 32.768KHz. Можно часики мутить ))
  • Программатор-отладчик ST-Link, с выходом SWD, так что можно его использовать и для прошивки своих девайсов. Что характерно, отладчик выполнен на более серьёзном STM32F103CBT6.
  • Две кнопки (правда одна из них — RESET).
  • Два светодиода.
  • Все ноги контроллера на штырьках (или не все, но большинство).
  • Всё необходимое для питания от 5V, 3.3V и USB.

Что интересного на плате: две перемычки CN3, в верхней части, справа от F103CBT6. Если они замкнуты, то отладчик работает с целевым контроллером на плате; если их разомкнуть, то можно подключать внешний контроллер к разъёму SWD (тут же, только слева).



Перемычка “ldd”, слева от целевого контроллера установлена в разрыв питания этого контроллера. Cняв её можно амперметром посмотреть потребление.



На нижней стороне платы есть несколько штук запаиваемых перемычек (как они правильно называются по русски?), о них подробно сказано в мануале. Отмечу здесь наиболее понятные мне сейчас:
SB12, SB13, если их замкнуть (и убрать R15), то кварцем X2 пользоваться не получится, но зато появятся две лишние ноги — PD1 и PD0. С завода они заведены на кварц.

SB14, SB15 — если замкнуть эти две (и убрать R14), то не получится пользоваться часовым кварцем X3, но тоже появятся две ноги — PC15 и PC14.



Также, несколько перемычек отвечают за bootloader (вернее за ноги BOOT), за SWD, и ещё за какую-то ересь. Все подробности есть в мануале, мне же пока сказать нечего, поскольку для мигания диодиком с ними возиться не пришлось. С описанными тоже не пришлось, но там как-то всё понятно ))

Там же, в мануале, есть принципиальная схема платы и описание всех выводов с альтернативными функциями и ремапом. Так что мануал полезен и скачать его надо.

Так же надо качать архив с примерами, в котором содержатся собственно примеры, исходники демонстрационной прошивки, CMSIS и библиотечка для платы, в которой описаны светодиоды, кнопки и прочая шелуха, присутствующая именно на этой плате.

Заруба

Итак, платка подключена к компу посредством шнурка USB, демо-прошивка моргает диодом, Keil запущен, всё вроде готово для быстрого старта. Но быстрого старта не получается.

Во-первых, написанная простецкая программа, даже из одного while(1) {} не компилируется, или компилируется, но не заливается в контроллер, или заливается, но не стартует. Не говоря уже о диодиках.

Во-вторых, после AVR Studio, тутошняя кухня, со всеми этими startup_stm32f10x_md_vl.s и прочими CMSIS’ами кажется непостижимой. Непонятно, зачем всё это надо и откуда начинать разбираться.

Сразу оговорюсь, что знание ассемблера, си и принципов компиляции исходников у меня так себе (хобби всё же), поэтому прошу гуру прочесть и поправить, если я где-то заблуждаюсь.

Прошивка и отладка

Я так понял это глюк Keil’а: прошить STM32VLDISCOVERY через меню Flash-Download не получается (Keil 4.23). Вот что надо сделать, чтобы прошить контроллер:

  • Alt-F7, вкладка Debug.
  • Ставим Use ST-Link Debugger, кнопка Settings — SWD.
  • Ставим галку Run to main(), чтобы отладка пошла с main().
  • Вкладка Utilities, Use Target Driver for Flash Programming — выбираем St-link. Кнопка Settings тут не работает почему-то.
  • Поставить галку Update Target Before Debugging

Теперь нужно скомпилировать код (F7), и начать отладку (Ctrl-F5). Код окажется в контроллере. Только так. Ну или пользоваться для прошивки отдельным софтом.

Добавляет радости тот факт, что отладка на симуляторе не запускается. Error 65: access violation…: no ‘read’ permission. Лечится выбором другого камня, например с F101RB или F103RB симулятор заводится. Но это маленько неудобно.

Инициализация

Первый вопрос, который у меня возник — откуда же стартует код. Мне по наивности казалось, что как всегда, с int main(), а начальная инициализация — забота компилятора.

А вот и нет! Всё начинается в файла startup_stm32f10x_md_vl.s. Этот файл генерируется Keil’ом при создании проекта. Тут и таблица векторов прерываний, и инициализация стека и кусочки кода, загружающие процедуры обработки прерываний. Нас интересует один кусок:

startup_stm32f10x_md_vl.s
; Reset handler
Reset_Handler    PROC
                 EXPORT  Reset_Handler             [WEAK]
     IMPORT  __main
     IMPORT  SystemInit
                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP

Это обработчик сброса, то есть код, который выполняется, после старта или reset’а. Насколько я понимаю, он загружает адреса двух процедур и по очереди передаёт им управление. Вторая из этих процедур — родная int main(), а первая — некая SystemInit() (в одной из статей читал, что Keil не вставляет вызов SystemInit() в генерируемый startup-файл. Возможно это зависит от конкретного камня или от версии Keil’а. У меня вставляет).

SystemInit() нашлась в файле system_stm32f10x.c, входящем в состав CMSIS. Отсюда первый вывод: хрен что заработает, пока вы не подключите CMSIS, или не напишите SystemInit() самостоятельно. Я не о том, что надо инициализировать контроллер вообще, а о том, что должна быть такая процедура. Если её нету, то исходник откажется компилироваться.

О том, что такое CMSIS подробно написано в статьях учебного курса ARM, смотрите на главной easyelectronics.ru. Вкратце — это библиотека, которая даёт всем регистрам стандартные понятные имена и здорово облегчает жизнь программерам, в том числе когда надо портировать код с одного камня на другой.

Собственно, SystemInit() отвечает своему названию, она настраивает камень перед стартом основной программы. Процедура украшена кучей дефайнов на все случаи жизни, если её почистить от всего лишнего (для конкретного проекта), то останется примерно следующее:

system_stm32f10x.c
#define SYSCLK_FREQ_24MHz  24000000
uint32_t SystemCoreClock         = SYSCLK_FREQ_24MHz;
static void SetSysClockTo24(void);
void SystemInit (void)
{
  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  /* Set HSION bit */
  RCC->CR |= (uint32_t)0x00000001;

  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
  RCC->CFGR &= (uint32_t)0xF8FF0000;

  /* Reset HSEON, CSSON and PLLON bits */
  RCC->CR &= (uint32_t)0xFEF6FFFF;

  /* Reset HSEBYP bit */
  RCC->CR &= (uint32_t)0xFFFBFFFF;

  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  RCC->CFGR &= (uint32_t)0xFF80FFFF;

  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;

  /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
  /* Configure the Flash Latency cycles and enable prefetch buffer */
  SetSysClock();
}


static void SetSysClock(void)
{
  SetSysClockTo24();
}

static void SetSysClockTo24(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
  /* Enable HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }  

  if (HSEStatus == (uint32_t)0x01)
  {
    /* Enable Prefetch Buffer */
    FLASH->ACR |= FLASH_ACR_PRFTBE;

    /* Flash 0 wait state */
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;    
 
    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
    
    /*  PLL configuration:  = (HSE / 2) * 6 = 24 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1_Div2 | RCC_CFGR_PLLMULL6);

    /* Enable PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }

    /* Select PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

    /* Wait till PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock 
         configuration. User can add here some code to deal with this error */
  } 
}

Понятно, тут инициализация тактового генератора, без которой жить совсем никак нельзя. Это тот минимум, который нужно сделать самому, если захочется накалякать свою SystemInit(). Естественно, перед сочинением своей SystemInit() необходимо хорошенько раскурить Reference Manual по камню, чтобы иметь представление о его работе.

stm32f10x.h

Вот helloworld, который я написал:

main.c
#include "stm32f10x.h"

void InitLeds(void)
{
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;	//Включили тактирование порта GPIOC.
	GPIOC->CRH	&= ~GPIO_CRH_CNF8;		// Настроили ногу 8 (синий LED) на выход Push-Pull.
	GPIOC->CRH	&= ~GPIO_CRH_CNF9;		// Настроили ногу 9 (зелёный LED) на выход Push-Pull.
 
	GPIOC->CRH   |= GPIO_CRH_MODE8_0;	// Настроили ногу 8 (синий LED) на 10MHz.
	GPIOC->CRH   |= GPIO_CRH_MODE9_0;	// Настроили ногу 9 (зелёный LED) на 10MHz.
	return;
}


int main(void)
{

uint32_t i;

	InitLeds();					// Инициализировали выходы на светодиоды.
	while (1)						// Навеки
	{	
		GPIOC->BRR = GPIO_BRR_BR8;		// Погасили синий
		GPIOC->BSRR = GPIO_BSRR_BS9;	// Зажгли зелёный
											
		for (i = 0; i < 4000000; i++) ;	// Подождали полсекунды
											
		GPIOC->BRR = GPIO_BRR_BR9;		// Погасили зелёный
		GPIOC->BSRR = GPIO_BSRR_BS8;	// Зажгли синий

		for (i = 0; i < 4000000; i++) ;	// Подождали полсекунды
	}
}

Всё по инструкции: новый проект, добавляю CMSIS, прописываю пути к заголовочным файлам, пишу код, компилирую, 0 errors, 0 warnings, заливаю — не работает. Компилирую пример от ST, заливаю — работает. Снова свой — снова нет. Три раза переделывал, IAR чуть не поставил, материал для этой статьи накопил )) — не работает!

Все ответы оказались в stm32f10x.h и в настройках компилятора. Вот фрагмент:

stm32f10x.h
/* Uncomment the line below according to the target STM32 device used in your
   application 
  */

#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD) && !defined (STM32F10X_MD_VL) && !defined (STM32F10X_HD) && !defined (STM32F10X_XL) && !defined (STM32F10X_CL) 
  /* #define STM32F10X_LD */     /*!< STM32F10X_LD: STM32 Low density devices */
  /* #define STM32F10X_LD_VL */  /*!< STM32F10X_LD_VL: STM32 Low density Value Line devices */  
  /* #define STM32F10X_MD */     /*!< STM32F10X_MD: STM32 Medium density devices */
  /* #define STM32F10X_MD_VL */  /*!< STM32F10X_MD_VL: STM32 Medium density Value Line devices */  
  /* #define STM32F10X_HD */     /*!< STM32F10X_HD: STM32 High density devices */
  #define STM32F10X_XL      /*!< STM32F10X_XL: STM32 XL-density devices */
  /* #define STM32F10X_CL */     /*!< STM32F10X_CL: STM32 Connectivity line devices */
#endif
/*  Tip: To avoid modifying this file each time you need to switch between these
        devices, you can define the device in your toolchain compiler preprocessor.

По умолчанию здесь выбран STM32F10X_XL, это камни 101, 102 и 103 серий. А на VLDISCOVERY стоит F100, у которого, в частности, максимальная частота поменьше. Для F100 надо выбрать STM32F10X_MD_VL, иначе SystemInit() попытается завести тактовый генератор на невозможных для этого камня 72 мегагерцах.

Меня сбило с толку то, что в примерах от ST тоже была раскомментирована строчка с STM32F10X_XL, но всё работало. Я решил, что это не критично. B только потом обратил внимание на последний комментарий и догадался заглянуть в дефайны препроцессора ST’шных примеров (Alt-F7, вкладка C/C++), чтобы найти там STM32F10X_MD_VL.

Из всего этого второй вывод: без чтения и понимания всех исходников ничего не заведётся, разве что случайно. А файл stm32f10x.h вдвойне обязательно надо внимательно просмотреть.

Upd:

О кокосе

По совету Ura_X500 скачал и поставил CooCox CoIDE, или просто «Кокос». Самое первое и главное: тулчейн, с которым работает кокос лежит тут.
В кокосе, конечно, удобнее подключать библиотеки, есть драйвер FAT32 и даж RTOS. Кокос сам прописывает дефайны препроцессора, в зависимости от выбранного камня и библиотек. Непонятно, почему Keil этого не может. Кокос сам создаёт main.c )) Это плюсы.
Минусов не заметил. Всё что мне не нравится — дело привычки и личных предпочтений. Для себя решил так, буду под Keil'ом, пока не упрусь в 32KB, чего возможно никогда не случится )) Впрочем не буду загадывать…

Но вот интересная штука: решил повторить тот же самый helloworld в кокосе. Создал проект, добавил всё что надо, скопипастил main.c, скомпилировал. Залил. Работает. Но в два раза медленнее!

Выкинул из исходников всё лишнее, скопипастил все файлы, совпадают до байта, единственная разница — startup_stm32f10x_md_vl.s (и .c), они сильно заточены под конкретную среду. И stdint.h у каждого свой, но типы вроде совпадают. Оптимизация одинаковая. И всё равно, прошивка собранная в Keil'е работает в два раза быстрее. В чём разница, в компиляторах, в каких-то тонкостях исходников? Я ума не приложу.
На случай, если кому интересно, приаттачиваю оба проекта.


Upd2:
Разобрался с разницей! Оказалось, что просто у gcc реализация for сильно длиннее — 10 команд, против 6 у Keil'овского компилятора.

Keil:
0x08000346 2200      MOVS     r2,#0x00
0x08000348 E000      B        0x0800034C
0x0800034A 1C52      ADDS     r2,r2,#1
0x0800034C 4803      LDR      r0,[pc,#12]  ; @0x0800035C
0x0800034E 4282      CMP      r2,r0
0x08000350 D3FB      BCC      0x0800034A

gcc:
0x080002da:   mov.w r3, #0
0x080002de:   str r3, [r7, #4]
0x080002e0:   b.n 0x80002ea <main+98>
0x080002e2:   ldr r3, [r7, #4]
0x080002e4:   add.w r3, r3, #1
0x080002e8:   str r3, [r7, #4]
0x080002ea:   ldr r2, [r7, #4]
0x080002ec:   ldr r3, [pc, #52]       ; (0x8000324 <main+156>)
0x080002ee:   cmp r2, r3
0x080002f0:   bls.n 0x80002e2 <main+90>

Оптимизация отключена. При включенной оптимизации поведение не меняется, но понять дизассемблер сложнее.
Дебаг удобнее у Keil'а. Кокосовский сильно тормознее, и трудно соотнести исходный листинг с дизассемблером, особенно при -O3. Вообще какая-то другая программа у gcc получается )) Keil тоже позволяет себе вольности, но там понятнее что к чему. А вот минус Keil'а в том, что он почему-то не показывает все регистры при отладке. RCC_CFGR2 я посмотреть не смог, нету его.

А в целом кокос вполне себе неплох ))
Файлы в топике: exp coocox.zip, exp Keil.zip

Комментарии (30)

RSS свернуть / развернуть
многие ругаются… но для самых начинающих — www.coocox.org/
скачал… поставил… выбрал проц… скомпилировал… залил… работает…
отладка тоже работает, и без танцев с бубном…
+1
Спасибо! Тоже хотел посмотреть на кокос, но не мог вспомнить, как он называется ))) Поставил, буду взглянуть.
0
На самом деле все не так уж и страшно у СТМ32…
просто компиляторы навязывают свой стиль программирования… :-( причем что кокос что кейл, что остальные…
и этот стиль не похож ни на что-то другое…

а после AVR так и вообще темный лес…

а вообще можно настроить один раз и использовать первый проект как заготовку для последующих
0
лично мне кокос пришелся по душе… тот же GCC, после AVR хоть что то похожее… а воoбще уже привык к стм… сейчас пытаюсь выбросить ATMega8 и поставить STM32F100
0
не знаю как отредактировать ATMega128 на STM32F100
0
<режим_зануды>128 мегабайт флеша? Вы серьезно? :) Контроллер STM32F100RBT6 (128MB Flash</режим_зануды>

Ну это так, а вообще автору спасибо. :)
0
Упс, очепятался )) Килобайт конечно )))
0
А было бы не плохо. Хотя куда ее столько? =)
0
* Контроллер STM32F100RBT6 (128MB Flash, 8KB RAM, up to 24 MHz, подробно здесь).
* Кварц 8MHz, установлен на цангах, так что можно ставить свой.
* Кварц 32.768KHz. Можно часики мутить ))
… так и не исправили
0
Точно. Исправил. Спасибо за напоминание! ))
0
Насчёт кокоса… Поставил, помучал. И я его и он меня ) Сейчас кажется обновлю статью, есть интересная загадка )
0
Собственно обновил, и о загадке написал.
0
я до кейла не добрался, про тулчейн забыл, сорри… но как по мне то загадки никакой нет
хотя конечно работать должно в три раза медленнее…

если я правильно понял про кейловский пример, то там идет запуск PLL на 24 мГц…
в случае с кокосом надо бы тоже запустить проц на 24 мГц, вместо 8, на которых проц стартует по умолчанию (есть пример в RCC)…
0
В том и дело, что SystemInit и там и там одинаковый. Там только старт на 24 MHz, остальное всё убрал. Сижу, курю даташит ))
0
В дизассемблер загляни. В кейле и кокосе совершенно разные компиляторы, а у тебя весь код из задержки на цикле состоит — оно весьма чувствительно к баловству оптимизатора (странно правда, что он вообще эти циклы не выпилил).
0
Не выпилит, там переменная i — volatile (в приложенных архивах). Да и дебаггер показывает, что i досчитывается до положенных 400000 и там и там.
Разгадку нашёл, дело не совсем в оптимизаторе, у gcc реализация for почти в два раза длиннее получается, 10 команд против 6, а так как этот for и занимает всё время, получается такая разница.
Статью обновил, заодно и небольшой опыт дебага получил. Спасибо за совет!
0
Чего и следовало ожидать. Кстати, кейл мухлюет — volatile int i он создал в регистре, тогда как GCC — в ОЗУ и в каждом цикле загружает ее в регистр, увеличивает и сбрасывает обратно. Кроме того, для сравнения он ее вновь загружает из ОЗУ. Поэтому у кейла цикл 4 команды, а у GCC — 7. Если заставишь GCC положить i в регистр, а не ОЗУ (или кейл — в ОЗУ) — время должно сравняться.
А вообще, в стародавние времена книжка по LPC2xxx утверждала, что у кейла оптимизатор получше. Но за это время ситуация могла и измениться.
0
Кейл мог бы и догадаться, что r0 в цикле не используется, так что
LDR r0,[pc,#12]
можно делать перед циклом один раз.
0
По правилам С условие цикла нужно вычислять на каждой операции. А оптимизатор выключен.
0
Если включить оптимизацию и убрать volatile, то у Keil'а остаётся:
0x080002DA 1C52      ADDS     r2,r2,#1
0x080002DC 428A      CMP      r2,r1
0x080002DE D3FC      BCC      0x080002DA

Загрузка r1 на пару команд раньше. То есть сам цикл становится на ту самую LDR r0,[pc,#12] короче. Даже при -O3.
gcc куда злее, на -O1:
0x0800024c: main+64   subs r3, #1
0x0800024e: main+66   bne.n 0x800024c <main+64>

А на -O2 и дальше цикл выбрасывается.
+1
… я с Keil и CoIDE не работаел, но как минимум в IAR и других тулчейнах необходимо отредактировать еще и компоновочный файл, с указанием линкеру о размерах памяти программ и данных и т.п. В IAR он имеет расширение *.icf, в GCC тулчейнах *.ld и т.д. Спрашиваю потому что не видел упоминания о них в вашей статье или они не используются в этих средах?
0
У кокоса в качестве компилятора GCC, файлы есть, memory.ld и link.ld Но генерируются они кокосом, по крайней мере я в их создании участия не принимал )
У Keil'а всё это хранится в файле проекта, как и все прочие настройки линкера, компилятора, и вообще всего. Заполняет он это всё тоже сам, без участия человека. Все настройки доступны в окне Target Options (тот самый Alt-F7).
0
Вкратце — это библиотека, которая даёт всем регистрам стандартные понятные имена и здорово облегчает жизнь программерам, в том числе когда надо портировать код с одного камня на другой.
это Вы описали SPL (standard peripheral library, стандартная библиотека переферии) — своя у каждого производителя камней, а cmsis (Cortex Microcontroller Software Interface Standard) — это описание самого ядра ARM. это желательно не путать.
0
Не совсем. До SPL у меня дело не дошло ещё. SPL это инструментарий для работы с периферией. А cmsis можно условно поделить на две части, одна (CoreSupport) — это описание ядра, а вторая (DeviceSupport) — описание периферии. Все эти RCC, GPIOx и т.д.
0
Кокос сам создаёт main.c )) Это плюсы.
Нет, main.c — это Си. А плюсов там нет — и это минус. И простым способом это не исправить (если ещё поддержку С++ не допилили).
И опять же подсадка на IDE-зависимые галочки/кодогенераторы.
0
Неа, не допилили, и вроде как не собираются. Но есть «непростой» способ: http://www.coocox.org/Forum/topic.php?id=730.
По поводу подсадки: пользуясь любым средством разработки мы так или иначе «подсаживаемся» на его особенности. Если это gcc и блокнот, то мы подсядем на makefile'ы, если IDE, то на галочки )) А кодогенераторов нету ни у кейла ни у кокоса, есть шаблоны, которые можно включить в свой проект. Но можно и не включать, а писать всё с нуля. Это на выбор пользователя.
0
Но есть «непростой» способ: www.coocox.org/Forum/topic.php?id=730.
Способ действительно непростой: пробовал, на их нафиг.
0
coocox + stm32vldiscovery… ну вот кажись и начались грабли… моргаю светодиодами… ставлю ReadOut Protection… и все… нифига не работает… в атмеле такого не было. куда смотреть ума не приложу…
0
вот блин… пол дня времени… надо было просто передернуть питание :((((( ну кто так строит…
0
набрел нечаянно на эту статью…

по поводу быстродействия — в void main() неплохо было бы вызвать SystemInit() — а то у вас камень работает от внутреннего кварца и без умножителей…
в кейле это делается в стартапе (в асм файле при старте прошивки) а вот в кокосе это автоматом не прописывается, и нужно самому добавлять вызов…
кстати еще нужно проверить а что там с коэффициентами — бывают стоят не правильно…
вот я как то писал про STM32F4, но у вас точно такая же ситуация vg.ucoz.ru/publ/programmirovanie_mikrokontrollerov_stm32/stm32_nastrojka_taktirovanija_kontrollera_v_srede_coocox/9-1-0-29
0
  • avatar
  • WitGo
  • 30 декабря 2015, 19:22
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.