Skocz do zawartości

Programowanie stm32 na rejestrach


faustin

Pomocna odpowiedź

Witam mam pytanie bo w kursie do stm32 w tej wersji gdzie jest używana płytka f103 wy uczycie programować z wykorzystaniem HALA a czy w tym środowisku takim jak systemworbenchforstm32? Lub nawet cubeide dałoby się programować na samych rejestrach ? A jeśli nie to w jakim ?

Link do komentarza
Share on other sites

17 minut temu, faustin napisał:

Witam mam pytanie bo w kursie do stm32 w tej wersji gdzie jest używana płytka f103 wy uczycie programować z wykorzystaniem HALA a czy w tym środowisku takim jak systemworbenchforstm32? Lub nawet cubeide dałoby się programować na samych rejestrach ? A jeśli nie to w jakim ?

Tak, bo przecież HAL odwołuje się do rejestrów (to tylko taka nakładka, która ułatwia pracę)

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

napisałam kod na rejestrach , ale nie moze sie skompliowac bo wyskakuje jakis bład , dodam , ze próbowałam konfigurowac srodowisko tak jak było to przedstawione w tej intrukcji tutaj https://www.elektroda.pl/rtvforum/topic3742356.html, wiec co jest zle?


#include "stm32f10xb.h"


void SysTick_Handler(void)
{GPIOC->ODR ^= GPIO_ODR_ODR13;// toogle LED
}
int main(void){
	RCC->APB2ENR = RCC_APB2ENR_IOPCEN;
	GPIOC->CRH |= GPIO_CRH_MODE13;
	GPIOC->CRH &= ~GPIO_CRH_CNF13_0;
	SysTick_Config(8000000*0.5);
	while(1){}
}

 

stm322.PNG

Link do komentarza
Share on other sites

Czy jesteś pewna, że ta podkreślona na żółto biblioteka, która wyrzuca błąd powinna mieć zastosowanie do wybranego przez Ciebie mikrokontrolera? Bo nie widzę listy plików nagłówkowych z folderu Inc ani listy błędów, więc obstawiam to jako przyczynę...

Link do komentarza
Share on other sites

Dnia 4.05.2022 o 18:11, faustin napisał:

Witam mam pytanie bo w kursie do stm32 w tej wersji gdzie jest używana płytka f103 wy uczycie programować z wykorzystaniem HALA a czy w tym środowisku takim jak systemworbenchforstm32? Lub nawet cubeide dałoby się programować na samych rejestrach ? A jeśli nie to w jakim ?

Witam, 

@faustin Prawdopodobnie myli Pani pojęcia środowiska (IDE w tym przypadku) i czynności programowania na rejestrach...
Otóż przykładowo to co Pani zrobiła:
 

    RCC->APB2ENR |= TIM1EN_WITH_IOPCEN;

To właśnie programowała Pani po rejestrze i może to Pani zrobić w każdym IDE czy to Keil, EWARM, SWAC6, CUBE_IDE, czy nawet bez IDE w commandline... natomiast: 

SysTick_Config(800000*0.5);

To już Pani zainkludowała do kodu funkcję z pliku core_cm3.h. Dlaczego piszę że Pani zainkludowała tą funkcję, a nie wywołała - ponieważ jest to funkcja z atrybutami STATIC INLINE, co oznacza że kod tej funkcji nie jest wywoływany jako callbac, tylko bezpośrednio dołączany w miejscu jej "wywołania", czyli SysTick_Config(800000*0.5); zostało zamienione na kod tej funkcji. To daje oszczędność czasową, która podczas inicjalizacji jest może mało istotna, lecz także daje oszczędność miejsca w ROM pomijając odkładanie i zdejmowanie rejestrów na stos.
 

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)

A co zrobiła ta funkcja? Programowała po rejestrach także, ale to już nie Pani bezpośrednio.

#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)

/**
  \brief   System Tick Configuration
  \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
           Counter is in free running mode to generate periodic interrupts.
  \param [in]  ticks  Number of ticks between two interrupts.
  \return          0  Function succeeded.
  \return          1  Function failed.
  \note    When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
           function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
           must contain a vendor-specific implementation of this function.
 */
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
  {
    return (1UL);                                                   /* Reload value impossible */
  }

  SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
  return (0UL);                                                     /* Function successful */
}

#endif

/*@} end of CMSIS_Core_SysTickFunctions */


 


W kwestii błędu - nie widać co to za błąd, widać że są dwa i widać że ikona błędu jest przy pliku nagłówkowym "stm32f10xb.h". 

Przy okazji zwracam uwagę że projekt, który testowo uruchomiłem do prezentacji tutaj jest naprawdę "odchudzony" i nie zawiera jak standardowo całego śmietnika niepotrzebnych i nieużywanych plików nagłówkowych i bibliotek (także jest bez HAL'a) - po lewej stronie zaznaczyłem pliki projektu.

files_and_error.thumb.png.d2d4f71b9dbb1b90449d24b610fa321f.png

Wracając do błędów... Aby je pokazać  należałoby skopiować i wkleić to, co "wypluła" Pani konsola CUBE_IDE jak np. poniżej:

Cytat

 

18:37:59 **** Incremental Build of configuration Debug for project SYSTICK_IRQ ****
make -j8 all 
arm-none-eabi-gcc "../Core/Src/main.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DSTM32F103xB -c -I"C:/Users/BOLO/STM32CubeIDE/workspace_1.8.0/REGISTRY_PROGRAMMING/SYSTICK_IRQ/CMSIS/Include" -I"C:/Users/BOLO/STM32CubeIDE/workspace_1.8.0/REGISTRY_PROGRAMMING/SYSTICK_IRQ/Core/Inc" -Os -ffunction-sections -fdata-sections -Wall -fstack-usage -MMD -MP -MF"Core/Src/main.d" -MT"Core/Src/main.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Core/Src/main.o"
../Core/Src/main.c: In function 'SysTick_Handler':
../Core/Src/main.c:29:1: error: expected ';' before '}' token
   29 | }
      | ^
make: *** [Core/Src/subdir.mk:19: Core/Src/main.o] Error 1
"make -j8 all" terminated with exit code 2. Build might be incomplete.

18:38:00 Build Failed. 2 errors, 0 warnings. (took 246ms)

 


Trudno powiedzieć czy np. nie dodała Pani ścieżki include do tego pliku, czy samego pliku Pani nie dodała, czy plik jest, ale brakuje definicji dla preprocesora
STM32F103xB 
 w miejscu jak na załączonym poniżej obrazku.  Co konkretnie robi ta definicja nie wiem, bo jestem w STM32 oraz w C bardzo początkujący, więc nie wyjaśnię tego.

symbols.thumb.png.33af5a8cd8f0857697eccc47ff12a13d.png

Z obrazków domniemuję że próbuje Pani w blupilu blinkać diodą co pół sekundy w przerwaniu systika, i wszystko się zgadza.

/**
 ***************************
 * @file       : main.c
 ***************************
 */
#include "stm32f103xb.h"

/******************************************************
 * This program use and enable SysTick
 * and blinking LED in the IRQ subroutine
 ******************************************************/

int main(void)
{

    RCC->APB2ENR  |= RCC_APB2ENR_IOPCEN;
    GPIOC->CRH    |= GPIO_CRH_MODE13;
    GPIOC->CRH    &= ~GPIO_CRH_CNF13_0;
    SysTick_Config(8000000 *0.5);


    while(1){}
}
/****************************
 *    IRQ service routine
 ****************************/
void SysTick_Handler(void)
{
    GPIOC->ODR ^= GPIO_ODR_ODR13;
}
/************************************************/

 

Program można uprościć i nieużywać SysTick'a i przerwania, poprzez zliczanie wartości zmiennej w pętli for();

/**
 ***************************
 * @file       : main.c
 ***************************
 */
#include "stm32f103xb.h"

/******************************************************
 * This program just
 * and blinking LED in the IRQ subroutine
 ******************************************************/

int main(void)
{
    RCC->APB2ENR  |= RCC_APB2ENR_IOPCEN;
    GPIOC->CRH    |= GPIO_CRH_MODE13;
    GPIOC->CRH    &= ~GPIO_CRH_CNF13_0;

    while(1)
    {
      for(uint32_t volatile i = 500000; i  != 0 ; i--);
      GPIOC->ODR ^= GPIO_ODR_ODR13;
    }
}

 

Jako ciekawostkę załączam linki  do moich programów na githubie

 

https://github.com/wegi1/BLUE_PILL_BLINK_IN_ASM_56_BYTES

https://github.com/wegi1/BLUE_PILL_BLINK_LED_RAM_EXECUTE/

https://github.com/wegi1/STM32F103C8T6_BLUE_PILL_MSD_RAMDISK

 

Powyższe programy realizują:

 

  1.  Mruganie diodą na blupilu w assemblerze rozmiar kodu 56 bajtów
  2. To samo co w punkcie 1, z tym że program co każdy reset naprzemiennie program wykonuje się we FLASH'u, albo w RAM'ie.
  3. Blue Pill jako MSD RAMDISK na USB - to tak naprawdę sztuka dla sztuki, ale jest 🙂

 

Przykład w assemblerze dla mrugania diodą 56 bajtów: 

// file startup_stm32f10x_md.S 

/****************************************************
* A SIMPLE BLINK LED ON THE BLUE PILL STM32F103C8T6 *
* WITHOUT ANY CMSIS, HEADERS AND OTHER MAGIC FILES  *
*****************************************************/

/********************/
/* STM32 DEVICE IS: */
/*  STM32F103C8T6   */
/********************/

/****************************************************************/
/* BLUE PILL LED IS EMBEDDED ON ---->PC 13<----  = GPIOC->PIN13 */
/****************************************************************/

#define RCC_APB2ENR                              0x40021018
#define RCC_APB2ENR_IOPCEN                       0x10

#define GPIOC_CRH                                0x40011004
#define GPIOC_CRH_VALUE                          0x44144444

#define GPIOC_ODR_OFFSET_FROM_CRH                0x08
#define GPIOC_ODR_ODR13                           0x2000

#define TOP_OF_STACK                             0x20005000
/*
***************************************************************
*** just done bellowed main function C routine in assembler ***
***************************************************************
int main(void)
{
    RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
    GPIOC->CRH = 0x44144444;
    uint32_t delay;
    while(1)
    {
        GPIOC->ODR ^= GPIO_ODR_ODR13;
        for(delay = 100000; 0; delay--) {};
    }
}
*/


    .syntax unified
    .cpu cortex-m3

    .section .isr_vector

    .long    TOP_OF_STACK
    .long    __Reset_Handler         /* Reset Handler */
    .thumb_func
    .text


__Reset_Handler:
/*********************************************/
/*
//RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
*/

    ldr    r2, =RCC_APB2ENR
    ldr    r3, [r2]
    orr.w    r3, r3, RCC_APB2ENR_IOPCEN
    str    r3, [r2]
/********************************************/
/*
//GPIOC->CRH = GPIOC_CRH_VALUE;
*/

    ldr    r1, =GPIOC_CRH_VALUE
    ldr    r2, =GPIOC_CRH
    str    r1, [r2]
/*******************************************/

/*
// while(1)
*/
//{
/*******************************************/
/*
//GPIOC->ODR ^= GPIO_ODR_ODR13;
*/
blink:

    ldr    r3, [r2, GPIOC_ODR_OFFSET_FROM_CRH]
    eor.w    r3, r3, GPIOC_ODR_ODR13
    str    r3, [r2, GPIOC_ODR_OFFSET_FROM_CRH]
/********************************************/
/*
//for(uint32_t delay = 500000; 0 ; delay--) {};
*/

    ldr    r3, =500000
count_delay:
    subs    r3, #1
    bne count_delay

    b  blink

//} /* end while(1){} */
    .end

 

Aby program chciał się skompilować i działać, tak wygląda dla niego plik linkera:

/*------------------------------------------------------------------------------
 *      Linker script for running in internal FLASH on the STM32F103C8
 *----------------------------------------------------------------------------*/

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)

/* Memory Spaces Definitions */
MEMORY
{
    ROM  (rx) : ORIGIN = 0x08000000, LENGTH = 64K
    RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
}


SECTIONS
{
    .text :
    {
        KEEP(*(.isr_vector))
        *(.text*)
        
    } > ROM
}

/*------------------------------------------------------------------------------
 *      Linker script EOT
 *----------------------------------------------------------------------------*/

 

Jeszcze większą ciekawostką dla mnie było gdy deassemblując wygenerowany kod projektów zdałem sobie sprawę, że korzystanie z odwołania, które kompilator najczęściej używa dla ładowania adresów, wartości zmiennych itp jest pobieranie wartości w oparciu o rejest licznika programu [PC] czyli program counter:

ldr r0, [pc + offset]

 

(gdzie offset jest wskazaniem ile bajtów od aktualnie wykonywanej instrukcji procesora jest dana do pobrania)

 

To praktycznie czyni kod" bardzo relokowalnym", że się tak wyrażę ponieważ jeżeli przepisze się go do RAM'u to oczywiście zmieni się wartość PC (adres wykonywanej aktualnie instrukcji procesora), ale offset pozostanie taki sam (!!!). Po drobnych korektach ulepiłem coś co potrafiło się przepisać z ROM do RAM i się tam uruchomić. Co ciekawe pętla opóźniająca wykonuje się tak naprawdę w RAM DWA razy dłużej, aniżeli we FLASH'u (!):

/******************************************************
 * @file      STARTUP_STM32F103C8TX
 *******************************************************/

// A FEW DEFINITIONS


#define TOP_OF_STACK              0x20000700
#define CHECK_BYTE                0x20000710

#define RCC_APB2_ADDR             0x40021018
#define ENABLE_GPIOC_VALUE        0x10

#define GPIOC_CRH                 0x40011004
#define GPIOC_CRH_VALUE           0x44144444

#define GPIOC_ODR_OFFSET_FROM_CRH 0x08

#define BIT_13_VALUE              (1UL << 13)

#define ROM_START                 0x08000000
#define RAM_START                 0x20000000
#define PROGRAM_LENGTH            END_LOOP - ROM_START

#define RAMCODE2                  ram_code - ROM_START
#define RAM_CODE_2                RAMCODE2 + RAM_START +1 // thumb MODE --> +1


#define COUNTER_DELAY_OFFSET      0x08
#define RCC_ADDR_OFFSET           0x0C
#define RAM_START_OFFSET          0x10
#define PROGRAM_LENGTH_OFFSET     0x14
#define RAM_CODE_OFFSET           0x18
#define ROM_START_OFFSET          0x1C
#define CHECK_BYTE_OFFSET         0x20
#define GPIOC_CRH_VALUE_OFFSET    0x24
#define GPIOC_CRH_OFFSET          0x28
/******************************************************************************
*  VECTORS
******************************************************************************/
// ARM ASSEMBLER ATTRIBUTES
.syntax unified
.cpu cortex-m4
/*********************************************************************
*  VECTORS SECTION START
**********************************************************************/
  .section .vector_table

  .word TOP_OF_STACK            // DOESN'T MATTER WE DON'T USE STACK HERE
  .word Reset_Handler           // RESET HANDLER VECTOR

  .word 400000                  // counter delay value for ROM execute
  .word RCC_APB2_ADDR           // BASE ADDRESS OF RCC 0x40021018
  .word RAM_START               // 0x20000000
  .word PROGRAM_LENGTH          // length of program
  .word RAM_CODE_2              // start addres in ram
  .word ROM_START               // = 0x08000000
  .word CHECK_BYTE              // = 0x20000710 indicator to run program after reset in ROM or RAM
  .word GPIOC_CRH_VALUE         // 0x44144444 initial value GPIOC->CRH
  .word GPIOC_CRH               // 0x40011004 GPIOC->CRH ADDRESS
/*********************************************************************
*  VECTORS END
**********************************************************************/

  .thumb_func
  .text
/***********************************************************
* RESET CODE - BLINKING LED PC13
********************************************************************/


Reset_Handler:

  mov  r7, 0x08000000                          // * [r7 = 0x08000000] --> [VECTOR TABLE START ADDRESS]

  // init values in registers to copy data from FLASH into RAM
  ldr  r0, [R7, #RAM_START_OFFSET]             // * [r0 = 0x20000000] --> = RAM_START
  ldr  r1, [R7, #PROGRAM_LENGTH_OFFSET]        // * how many bytes to copy into RAM
  ldr  r2, [R7, #ROM_START_OFFSET]             // r2 = 0x08000000 --> start of ROM
  movs r3, #0                                  // r3 = 0 = initial value to count copied bytes


Copy_Data:
  ldr  r4, [r2, r3]                             // copy 32bit word from ROM
  str  r4, [r0, r3]                             // and store this 32bit word into RAM
  adds r3, r3, #4                               // count copied bytes
  cmp  r3, r1                                   // compare copied bytes with length of program
  bcc  Copy_Data                                // test

  ldr  r4, [r7, #COUNTER_DELAY_OFFSET]          // r4 = 400000
  lsr  r4, 2                                    // r4 = 400000/4 = 100000
  str  r4, [r0, #COUNTER_DELAY_OFFSET]          // store in RAM lower value for faster led blinking


  ldr  r5, [R0, #RAM_CODE_OFFSET]               // R5 = start addres in RAM

  ldr  r4, [R2, #CHECK_BYTE_OFFSET]             // our control byte address
  ldr  r3, [r4]                                 // get our control byte into r3 from RAM
  eor  r3, #0x01                                // toggle lowest bit
  ands r3, #0x01                                // check lowest bit to execute place
  str  r3, [r4]                                 // store our check byte after change

  beq  ram_code                                 // if 0 go to flash execute, if 1 = RAM execute

  mov  pc, r5                                   // GO TO RAM EXECUTE !!!

//****************************************************************************************************/

/* 1. ENABLE RCC CLOCK FOR GPIOC (0x40021018 ADDRESS) */
/* 2. SET REGISTER R1 AS GPIOC->CRH VALUE   (0x44144444  VALUE) */
/* 3. SET REGISTER R0 AS GPIOC->CRH ADDRESS (0x40011004  ADDRESS) AND STORE INTO GPIOC_CRH */
/* 4. TOGGLE BIT 13 IN GPIOC->ODR REGISTER  (0x4001100C  ADDRESS)  */
/* 5. A SMALL DELAY LOOP */
/* 6. GO BACK TO TOGGLE BIT 13 IN GPIOC->ODR REGISTER */


ram_code:
  mov  r7, pc                                  // check program counter where is - in RAM or ROM?
  and r7, 0x28000000                           // and make ADDRES to DATA_TABLES now we got
                                               // R7 = RAM or ROM START ADDRESS 0x20000000 or 0x08000000

//**********************************************************************************************************

/* 1. ENABLE RCC CLOCK FOR GPIOC (0x40023830 ADDRESS) */
  LDR    R0, [R7, #RCC_ADDR_OFFSET]           // R0 = ROM_OR_RAM_BASE_ADDRES (R7 = 0x08000000 or 0x20000000)  12 = RCC_APB2_BASE_ADDRES
  LDR    R1, [R0]                             // R1 = RCC_APB2_EN ADDRESS = (0x40021018)
  ORR.W  R1,  R1, #ENABLE_GPIOC_VALUE         // ENABLE GPIOC
  STR    R1, [R0]                             // STORE NEW VALUE WITH GPIOC RUNNING CLK


/* 2. SET REGISTER R1 AS GPIOC->CRH VALUE   (0x44144444  INITIAL VALUE) */
/* 3. SET REGISTER R0 AS GPIOC->CRH ADDRESS (0x40011004  BASE_ADDRESS) AND STORE INTO GPIOC->CRH */
  LDR    R1, [R7, #GPIOC_CRH_VALUE_OFFSET]    // R1 = (0x44144444  INITIAL VALUE
  LDR    R0, [r7, #GPIOC_CRH_OFFSET]          // R0 = (0x40011004  BASE_ADDRESS)
  STR    R1, [R0]                             // STORE INITIAL VALUE INTO GPIOC->CRH


  //LDR    R1, [R0, #GPIOC_ODR_REG_OFFSET]    // UNNEECESSARY

LOOP01:
/* 4. TOGGLE BIT 13 IN GPIOC->ODR REGISTER (0x4001100C  ADDRESS)  */
  EOR.W  R1,  R1,BIT_13_VALUE                 // TOGGLE BIT 13 IN R1
  STR    R1, [R0, #GPIOC_ODR_OFFSET_FROM_CRH] // STORE VALUE WITH TOGGLED BIT 13 INTO GPIOC->ODR_REGISTER

  LDR R2, [R7, #COUNTER_DELAY_OFFSET]         // SIMPLE DELAY LOOP  R2 = 400000 or 400000/4


LOOP02:

/* 5. A SMALL DELAY LOOP */
  SUBS   R2,#1                                // DECREMENT REGISTER WITH FLAGS UPDATE (ZERO FLAG WE USED)
  BNE    LOOP02                               // REGISTER NOT 0? SO STILL DECREMENT

/* 6. GO BACK TO TOGGLE BIT 13 IN GPIOC->ODR REGISTER */
  BEQ    LOOP01
END_LOOP:                         // DELAY END GO BACK TO BLINKING LOOP
/*****END OF FILE****/

 

Plik linkera pozostaje praktycznie taki sam jak poprzednio (z wyjątkiem nazwy sekcji dla tablicy wektorów).

 

W załączniku dodałem działający  program spod STM32CUBE_IDE, który w przerwaniu SysTick'a mruga diodą.

 

 

 

 

 

 

 

 

SYSTICK_IRQ.ZIP

Edytowano przez virtualny
  • Lubię! 1
  • Pomogłeś! 1
Link do komentarza
Share on other sites

(edytowany)

Dziękuje bardzo jestem pod  ogromnym wrażeniem. Programowanie na rejestrach jednak robię z przymusu bo o wiele lepiej jest na HALU ale i tak bardzo dziękuję na pewno mi to pomoże. 

Edytowano przez faustin
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!

Anonim
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.