Защо точно ни трябва да ползваме виртуален ком порт през УСБ? Имаме освен нашият CDC, още DFU и HID класове USB и за тях има и работещи примери, STM32F4 Discovary идва със заредено демо, в който се ползва HID клас драйвер, и то работещ в OTG – и хост, и девайс, както го включиме.
А DFU пък си е пък стандарт за флашване на фъруера, така че и той трябва да е бетон.
Ами, тъй като темата е 'Armduino Scada', заглавието предполага, че ще имаме нещо общо ис двете, и че е продължение на предишната - 'Arduino Scada'. В нея , вързахме Ардуйното с Proview Scada-та.
Сега, вчера по точно, гледам Proview са пуснали и версия за Убунто 12.04,
http://sourceforge.net/projects/proview/files/proview/proview_4.8.4-1/И в нея има Arduino UNO. И ще ползваме неговият интерфейс, иначе ще трябва да пишем и компилираме наш, а с това вече е ни стане много.
http://gitorious.org/proview/mainline/blobs/master/otherio/exp/rt/src/pwr_arduino_uno.ino----
Предполага се, че сме инсталирали Eclipse, закачи сме му плагините за ARM и сме указали компилатора и st-utils /като External Tools /.
Project->Properties->C/C++Build ->Environment->
Add -> PATH value expample: /my_compilers_top_dir/arm-2011.09/bin
В смисъл, готви сме да пишем код и компилираме. И тъй като се предполага, че ще има бая пъти да корегираме,зареждаме и тестваме кода, остава ни една важна екстра – STM32F407 притежава достатъчно RAM, за да си заредим нашата програма там и да я тестваме, без да ползваме FLASH паметта. Не че ще я съсипем, имаме 10 000 гарантирани цикли на запис, но е значително по бързо зареждането в RAM. В Еклипса такава екстра – да щракнеме 'Дебъг в РАМ' нямаме, за това трябва да ползваме лоудер скрипта, xxx.ld, и без това трябва да го имаме някъде, а най добре да си имаме два – за 'всичко в рама' и нормален. Впрочем направо давам моя от проекта, номера е флаш или ром е заменено с 'рам'.
И го посочваме,с опция -Т за линкера:
Project->Properties->C/C++Build ->Settings->ARM Sorsery Linux GCC C Linker ->General->Script file (-T)
Друго каквото трябва да направим / то зависи от конкретните библиотеки, в случая тези на STM32F4Discavary firmware / е да експортираме символи, които ще се дават в командния ред към GCC-то.
Нашата платка има външен кварцов генератор 8Mhz. Библиотеките /за stm32f4/по подразбиране слагат 25Mhz, а на нас ни трябва в командния ред -DHSE_VALUE=8000000 .
Project->Properties->Paths and Symbols->Symbols :
HSE_VALUE=8000000
STM32F4XX
USE_STDPERIPH_DRIVER
USE_USB_OTG_FS
----
Разбира се, редно е първо да се опитаме да минем тънко, без да набутаме всичките библиотеки в нашият проект. Естествено, правим една папка src, пишем файл main.c с void main(){}; и ... той се компилира.
Това е така, защото компилатора си слага неговите 'старт ап' файлове и билиотеки, нашият случай обаче не е такъв. Ще срещнем флагове като -nostdlib, който забранява включването и на старт ап на компилатора, и на код от библиотеките, или пък -nostartfines -nodefaultlibs поотделно.
Линкер скрипта , след като го включим, пръв ще даде грешка. Впрочем да не закопаваме много надълбоко , просто ни трябва горе долу да знаем кое за какво го правим и какво слагаме в 'манджата'.
Компилатора знае по подразбиране адреса на който предаде управлението след Reset, и това е грешно предположение. Защото адреса е зает. А пък и ние решихме, че ще ползваме рама първоначално. И като решихме да ползваме
https://www.das-labor.org/trac/browser/microcontroller/src-stm32f4xx/serialUSBпървият файл, който ще 'пейстнеме' e startup_stm32f4xx.s /разбира се там вече е нашето сиромашко main.c / Да не забравя, трябва да сменим разширението 's' с голямото 'S', щото Еклипса не разпознава правилно и не се компилира.
Тук се слага стек пойнтера, така че да може да викаме с call. Копират се праменливи в рама, и др неща, както и при другите процесори, нищо неочаквано. След това на
97 bl SystemInit - викаме SystemInit()
98 /* Call the application's entry point.*/
99 bl main викаме main()
пак нищо неочаквано.
Другото са векторите и най-важният – Reset Hendel който сочи началото на кода.Всичките обявени за weak, меки, така че ако ги предифинираме, компилатора няма да мрънка.
Особенното тук е друго, хардуерно, в този момент ние сме още с системен клок 16Мнц, от вътрешният тактов генератор, HSI. И първата ни работа е да превключим на истинската ни работна честота.
Тази SystemInit() се намира във файла system_stm32f4xx.c .
Там се задават и другите честоти, а и нещо важно за нас
/* Configure the Vector Table location add offset address */
#ifdef VECT_TAB_SRAM
SCB->VTOR =SRAM_BASE |VECT_TAB_OFFSET;
Vector Table Relocation in Internal SRAM
#else
SCB->VTOR = FLASH_BASE |VECT_TAB_OFFSET;
/* Vector Table Relocation in Internal FLASH */
#endif
Демек, да си добавим и 'VECT_TAB_SRAM' в експортираните символи ако ще ползваме само РАМа за кода, /таблицата с векторите се сочи от хардуерен регистер /
За да си свърши обаче работата SystemInit(), има още файлове да включим. Например ни може да подозираме, че RCC->CFGR е някякъв бит/бита от регистър, но всичко това е описано в stm32f4xx.h, главният файл който задължително трябва да включим.
Той от своя страна изисква няколко файла, които не са само за STM32F4, а за CortexM4 изобщо. core_cm4...
Тук е дефинирана и HSE_VALUE 25MHz, а и ако сме дефинирали USE_STDPERIPH_DRIVER се включва и протребителският
stm32f4xx_conf.h
кайто чрез коментиране просо на
#include заглавен файл
прави Еклипс базирани среди като CooCox например едва ли не да изглеждат като автоматични. Отваряме го и коментираме каквото не ни е нужно, това е.
STM32F407, и другите, при включване работи абсолютният минимум от периферията, почти всичко е изключено. Включително към периферията не се подава и тактова честота.
В system_stm32f4xx.c се кофигурират основните честоти, но не се пуска към устройствата.
Преди да се опитаме да включим нещо, ние му подаваме тактова честота, и то не само на него, а по целият път към него, както и на свързаните с него други.
Разбира се, можем и без библиотеките, става въпрос за включване на няколко бита от регистри. Обаче като опрем до УСБ то, нещата стават прекалено сложни, така че по добре отсега да ползваме библиотеките.
В библиотеките на периферията, за включване на честотите са написани stm32f4xx_rcc.c/stm32f4xx_rcc.h , за работа с gpio, stm32f4xx_gpio.c /stm32f4xx_gpio.h , тия определено ни трябват, слагаме ги. / и ги откоментирваме в stm32f4xx_conf.h/.
Хубаво е отсега да отделим файловете в различни поддиректории, особенно тези, който ще бъдат редактирани, /като stm32f4xx_conf.h например, хедер, ама ако го плеснем при хедерите ще ни е крайно неудобно, а пък променен с нещо файл, и сложен в кюпа може да ни подлуди!/.
Тъй като пускането и кофигурирането на дадена периферия най-често е установяване на разни битове и групи от битове в разни регистри, библиотекиге дефинират стрктури, които ние ползваме. Пример,
typedef struct
{
uint32_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured.
This parameter can be any value of @ref GPIO_pins_define */
GPIOMode_TypeDef GPIO_Mode;
.........
}GPIO_InitTypeDef;
Ние искаме да пуснем краче 4 .
Дефинираме такава структура
GPIO_InitTypeDef my_gpio_init_struct;
След това я попълваме
my_gpio_init_struct .GPIO_Pin = GPIO_Pin_4
.....
И я предаваме / по адрес / за инициализация на регистрите.
GPIO_Init(GPIOA,&my_gpio_init_struct);
Та да не чудим на тия дълги писания – просто е като попълване на таблица.