Skocz do zawartości

Nucleo kompilator "nie widzi" rejestrów uC


Majk

Pomocna odpowiedź

Witam wszystkich serdecznie na forum pierwszy raz,

analogicznie do kursu STM dostępnego na Forbot zainstalowałem sobie Nucleo, z tym, że mam inne od prezentowanego, posiadam z serii L0.

Postępowałem zgodnie z

https://forbot.pl/blog/artykuly/programowanie/kurs-stm32-3-plytka-nucleo-konfiguracja-srodowiska-id4875.

I mam problem, że jeżeli używam nazw rejestrów w programie to kompilator pokazuje błąd: Symbol could not be resolved. Szukając odpowiednich nazw rejestrów korzystam z http://www.st.com/web/en/resource/technical/document/reference_manual/DM00095744.pdf .

Nie wiem dlaczego, czyżby coś nie tak z plikiem stm32l0xx.h ?

Dodatkowo podczas instalacji w zakładce Project Firmware configuration (jest też zdjęcie takiej zakładki na stronie kursu) nie mogłem wybrać opcji Standard Peripheral Library tylko mogłem Hardware Abstraction Layer. Jest to moje pierwsze podejście do STM, wcześniej programowałem tylko AVR. Do tej pory zawsze korzystałem z operacji na rejestrach bez bibliotek, tutaj na początku chciałbym tak samo, dopiero później korzystać z tej biblioteki jednakże nic nie mogę zacząć pisać.

Proszę o pomoc w tym temacie, mam nadzieję, że Wasze doświadczenie pozwoli rozwiązać ten problem.

Pozdrawiam

Edit: Podłączyłem kolejny zestaw, dokładnie to Discovery i mam ten sam problem.

Zorientowałem się, że nigdzie na dysku nie mam plików nagłówkowych typu stm32f4xx.h więc zapewne to jest właśnie ta przyczyna. Ściągnąłem z internetu, wkleiłem ale nie działa. Teraz pytanie. W którym miejscu w katalogu powinienem doinstalować te pliki nagłówkowe? Dlaczego nie zainstalowało się razem ze środowiskiem?

Pozdrawiam

Link do komentarza
Share on other sites

Pokaż ten kod co go napisałeś, bez tego nic nie zdziałamy.

W przypadku STMów dostęp do rejestrów odbywa się poprzez struktury: Tutaj masz poradnik:

http://www.elektroda.pl/rtvforum/topic3111562.html

i przykładowy kod (ustawienie zegarów (do wyboru) dla rodziny F1:

#include "stm32f10x.h"
#include "system_stm32f10x.h"

uint32_t pll_start(uint32_t crystal, uint32_t frequency);
void flash_latency(uint32_t frequency);
extern void SystemInit(void);
void internal_clock(uint32_t frequency);

extern void gpio_pin_cfg(GPIO_TypeDef *port_ptr, uint32_t pin,
	uint32_t mode_cnf_value);

#define CLOCK_SOURCE 1 //External source == 1; Internal source == 0;

#if CLOCK_SOURCE == 1
#define CRYSTAL 8000000 //kwarc
#define CPU_FREQUENCY 72000000 //częstotliwość porządana
#endif
#if CLOCK_SOURCE == 0
#define CPU_FREQUENCY 64000000
#endif

void SystemInit(void)
{
//source http://www.freddiechopin.info/
// set all ports to input with pull-down
GPIOA->CRL = 0x88888888;
GPIOA->CRH = 0x88888888;
GPIOA->ODR = 0;
GPIOB->CRL = 0x88888888;
GPIOB->CRH = 0x88888888;
GPIOB->ODR = 0;
GPIOC->CRL = 0x88888888;
GPIOC->CRH = 0x88888888;
GPIOC->ODR = 0;
GPIOD->CRL = 0x88888888;
GPIOD->CRH = 0x88888888;
GPIOD->ODR = 0;
GPIOE->CRL = 0x88888888;
GPIOE->CRH = 0x88888888;
GPIOE->ODR = 0;

RCC->APB1ENR |= RCC_APB1ENR_PWREN;
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN
		| RCC_APB2ENR_IOPDEN | RCC_APB2ENR_AFIOEN; //enable PORTS (A,B,C,D) and AFIO

#if CLOCK_SOURCE == 1
pll_start(CRYSTAL,CPU_FREQUENCY);
#endif
#if CLOCK_SOURCE == 0
internal_clock(CPU_FREQUENCY);
#endif

AFIO->MAPR |= (1<<25) | (1<<1); //JTAG disable
}

void flash_latency(uint32_t frequency)
{
//source http://www.freddiechopin.info/
uint32_t wait_states;

if (frequency < 24000000ul)
	wait_states = 0; //0 wait states for core speed below 24MHz
else if (frequency < 48000000ul)
	wait_states = 1; //1 wait state for core speed between 24MHz and 48MHz
else
	wait_states = 2; //2 wait states for core speed over 48MHz

FLASH->ACR |= wait_states;				// set the latency
}

/*------------------------------------------------------------------------*//**
*
* Configure and enable PLL to achieve some frequency with some crystal.
* Before the speed change Flash latency is configured via flash_latency(). PLL
* parameter mul is based on both function parameters. The PLL is set up,
* started and connected. APB1 clock ratio is set to 1:2 (max freq = 36MHz)
*
* \param [in] crystal is the frequency of the crystal resonator connected to the
* STM32F103RB
* \param [in] frequency is the desired target frequency after enabling the PLL
*
* \return real frequency that was set
*
* Function flash_latency, pll_start, SystemInit from http://www.freddiechopin.info/ moded by ps19
*/

uint32_t pll_start(uint32_t crystal, uint32_t frequency)
{
//source http://www.freddiechopin.info/
uint32_t mul;

RCC->CR |= RCC_CR_HSEON; //enable HSE clock
flash_latency(frequency); //configure Flash latency for desired frequency

mul = frequency / crystal; // PLL multiplier calculation
if (mul > 16) mul = 16; // max PLL multiplier is 16
frequency = crystal * mul;

RCC->CFGR |= ((mul - 2) << 18) | RCC_CFGR_PLLSRC | RCC_CFGR_PPRE1_DIV2;	//configuration of PLL: HSE x (mul), APB1 clk = /2

while (!((RCC->CR) & RCC_CR_HSERDY));//wait for stable clock

RCC->CR |= RCC_CR_PLLON; //enable PLL
while (!((RCC->CR) & RCC_CR_PLLRDY) ); //wait for PLL lock

RCC->CFGR |= RCC_CFGR_SW_PLL; //change SYSCLK to PLL
while (((RCC->CFGR) & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); //wait for switch

return frequency;
}

void internal_clock(uint32_t frequency)
{
//Written by ps19
uint32_t mul;

RCC->CR |= RCC_CR_CSSON | RCC_CR_HSION;

flash_latency(frequency);// configure Flash latency for desired frequency

mul = frequency / 8000000UL; // PLL multiplier calculation
if (mul > 16) mul = 16;	// max PLL multiplier is 16
frequency = 8000000UL * mul;

RCC->CFGR &= ~RCC_CFGR_PLLSRC; // HSI/2 as source for PLL
RCC->CFGR |= ((mul - 2) << 18) | RCC_CFGR_PPRE1_DIV2; //APB1/2
while (!((RCC->CR) & RCC_CR_HSIRDY)); //wait for stable HSI clock
RCC->CR |= RCC_CR_PLLON; //enable PLL
while (!((RCC->CR) & RCC_CR_PLLRDY)); //wait for PLL lock
RCC->CFGR |= RCC_CFGR_SW_PLL; //change SYSCLK to PLL
while (((RCC->CFGR) & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); //Wait until PLL will be work as clock source
}

void gpio_pin_cfg(GPIO_TypeDef *port_ptr, uint32_t pin, uint32_t mode_cnf_value)
{
//source http://www.freddiechopin.info/
volatile uint32_t *cr_ptr;
uint32_t cr_value;

cr_ptr = &port_ptr->CRL;	//configuration of pins [0,7] is in CRL

if (pin >= 8) 	//is pin in [8; 15]?
{				//configuration of pins [8,15] is in CRH
	cr_ptr++;	//advance to next struct element CRL -> CRH
	pin -= 8;	//crop the pin number
}

cr_value = *cr_ptr;	//localize the CRL / CRH value

cr_value &= ~((3 | 3<<2) << (pin * 4));	//clear the MODE and CNF fields (now that pin is an analog input)
cr_value |= (mode_cnf_value << (pin * 4));	//save new MODE and CNF value for desired pin

*cr_ptr = cr_value;	//save localized value to CRL / CRL
}

Jak chciałbyś z tego korzystać to nigdzie nie wywołujesz funkcji - robi to za ciebie plik startowy z rozszerzeniem "s". Wybór zegara to zmiana w 0/1 w tej definicji

#define CLOCK_SOURCE 1 //External source == 1; Internal source == 0;
Link do komentarza
Share on other sites

Dzięki.

Tak więc po kolei.

Teraz podpiąłem sobie Evalboard Discovery, wgrałem sobie plikz Library dla serii F4 Standrd Pheripheral Library.

W screenie pokazuję jak wygląda mój projekt, drzewo po lewej stronie. Widać, że jest załączony plik stm32f4xx.h, jest po lewo StdPeriph_Driver gdzie w inc są wszystkie pliki typu .h.

Ja struktur nie używam, tylko operuje na rejestrach co i tak nie ma znaczenia gdyż i w jednym i w drugim przypadku powinno działać.

Stąd biorę nazwy rejestrów:

http://www.st.com/web/en/resource/technical/document/reference_manual/DM00096844.pdf

Gdy teraz w main chcę sobie coś spisać do rejestru, czyli napiszę np. : RCC_AHB1ENR = 0x0001 to jest błąd następujący: Symbol could not be resolved

Edit:

Wgrałem taki poniższy program, przkompilował się, nie ma żadnych error.

/**

******************************************************************************

* @file main.c

* @author Ac6

* @version V1.0

* @date 01-December-2013

* @brief Default main function.

******************************************************************************

*/

#include "stm32f4xx.h"

#include "stm32f4_discovery.h"

#include "stm32f4xx_gpio.h"

#include "stm32f4xx_rcc.h"

#include "misc.h"

void main (void)

{

int a=0;

int b=0;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); //Port D clock enable

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //Port D clock enable

GPIO_InitTypeDef GPIO_InitStruct; //Init struktury

GPIO_StructInit(&GPIO_InitStruct);

GPIO_InitStruct.GPIO_Pin=GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; //Init pinów, które chce używać

GPIO_InitStruct.GPIO_Mode=GPIO_Mode_OUT; //Linie 12-15 jako wyjścia

GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz; //Prędkość linii 50MHz

GPIO_Init(GPIOD, &GPIO_InitStruct); //Init struktury portu D

GPIO_InitTypeDef GPIO_InitStructe; //Init struktury

GPIO_StructInit(&GPIO_InitStructe);

GPIO_InitStructe.GPIO_Pin=GPIO_Pin_0; //Init pinów, które chce używać

GPIO_InitStructe.GPIO_Mode=GPIO_Mode_IN; //Linie 12-15 jako wyjścia

GPIO_InitStructe.GPIO_Speed=GPIO_Speed_2MHz; //Prędkość linii 50MHz

GPIO_Init(GPIOA, &GPIO_InitStructe); //Init struktury portu D

//GPIO_SetBits(GPIOD, GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);

//for (i=0;1

 

while(1)

{

 

if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==Bit_SET)

{

a=a+1;

}

//{ GPIO_SetBits(GPIOD, GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);}

//GPIO_ResetBits(GPIOD, GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);

else a=a+0;

if (a>=100)

{

GPIO_SetBits(GPIOD, GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);

for (b=0;b<60000;b++);

for (b=0;b<60000;b++);

for (b=0;b<60000;b++);

for (b=0;b<60000;b++);

GPIO_ResetBits(GPIOD, GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);

a=0;

}

else a=a+0;

}

}

 

Z tym, że ja nie chcę korzystać ze struktur tylko chcę operować na rejestrach.

Pomysł co jest nie tak?

 

__________

Komentarz dodany przez: Treker

Programy umieszczamy w tagach , proszę to poprawić.

Link do komentarza
Share on other sites

Tak jak napisał ps19, w przypadku Cortex-ów, nie tylko STM32 nie używa się rejestrów jak dawniej. Zamiast tego są struktury, więc można napisać:

RCC->AHB1ENR = 0x0001

Nie jest to biblioteka StdPeriph, tylko CMSIS - dostarczana przez ARM-a.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Wstawiłem

RCC->AHB1ENR = 0x0001;

tak jak napisałeś i błędów nie ma.

Dziękuję.

Prosiłbym jeszcze o wyjaśnienia.

Kiedyś sporo pisałem na AVR, kilka lat temu i większość rzeczy pisałem w Asemblerze, dlatego jestem bardzo przyzwyczajony do pracy na rejestrach.

Teraz już się tego nie praktykuje? STM programuje się tylko w postaci struktur?

A czy taki zapis RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

według kursu to nie jest korzystanie z StdPeriph ? Napisane jest, że kurs właśnie z tego korzysta.

Co oznacza zapis RCC-> ? I czy wszystko już tak należy programować? Z każdym rejestrem tak postępować?

Pozdrawiam

Link do komentarza
Share on other sites

To nie jest kwestia ST, ale Arm-a. To w sumie tylko inny zapis, ale dużo wygodniejszy. Oczywiście wszystkie rejestry są "normalnie" widoczne w przestrzeni adresowej procesora, więc można samemu zdefiniować rejestry i działać po staremu.

Natomiast ARM dostarcza nagłówki oparte o strukturach - nic na to nie poradzimy.

Ostateczny efekt jest absulutnie ten sam. Po prostu pola struktur wypadają w tych miejscach, godzie są rejestry. Różnica jest tylko w zapisie, ale jest dużo bardziej elastyczna - wreszcie można pozbyć się niekończących #define na początku pliku.

Link do komentarza
Share on other sites

Czyli mam rozumieć, że korzystam ze struktur i tak ma po prostu być?

A czy taki zapis RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

według kursu to nie jest korzystanie z StdPeriph ? Napisane jest, że kurs właśnie z tego korzysta.

Pozdrawiam

Link do komentarza
Share on other sites

RCC_AHB1PeriphClockCmd już korzysta z StdPeriph. Ale samo RCC jest w CMSIS. Nie wszystkie struktury są ze StdPeriph.

Nie musisz korzystać z CMSIS, ale wtedy kompilator nie będzie miał adresów rejestrów - musiałbyś sam pliki nagłówkowe napisać (albo odszukać napisane przez kogoś).

Niestety ale pisanie na AVR różni się od tego co teraz jest popularne. Z drugiej strony STM32F4 to rakieta w porównaniu z AVR, więc ciężko się dziwić że i metody programowania uległy zmianie.

Niby można na rejestrach i w asemblerze napisać własny stos do obsługi TCP/IP - tylko po co?

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Gość
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.