0

I am programming STM32L152 that connected to my PC via UART.

I use GNU Tools ARM Embedded version 6.2 2016q4.

Compiler control string:

-mcpu=cortex-m3; -mthumb; -Wall; -ffunction-sections; -g; -O0; -DSTM32L152RB; -DSTM32L1XX_MD; -I.; 

Linker control string

-mcpu=cortex-m3; -mthumb; -g; -Map=mufs_stm32l152.map; -O0; --gc-sections; -L${linkdir}; -T${linkdir}/arm-gcc-link.ld;  

In fact, it default value for Coocox IDE, I don't change it.

My code:

int main(void)
{
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    //PD6  -> RX UART.
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_8| GPIO_Pin_7| GPIO_Pin_6;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    //enable pin
    GPIO_SetBits(GPIOB, GPIO_Pin_9);

    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
    USART1->CR1 |= USART_CR1_UE;
    USART1->CR1 &= ~USART_CR1_M;
    USART1->CR2 &= ~USART_CR2_STOP; 
    USART1->BRR = 139; //baud rate 115200 HSI = 16 МГц
    USART1->CR1 |= USART_CR1_TE;
    USART1->CR1 |= USART_CR1_RE;

    USART_ITConfig(USART1,USART_IT_RXNE, ENABLE);
    NVIC_EnableIRQ(USART1_IRQn);

    while(1)
    {}

}

char hh = 'G';
void USART1_IRQHandler(void)
{
    if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE))
    {
        char ch = USART_ReceiveData(USART1);
        USART_SendData(USART1, hh);
        if(ch == 'A')
            GPIO_ToggleBits(GPIOB, GPIO_Pin_8);

    }
}

When I pressing keys on my PC I expect to see in console something like this

GGGGGGGGGGGG

But instead I getting just some garbage. Sometimes it some letter sometimes it is unprintable character. And it not changing until I edit my code and recompile it. I can assign value and it work. It is look like global variable hh has no her initial value. Furthermore, if I mark it as constant it start working as expected.

What am I doing wrong?

Konstantin T.
  • 994
  • 8
  • 22
  • 2
    It is the tool-chain dependent C runtime startup that is responsible for static initialisation - some have an option not to do it at all. What tool-chain are you using? You have omitted that vital information. Also can you reproduce the problem with a simpler example. i.e just a global initialised, and then inspecting it in your debugger rather then indirectly inferring via the serial output - to discount any of the other code corrupting your global for example. If it works when you assign the value, it would be useful to include that version of the code rather than merely _describing_ it. – Clifford Apr 17 '17 at 10:07
  • Do you see garbage only when you press a key?If yes, it generally happen when the UART is not initialized correctly on the host (baudrate, flow control, data bits, stop bits) – OlivierM Apr 17 '17 at 10:17
  • @Clifford thankyou for reply! I have added information about my toolchain. And I have checked variable just in debugger, it is staying not initialized at start of main function. – Konstantin T. Apr 17 '17 at 11:44
  • @OlivierM Please, look my comment for Clifford. Problem not in UART. If I assign some value to global variable it work well. – Konstantin T. Apr 17 '17 at 11:48
  • Without knowing your toolchain I cannot go into details. Did you study the layout and attributes of sections setup for the linker? E.g. for my toolchain I would identify and study a file "something.ld". And for explicitly initialised global variables I'd expect a data section and something like a data.rom section, from which values are copied to the memory locations which represent the variables. Then those two section need to have several appropriate attributes set. They in turn should be handlded by "CRT", the C runtime environment, just before starting main(). – Yunnosch Apr 17 '17 at 13:08
  • Does your project use startup_ARMCM3.S or crt0.o for its run-time initialisation? Either way one or the other is responsible for the C run-time start up, including global initialisation. The former being provided as source code can be modified to defeat or break default initialisation. – Clifford Apr 17 '17 at 15:56
  • Can you post your linker script.?. There are a couple of symbols, sdata and edata I think which are used to mark the start address and end address of initialised data. If you variables are not stored between these two addresses then they will not get initialised. That said it does also depend of the startup code as Clifford said, so they may or may not be required. – Realtime Rik Apr 17 '17 at 19:38
  • @Clifford Thankyou! Your help have given me the right direction. I have added the answer. If you can give more suitable explanation of my problem, please feel free. – Konstantin T. Apr 18 '17 at 07:08

1 Answers1

0

In CooCox IDE (v1.7.6) initialization of global variables (data segment in fact) perform in startup_stmxxxxxx_md.c file in Default_Reset_Handler function. And I don't know what the point of this, but in my case code which perform data segment initialization as well as bss zero-filling, was commented out by default. For properly variables initialization you should uncomment this code.

Clifford
  • 88,407
  • 13
  • 85
  • 165
Konstantin T.
  • 994
  • 8
  • 22
  • The startup_stmxxxxxx_md.c code is originally provided by ST (check the boiler-plate/copyright comment in your version to confirm). In the original code it is not commented out - perhaps it was done by someone in your team, copied from another project or even done by coocox.org, but certainly not ST. My advice would be to get the latest device support code form ST - it is included in their standard peripheral library examples. – Clifford Apr 18 '17 at 10:15
  • Isn't this part of the C lib that you are using? There should be a C library entry point that is called as part of the reset_handler that will initialise things like the RW data section, BSS section and heap. – Flip Apr 19 '17 at 11:40
  • @Flip No. As far as I can see, it is not a part of C lib. It just per byte copying data from FLASH to SRAM. – Konstantin T. Apr 19 '17 at 12:41
  • @KonstantinT, Yes, that is all that C really needs. That and zeroing the BSS section. But there are usually library routines that do this or that you have to manually provide. In ARMCC it is the scatter loading part that the tool chain inserts behind the scenes. In GCC I believe you may have to manually provide that, though there are examples on the web. With C++ you'd also need to call the constructors for static objects. – Flip Apr 19 '17 at 12:57