Benutzer-Werkzeuge

Webseiten-Werkzeuge


tipps

Tipps und Tricks

Hardware Design

STM32

Tutorials

Programmierung / KEIL Compiler (MDK µ-Vision)

Als erstes sollte man sich das mal durchlesen:
MDK5 getting started
CMSIS-Driver (Keil)
Tools von ST
- ( Clock-Konfigurations Tool (Excel), … )
Keil - Migrate ARM Compiler 5 to ARM Compiler 6
STVP-STM32 - ST Visual Programmer STM32

  • Keil - µ-Vsion - Dark-Theme
    Dark-Theme Datei:global.prop in c:\keil\uv4 abspeichern.

Die alte Datei am besten vorher sichern. Da das ganze Handling für die Einstellungen der Farben in der Keil IDE sehr umständlich ist, habe ich obige Vorlage erstellt.

Hinweis: In dieser Datei sind auch meine Templates gespeichert (z.B. für doxygen Blöcke)

Und so sieht es aus :-)

Ansicht global.prop (obiger Link kann direkt gedownloaded werden)

Debugging / Simulator

  • Beim Simulieren eines Programmes (ohne Debug-Hardware) kommt es immer wieder vor, dass auf die Adressbereiche von den Hardware Registern nicht zugegriffen werden kann. z.B.
    *** error 65: access violation at 0x40021000 : no 'read' permission

    Mit foglenden Mapping lässt sich das Problem lösen:

    MAP 0x40000000, 0x400FFFFF READ WRITE


    Damit man nun nicht immer händisch mit den Bereich im „Memory Map“ im Debugger Menü eintragen muss,
    kann man eine „Initializiation File“ anlegen welches den MAP-Befehl enthält.
    ini-File
    Hier werden dann die Rechte für den Speicherbereich von 0x40000000 bis 0x400FFFFF auf „Read“ und „Write“ gesetzt.
    Falls noch weitere Speicherbereiche benötigt werden, müssen dies hier ebenfalls eingetragen werden.
    (simu_stm32f105.ini)

  • Komfortablere Peripherie-Windows aktivieren:
    Dazu im obigen Debug-Setup
    • TCM.DLL durch TARMSTM.DLL
    • -pCM3 durch -pSTM32F103CB ersetzen

Nun erscheinen für den STM32F103 beim Debuggen unter Peripherals komfortablere Menüeinträge für die Peripeherie.
Wie dies auch für den STM32F105 funktioniert, habe ich noch nicht rausgefunden.
 Peripherie Module im Klartext beim Debuggen (nur STM32F103)

In der DLL konnte ich folgende Parameter (somit werden wohl bloss diese Prozessoren unterstützt) finden:

'STM32F101T6', 'STM32F101RD','STM32F103T6', 'STM32F101ZE'
'STM32F101T8', 'STM32F101RE','STM32F103T8', 'STM32F103RE'
'STM32F101C6', 'STM32F101V8','STM32F103C6', 'STM32F103V8'
'STM32F101C8', 'STM32F101VB','STM32F103C8', 'STM32F103VB'
'STM32F101CB', 'STM32F101VC','STM32F103CB', 'STM32F103VC'
'STM32F101R6', 'STM32F101VD','STM32F103R6', 'STM32F103VD'
'STM32F101R8', 'STM32F101VE','STM32F103R8', 'STM32F103VE'
'STM32F101RB', 'STM32F101ZC','STM32F103RB', 'STM32F103ZC'
'STM32F101RC', 'STM32F101ZD','STM32F103RC', 'STM32F103ZD'
'STM32F101RD', 'STM32F101ZE','STM32F103RD', 'STM32F103ZE'
'ST_bare'    
'CortexM3' 
'STM32F217IG'

Debug Settings Keil

  • DBGMCU_Config
    Um die Konfiguration (wird ja nur zum Debugging benötigt) nicht im Quellcode aufzuführen, kann man unter „Projektsettings→Debug→Initialzation File“ angeben welches die Konfiguration vornimmt (mittels Keil Configuration Wizard)
    - stm32f10x_dbgmcu.ini
    -stm32g4xx_dbgmcu.ini - Quelle Keil DFP-Pack 1.2.0

  • Hinweis: Bei der STM32CubeIDE kann man unter der Debug-Konfiguration→Startup→Initialization Commands mittels
    set *0xE0042004 = 0x7E3FFF07

    das DBG-Register beim Starten des Debuggers mit den passenden Werte beschreiben.

  • was macht das hier:
    # Enable Debug connection in low power modes (DBGMCU->CR)
    set 0xE0042004 = (0xE0042004) | 0x7

    als Beispiel für andere Schreibweise
    hier werden die unteren 3-Bits gesetzt.

Target Settings Keil - Hinweise

  • Wird als Target z.B. der STM32F105 ausgewählt so wird der C-Compiler mit der Option:
    1. -DSTM32F10X_CL aufgerufen. Dies hat zur Folge das in der Standard Lib dann automatisch von einen 25 MHz externen Quarz ausgegangen wird wenn das MAKRO HSE_VALUE nicht gesetzt ist und somit wird der HSE_VALUE auf 25000000 gesetzt.
      #if !defined  HSE_VALUE
       #ifdef STM32F10X_CL   
        #define HSE_VALUE    ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
       #else 
        #define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
       #endif /* STM32F10X_CL */
      #endif /* HSE_VALUE */
      
      Aus diesem Grund sollte das MAKRO HSE_VALUE in den C/C++ Compiler Optionen immer auf den den richtigen Wert gesetzt werden.z.B.
      HSE_VALUE=8000000
  • Xtal (Mhz) ( 8 ) - Settings in den Compiler - Target Optionen
    Hier wir auch der Wert des externen Quarzes eingetragen. Allerdings spielt dieser Wert nur eine Rolle für die Initialisierung des Debuggers und eines externen Flashers
  • Das Makro USE_FULL_ASSERT aktiviert die Benutzung des „assert_param()“ Makros. Desweiteren muss dann die Funktion failed_assert(..) implementiert werden. Hier ein Bespiel wenn das UART Retargeting aktiviert ist:
    #ifdef  USE_FULL_ASSERT
    
    /**
      * @brief  Reports the name of the source file and the source line number
      *         where the assert_param error has occurred.
      * @param  file: pointer to the source file name
      * @param  line: assert_param error line source number
      * @retval None
      */
    void assert_failed(uint8_t* file, uint32_t line)
    { 
      /* User can add his own implementation to report the file name and line number,
         ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    
      /* Infinite loop */
    
      printf("\n##########[Error]: Zeile: %d  in der Datei: %s\n\n",line,file);
      { 
          u32 i=0;
          
          for (i=0;i<120000;i++) {
              #ifdef WATCHDOG_AKTIV
                  vResetWdg();
              #endif
          }    
       }
      
      while (1)  {  }
    }
    
    #endif
    
    
    Hier wird dann die entsprechende Fehlerzeile über UART ausgegeben, bevor dann in der Endlos-Schleife beim aktivierten Watchdog-Timer ein Reset ausgelöst wird.
  • Clock Konfiguration - Um mich nicht immer durch die Header durchwühlen zu müssen, verwende ich eine eigene Clock-Konfigurations Funktion, die immer folgende Werte einstellt:
    • externer Quarz mit 8 MHz aktivieren
    • 72 MHz Sysclock
    • PLL1 als Sysclock Quelle verwenden
    • internen Takt abschalten (Beim Schreiben vom Flash muss der HSI aktiv sein)
      Somit sieht meine main immer so aus:
      int main(void) {
          RCC_Configuration();                            // Zuerst den Clock konfigurieren
          
          SystemCoreClockUpdate();                        
          if (SysTick_Config(SystemCoreClock / 1000)) {   // dann den Systick auf 1ms setzen
              // Capture error 
              while (1);
          }
      
          NVIC_Configuration();                           
          ....
      
      Und hier noch meine Clock-Konfiguration:
      /**
        * @brief  RCC_Configuration - Configures the different system clocks.
        *
        * Hier wird nun nachträglich der Takt auf 72MHz ( 32MHz bei L100) gestellt (HSE 8MHz => PLL => 32 MHz) (nur bei L100)
        * @attention Wenn der Speicher knapp wird dann auf diese Funktion verzichten, und nur die Startup-Konfiguration verwenden (diese steht aber noch auf 24 MHz)
        * @param  None
        * @retval None
        */
      
      static void RCC_Configuration(void){
          RCC_DeInit();                                   // RCC system reset(for debug purpose) 
          
          RCC_HSEConfig(RCC_HSE_ON);                      // Enable HSE 
          HSEStartUpStatus = RCC_WaitForHSEStartUp();     // Wait till HSE is ready 
      
          
          #ifdef PROZESSOR_FAMILY_STM32LXX    
              if(HSEStartUpStatus == SUCCESS){
                  FLASH_ReadAccess64Cmd(ENABLE);          // Enables  read access to flash by 64 bits
                  FLASH_PrefetchBufferCmd(ENABLE);        // Enable Prefetch Buffer 
                  FLASH_SetLatency(FLASH_Latency_1);      // ????
                  
                  RCC->APB1ENR |= RCC_APB1ENR_PWREN;      // Power enable 
      
                  PWR->CR = PWR_CR_VOS_0;                 // Select the Voltage Range 1 (1.8 V) 
                   
                  while((PWR->CSR & PWR_CSR_VOSF) != RESET) { // Wait Until the Voltage Regulator is ready
                  };
      
                  RCC_HCLKConfig(RCC_SYSCLK_Div1);        // HCLK = SYSCLK 
                  RCC_PCLK2Config(RCC_HCLK_Div1);         // PCLK2 = HCLK 
                  RCC_PCLK1Config(RCC_HCLK_Div1);         // PCLK1 = HCLK 
                  RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);  //by aw  als Quelle für den SysClk PLL1 verwenden
                  RCC_PLLConfig(RCC_PLLSource_HSE, RCC_PLLMul_12 , RCC_PLLDiv_3);// nun 32MHz // PLL konfigurieren: HSE * 12 / 3 = 96 Mhz /3 = 32 MHz
                  RCC_PLLCmd(ENABLE);                     // PLL einschalten   
      
                  while(RCC_GetSYSCLKSource() != 0x0C)    // 0x0C: PLL used as system clock 
                  {  };
      
                  RCC_HSICmd(DISABLE);                     //deAktiviert den internen Highspeed Oszillator.  
                  
                  #ifdef PROZESSOR_FAMILY_STM32LXX
                      RCC_MSICmd(DISABLE);
                  #endif
                  
      
              } // end HSE Startup Success
          #else   
      
              if(HSEStartUpStatus == SUCCESS){
                  FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);   // Enable Prefetch Buffer 
                  
                  RCC_HCLKConfig(RCC_SYSCLK_Div1);            // HCLK = SYSCLK 
                  RCC_PCLK2Config(RCC_HCLK_Div1);             // PCLK2 = HCLK 
      
                                                              // PCLK1 = HCLK 
                  RCC_PCLK1Config(RCC_HCLK_Div2);             // by AW (72MHz/2 = 36 MHz)	 wegen Umstelllung auf 72MHz Systemtak
                                                              // Achtung  Timertakt verdoppelt sich dann ???
      
                  RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);  //by aw  als Quelle für den SysClk PLL1 verwenden
      
                  RCC_PLLConfig(RCC_PLLSource_PREDIV1,RCC_PLLMul_9); // PLL konfigurieren: HSE / 1  * 9 = 72MHZ
                  RCC_PLLCmd(ENABLE);                        // PLL einschalten   
      
      
                  while(RCC_GetSYSCLKSource() != 0x08)    // by aw  warten bis PLL als Systemquelle genommen wird
                  {  }
      
                  // test von Aw
                  RCC_HSICmd(DISABLE); //deAktiviert den internen Highspeed Oszillator, Beim Flashspeichern, darf der interne nicht abgschaltet werden 
      
              } // end success
          #endif    
      } //end RCC_Configuration
      
      

Hinweis das Makro PROZESSOR_FAMILY_STM32LXX wird von mir im Header definiert, wenn ich einen STM32L1xx Type verwende:

//#define PROZESSOR_FAMILY_STM32LXX      // Makro zum aktivieren, dass die STM32LXX-Variante
                                         // verwendet werden soll 

Tipps zu Timer Konfigurationen (PWM)

Timer Codebook

  • Prescaller: Der Timertakt für den Timer berechnet sich folgendermassen:
      CK_CNT = fCK_PSC / (PSC[15:0] + 1)
    
    Daraus folgt dann z.B. für einen Timerclock von 10kHz := 72 Mhz / (prescaler +1)
    prescaler = (72 Mhz / 10 kHz) - 1 ⇒ 7199

    Und hier noch ein paar Makros für Timer (PWM):
     
    //! PWM Grundfrequenz für Timer2 (960 Hz)
    #define TIMER2_PWM_FREQUENZ (960)    // Grundfrequenz der PWM
    
    //! Timer2 Takt auf 8 MHz
    #define TIMER2_CLOCK (8000000)       // Timer2 Clock wird auf 8 MHz festgelegt     ( SYSCLK_FREQ_72MHz)
    
    //! Prescaler Wert für den Timer1
    #define TIMER2_PRESCACLER  ( (vu16) ((SystemCoreClock / TIMER2_CLOCK) - 1)) 
    
    //! PWM Timer2 Period um auf die 960 Hz zu kommen.
    #define TIMER2_PWM_PERIOD (0x208D)    // (0x109E)
    

und noch ein Beispiel für die PWM initialisierung von 4 PWM-Kanäle:

header.h:

//! PWM Timer2 Period um auf die 960 Hz zu kommen.
#define TIMER2_PWM_PERIOD (0x208D)    // (0x109E)

typedef enum extern_inputs_name_en {
    EXTERN_MOTOR_1    
,   EXTERN_MOTOR_2    
,   EXTERN_MOTOR_3    
,   EXTERN_MOTOR_4    
    
,   EXTERN_COUNTS_MOTOR_INPUTS    
} extern_inputs_name_t;



typedef volatile struct pwmStatus_st {
    struct pwm_st {
        u32 dutyCycle;
        u32 newDutyCycle;    // wenn wahr dann neuen Wert setzen
        
    } pwm[EXTERN_COUNTS_MOTOR_INPUTS];
    
    struct pwm_timer_st {
        u16 CCRx_Val ;     // Wert für die Peridodendauer vom Timer2 Channel x   (1-4) 
        void (*pTimSetCompare)(TIM_TypeDef* TIMx, uint16_t compare);                    // Zeiger auf die TIM_SetCompare Funktion
        void (*pTimOcInit)(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);     // Zeiger auf die OCxInit Funktion
        void (*pTimOcPreload)(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); 
    } pwm_timer[EXTERN_COUNTS_MOTOR_INPUTS]; 
} pwmStatus_t;

extern pwmStatus_t  pwmStatus;
extern pwmStatus_t* const pPwmStatus;



main.c:

//! PWM Statusflags über den PWM-Systemzustand
pwmStatus_t  pwmStatus =    {

                                {
                                    { PWM_DEFAULT_DUTY_CYCLE,1 }
,                                   { PWM_DEFAULT_DUTY_CYCLE,1 }                             
,                                   { PWM_DEFAULT_DUTY_CYCLE,1 }                            
,                                   { PWM_DEFAULT_DUTY_CYCLE,1 }   
                                } 
,                               {
                                    { 0x00 , TIM_SetCompare1, TIM_OC1Init, TIM_OC1PreloadConfig }     //CCR, TimeSetCompare(), TIM_OCxInit(), 
,                                   { 0x00 , TIM_SetCompare2, TIM_OC2Init, TIM_OC2PreloadConfig } 
,                                   { 0x00 , TIM_SetCompare3, TIM_OC3Init, TIM_OC3PreloadConfig }    
,                                   { 0x00 , TIM_SetCompare4, TIM_OC4Init, TIM_OC4PreloadConfig }
                                }
                            };

pwmStatus_t* const pPwmStatus = &pwmStatus;




/**
  * @brief  Timer2 Kanäle 1-4 für das PWM Ausgangssignal initialisieren
  *  
  *  PWM-Frequenz 940 Hz für alle Kanäle
  *  PORT A1  (T2.1n)
  *  PORT A2  (T2.2n)
  *  PORT A3  (T2.3n)
  *  PORT A4  (T2.4n)
  * @param  u16 defaultTast
  * @retval None
  */

 void vInitTimer2PWM(u32 defaultTast) {
    u32 i;

    // TIM2 clock enable  für das Licht PWM-Signal Test
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
                            
    // Timer2 Konfiguration PBA2
    // Tim2-CLK= auf 4 Mhz festlegen
    // Time base configuration
    // PWM Frequenz soll (f= 940 Hz) sein:
    // allgemein:   f=TimerCLK/(ARR+1)  ==> ARR=(4 MHz/940Hz)-1 =     4254,32 = 4254 = 109E        0x14F1
                                     // ==> ARR=(8 MHz/940Hz)-1 =     8509,64 = 8510 = 213E
    PrescalerValue = (vu16) (SystemCoreClock / TIMER2_CLOCK) - 1;  // 17    (8 für ( Mhz)

    TIM_TimeBaseStructure.TIM_Period = TIMER2_PWM_PERIOD ;          // 0x109E ==> PWM = 940 Hz
    TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;           // Timer1 Clk=4 MHz
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;         // keine weiterer Teiler
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;     // Vorwärtszähler
    //TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;              // Nur bei Timer1 und Timer8

    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);   
     
    // TIM1 Channel3 duty cycle = (TIM1_CCR3/ TIM1_ARR)* 100 = 25%
     
    for(i=0;  i<EXTERN_COUNTS_MOTOR_INPUTS;i++) {
        pPwmStatus->pwm_timer[i].CCRx_Val = SetPWM_Tast(defaultTast);
        
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
        //TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
        TIM_OCInitStructure.TIM_Pulse = pPwmStatus->pwm_timer[i].CCRx_Val;
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
        
        pPwmStatus->pwm_timer[i].pTimOcInit(TIM2, &TIM_OCInitStructure);
        pPwmStatus->pwm_timer[i].pTimOcPreload(TIM2, TIM_OCPreload_Enable);
    }
     
/*  nicht notwendig
    // Update registers
    TIM1->EGR |= (1 << TIM_EGR_UG);
*/

    TIM_ARRPreloadConfig(TIM2, ENABLE);

   /* TIM2 enable counter */
    TIM_Cmd(TIM2, ENABLE);

  // Main Output Enable  //nur bei Timer 1, 8
  //  TIM_CtrlPWMOutputs(TIM2, ENABLE);

}

sonstige Keil Tipps

  • String an einer festen Adresse platzieren
    • const char string[] __attribute__((at(0x0xxxxxxx)) = "Version 1.xxxxdfdf";
  • Software-Reset:
    • NVIC_SystemReset();
    • in neueren Versionen von core_cm3.h :
      __NVIC_SystemReset();

      Wobei mittels Makrodefinition auch der alte Name weiterhin verwendet werden kann.

  • EEPROM Emualation/Simulation: EEPROM Emulation

Keil / STM32CubeIDE

  • apnt_323.pdf - AppNote 323 - Using Keil MDK with STM32CubeIDE

ST-Standard Peripherie Lib

Und noch ein paar Tipps:

  • GPIO_PinSource6 - ist die Pinnummer (0..15)
  • GPIO_Pin_6 - ist der Wert für den gewählten Pin (1« Pinnummer)

STM32F1 HAL

App-Notes ST

App-Notes von Keil

Die ST-LINK/V2-1 auf den NUCLEO und Discovery-Boards können auf ein J-Link OB geflasht werden.
Die Anleitung von Segger ist hier:
ST-LINK zu J-Link von Segger

STM32 Bootloader Projekte

Diverse andere Projekte verwenden auch den Tiny-USB Stack um für Ihren eigenen Bootloader:

Normalerweise verwende ich mein JTAG Standardkabel (und Belegung) um die ST's zu programmieren.
Da ich immer wieder danach gefragt werde, hier mal die einfachste Variante (SWD Schnittstelle) hier werden nur 4 Verbindungen benötigt. Die Spannungsversorgung des Prozessors mache ich immer mit dem USB Verbindungskabel.

SWD Schnittstelle

ST-LINK ←→ Interface (meine STM32 Hardware)

 1 ---- Vdd -----2
 4 ---- GND ---- 4
 7 ---- TMS ---- 8  (SWDIO)
 9 ---- TCK ---- 7  (SWCLD)
 

Und hier noch ein Bild: SWD Verbindungen

JTAG Schnittstelle

ST-Utility - Klone

Dieser USB-Stick Klone hat den Vorteil, dass er auch die Versorgungsspannung liefert. Dafür ist er halt etwas langsamer und unterstützt nur das SWD-Schnittstelle. Dieses Teil hatte ich mir nur für Testzwecke zu gelegt.

ST-Klone ←→ Interface (meine STM32 Hardware)

 1 ---- Reset ---- 1  (optional)
 2 ---- SWDIO ---- 8  (TMS)
 4 ---- GND   ---- 4
 6 ---- SWCLK ---- 7  (TCK)
 7 ---- +3,3V ---- 2  (+3,3V MCU)

STM32 Discovery Boards

STM32-VL-DISCOVERY (STM32F100RB)

Sehr einfaches Eval-Board. Hat im Prinzip nur zwei LEDs und einen Taster als Input. Ist aber für kurze Tests gut geeignet

LEDS

  • grün (LD3) - PC9
  • blau (LD4) - PC8

die beiden anderen LEDS (LD1, LD2) sind fest verdraht und sind für PC-Board Kommunikation (LD1) und Power LED (LD2) vorbehalten.

Taster

  • schwarz - Reset - Reset Taster
    schaltet nach Masse
  • blau - PA0 - Benutzertaster (auch für Wake-Up)
    schaltet nach +3,3V

Hinweis zu STM32CubeIde und Debugging - In den neueren Versionen wird das Debugging dieses Board nicht unterstützt (wegen ST-LINK V1 auf dem Board). Deswegen verwende ich dann den BMP, d.h.:

  • beide Jumper von CN3 entfernen
  • von BMP dann die Signale:
    • +3,3V
    • GND
    • CLK - PA14
    • Data - PA13

verbinden.

STM32F429I-DISCO1

Moving Tux Demo

Ich habe die „Moving Tux Demo“ mal probeweise auf dem Disco1-Board installiert. Eine kurze Beschreibung von den Abweichungen der Installation und die binär Dateien findet ihr hier:

GDB Tipps

Da bei der MovinTux Demo auch OpenOCD installiert wird kann man auch den GDB von den ARM-Tools aus dem openOCD Ordner verwenden. Als erstes muss aber der ST-Link GDB-Server mit:

  • st-util (lauscht dann auf: Listening at *:4242… )
    gestartet werden.
  • arm-uclinuxeabi-gdb startet dann den Debugger (Der „bin“-Pfad auf den Ordner muss gesetzt sein).
    • tar extended-remote :4242 - baut dann die Verbindung zum Target (über den GDB-Server) auf and die Programmausführung wird angehalten.
    • continue - führt die aktuelle Programmausführung fort.
    • CTRL+C - unterbricht die Programmausführung mittels eines manuell gesetzen Breakpoints
    • b (break) - setzt einen Breakpoint an der aktuellen Position
    • info b (info break) - Zeigt Informationen über alle Breakpoints an
    • del x - x ist die Nummer von der Infoanzeige von einem Breakpoint den man löschen will
    • r (run) - startet das Program oder restart
    • Hinweis: Die Befehle müssen nicht ausgeschrieben werden, sobald die Abkürzung eindeutig ist, wird der entsprechende Befehl ausgeführt. Z.B.
      • continue kann auch als cont geschrieben werden.
      • info alli all

STLinux

ST bietet noch folgendes an:

TouchGFX Designer

Habe ich mit dem 429 Discoveryboard getetstet. Hinweise um den Bildschirm zu um 90° zu drehen:

  • Display-orientation
    Hat genauso funktioniert.
  • Arbeitet man mit Keil und man hat man hat beim ersten mal das exportierte Projekt geöffnet und zu Keil 5 mitgriert, so funktioniert der TouchGFX Designer nicht mehr, da er das Keil Projekt nicht mehr findet.

Hier mein erstes Testprojekt für das Lüftermenü:

STM32 unter Linux


Step-by-Step: STM32 Development Environment with OpenOCD and Visual Studio Code (Linux)


32 Runtime Libs unter Ubuntu 16.04
install all dev and docs


VS-Code unter Ubuntu installieren

Unter Ubuntu am besten folgende vorgehensweise (auch für 18.04):

curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list'

sudo apt update
sudo apt install code

Hat den Vorteil das man auch immer die aktuellste Version mittels apt updaten kann. Ab 18.04 ist VS-Code als Package im Software-Center enthalten, aber halt nicht immer ganz aktuell

Tipps zu Busmaster

CAN-Simulationen

Hinweis ab der Version V3.0 hat sich die STCAN_MSG Struktur geändert (vereinfacht). Deshalb müssen bestehende Simulationen angepasst werden. Die automatisch Konvertierung beim Importieren einer älteren Version hat bei mir nicht funktioniert. Eventuell lags daran, dass meine Simulationen schon etwas älter sind und im Header die Busmaster Version: BUSMASTER VERSION [1.7.1] angegeben war.
Hier nun die neu Struktur:

class STCAN_MSG
{
  unsigned int    id;        
  bool            isExtended; 
  bool            isRtr;    
  unsigned char   dlc;      
  unsigned char   cluster;
  unsigned char   data[64];
  unsigned long   timeStamp;
  bool            isCanfd;

  // To set data
  bool byteAt(int index, unsigned char val);
  bool wordAt(int index, unsigned short val);
  bool longAt(int index, unsigned long val);

  // To get data
  unsigned char  byteAt(int index);
  unsigned short wordAt(int index);
  unsigned long longAt(int index);
};
*Cluster ist die CAN-Kanalnummer vom Interface

Meine CAN Simulationen für Busmaster V3.1.0

  • Gateway Knoten zwischen CAN1 und CAN2 (inkl. Manipulationsmöglichkeit der gerouteten CAN-Botschaft)
    gateway.cpp
    Zum manipulieren einzelner CAN-Botschaften wird das „filterMask“-Array (maskieren von Datenbits) und „filterSet“-Array (zum Setzen einzelner Bits) verwendet.
  • BWM Diagnose Tester (todo: an das neue Format anpassen)
    bwm_diagnose.cpp
  • Porsche Head Unit Diagnose (inkl. Security Login) (todo: an das neue Format anpassen)
    porsche_hu_diagnose_sim.cpp
  • OBD2-Simulator
    Simuliert das Motorsteuergerätes eines Audi und dient zum Testen eines OBD2 Diagnose Dongle
    OBD_Simulator.cpp
    Folgende Funktionen sind implementiert
    - VIN Abfrage
    - DTC Fehlercodes
    - diverse Messwerte (Speed, RPM, Kühlwassertemp, usw…).
  • TP2.0 Simulator (todo: an das neue Format anpassen)
    VW_TP20_Simulator.cpp
  • VW Diagnose (todo: an das neue Format anpassen)
    VW_Diagnose.cpp
    Simuliert einen VW-Tester um eine Diagnose Sitzung zu einem TP2.0 Steuergerät aufzubauen.
  • KWP 2000 Modul zum Auflösen der SID Nummern in Klartextnamen (wird für Debug-Ausgabe von diversen Simulationen benötigt
    - kwp_2000.h
    - kwp_2000.c

VS Code Busmaster Settings für die Busmaster Simulationen

Da der integrierte Code Editor vom Busmaster grausam ist, habe ich jetzt eine Lösung gefunden um den Visual Studio Code Editor für die Busmaster Knoten Simulation zu verwenden inkl. der IntelliSense Funktionalität und compilieren des Quellcodes direkt aus VS Code herraus.

Hier folgt nun eine kurze Beschreibung wie man den Visual Studio Editor konfigurieren kann damit man für die Busmaster Simulationen die IntelliSense zur Verfügung steht und man auch direkt unter VS Code compilieren kann, d.h. direkt die DLL Datei für den Busmaster erzeugen kann.
Hier für müssen 2 Konfigurations Dateien angelegt werden:

  • c_cpp_properties.json - Konfiguration für IntelliSense
  • tasks.json - Konfiguration des Build-Systems, d.h. hiermit wird die Bumsmaster Simulation compiliert

Durch den angepassten „problemMatcher“ werden auch die Fehlermeldungen beim Compilieren in das Problemfenster übernommen, und man kann mit einem Mausklick direkt zur fehlerhaften Zeile springen.
Legendlich der Dateiname ist dann in der alten WIN/MSDOS Schreibweise.

Hier folgt nun eine kurze Beschreibung der wichtigsten Einträge:

  • c_cpp_properties.json (Ausschnitt für Win32):
            {
                
                "name": "Win32",
                "intelliSenseMode": "clang-x64",
                "includePath": [
                    "${workspaceRoot}",
                    "C:/Program Files (x86)/BUSMASTER_v3.2.2/SimulatedSystems/Include",
                    "C:/MinGW/lib/gcc/mingw32/5.1.0/include/c++",
                    "C:/MinGW/lib/gcc/mingw32/5.1.0/include/c++/mingw32",
                    "C:/MinGW/lib/gcc/mingw32/5.1.0/include/c++/backward",
                    "C:/MinGW/lib/gcc/mingw32/5.1.0/include",
                    "C:/MinGW/include",
                    "C:/MinGW/lib/gcc/mingw32/5.1.0/include-fixed"
                ],
                "defines": [
                    "_DEBUG",
                    "UNICODE",
                    "__GNUC__=6",
                    "__cdecl=__attribute__((__cdecl__))"
                ],
                "browse": {
                    "path": [
                        "C:/Program Files (x86)/BUSMASTER_v3.2.2/SimulatedSystems/Include",
                        "C:/MinGW/lib/gcc/mingw32/5.1.0/include",
                        "C:/MinGW/lib/gcc/mingw32/5.1.0/include-fixed",
                        "C:/MinGW/include/*"
                    ],
                    "limitSymbolsToIncludedHeaders": true,
                    "databaseFilename": ""
                }
            }

Hinweis: Die Pfade bei den markierten Zeilen müssen eventuell angepasst werden.

  • tasks.json (komplett, s.o.):
    {
        // See https://go.microsoft.com/fwlink/?LinkId=733558
        // for the documentation about the tasks.json format
        "version": "2.0.0",
        "tasks": [
            {
                "label": "build OBD_Simulator",
                "type": "shell",
                "command": "make -f OBD_Simulatormake",
                "problemMatcher": [
                    {
                        "owner": "cpp",
                        "fileLocation": "absolute",
                        "pattern": {
                            "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
                            "file": 1,
                            "line": 2,
                            "column": 3,
                            "severity": 4,
                            "message": 5
                        }
                    }
                ],
                "group": {
                    "kind": "build",
                    "isDefault": true
                }
            },
            {
                "label": "clean",
                "type": "shell",
                "command": "make clean -f OBD_Simulatormake",
                "problemMatcher": [
                    "$gcc"
                ]
            }
        ]
    }
    

Hinweis: OBD_Simulatormake ist das vom Busmaster erzeugte Makefile für den Compiler und der Name muss an das eigene Simulations-Projekt angepasst werden.


Tipps zu Doku-Wiki

SyntaxHigligther 4

SyntaxHighlighter 4 on Github

<sxh [brush][; options]>
... code/text ...
</sxh>

Beispiel mit Markierung bestimmter Zeilen:

#define CIRCBUF_DEF(x,y) uint8_t x##_space[y]; circBuf_t x = { x##_space,0,0,y}
 
CIRCBUF_DEF(cb, 32);
 
int circBufPush(circBuf_t *c, uint8_t data)
{
    int next = c->head + 1;
    if (next >= c->maxLen)
        next = 0;
 
    // Cicular buffer is full
    if (next == c->tail)
        return -1;  // quit with an error
 
    c->buffer[c->head] = data;
    c->head = next;
    return 0;
}
 
int circBufPop(circBuf_t *c, uint8_t *data)
{
    int next;
    // if the head isn't ahead of the tail, we don't have any characters
    if (c->head == c->tail)
        return -1;  // quit with an error
 
    *data = c->buffer[c->tail];
    c->buffer[c->tail] = 0;  // clear the data (optional)
 
    next = c->tail + 1;
    if(next >= c->maxLen)
        next = 0;
 
    c->tail = next;
 
    return 0;
}


Tipps zu Raspberry

pi1_tipps
pi3_tipps
Upgrade von Rpi2 zu Rpi3 - System Upgrade von einer Rpi2 SD-Karte auf 3

I²C Schnittstelle und Raspi - Beispiele mit Python

I2C-Sniffer

pigpio

Raspi-Sniffer

Git: push over ssh:

cd my-project
git remote add origin ssh://user@host/mnt/foo/bar/my-project.git
git push origin master 

HW Design Eagle

Hier sind ein paar Links zu Eagle Libs für HW Erweiterungen für den Raspi

SD-Karte klonen

Mit diesem kleine Windowstool kann man die kompletter SD-Karte inkl. aller Partitionen klonen:

Hinweis: Eventuell muss man auf der Ziel SD-Karte vorher alle bestehende Partitioinen und das Volume mit dem Festplattenmanager löschen, falls es zu write Fehlern kommt (bei Roadkil's Diskimage war dies bei mir erforderlich)

Unter „Linux“ kann man auch „dd“ verwenden um die komplette SD-Karte oder einzelne Partitionen zu klonen.

# Ein Image von einer einzelnen Partion auf sdf erstellen:
sudo dd if=/dev/sdf1 of=/home/myusername/raspberry_root-backup-sdf1-2017-05-10.img

# komplettest Image erstellen:
sudo dd if=/dev/sdf of=/home/myusername/raspberry-backup-sd_card_2017-05-10.img

Image mounten

Die obige erstellten Images können als „Loop Device“ eingebunden werden:

  • sudo losetup /dev/loop0      # prüfen, ob "loop0" frei ist  (falls nichts erkannt wird ist es verfügbar.
  • sudo losetup /dev/loop0 /home/myusername/raspberry_root-backup-sdf1-2017-05-10.img   #image dem loop device zuweisen
  • sudo mount -t vfat /dev/loop0 /media/sdimage-1   # image mounten, oder unter /mnt/raspi  
    nachträglich als Read Only mounten:
    sudo mount -o remount,ro /mnt/raspi
    
    oder direkt als read only und wenn mehrere partitionen im image sind eine auswählen:
    sudo mount  /dev/loop0p7 /mnt/raspi/ -o ro      #read only und die Linux SystemPartition mounten
    
    
  • sudo umount /dev/loop0
    sudo losetup -d /dev/loop0

obiges kann mit:

sudo losetup --find --show -P minix203.img

vereinfacht werden, da hier das Image direkt an das erste freie Loop-Device verbunden wird.

SD-Karte formatieren

Fail2ban Tipps

einzelne Fiterregeln (jails) kann man in der shell prüfen:

fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf 

oder mit Ausgabe der Logzeile:

fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf  --print-all-matched

Hinweis: immer den kompletten Pfad zur Konfigurationsdatei verwenden

Fail2Ban Filter und Jails Konfiguration

Weitere Tipps:

 fail2ban-client status 
 fail2ban-client status ssh             # zeigt alle IPs an die von "SSH" gebannt wurden
 fail2ban-client get ssh banned         # gibt ein Array der gebannte IPs von "SSH" zurück
 fail2ban-client unban xxx.xxx.xxx.xx   # IP für alle Jails wieder freigeben.

ESP32 Pico Kit

ESP32 CAM DEV

Hier eine kurze Beschreibung vom Modul:
ESP32-CAM Dev Board

OCTAVE

Für meine Tests wurde die Version V4.2.1 verwendet. Mit der nachträglichen Installation des Signal Moduls:
pkg install D:\Downloads\chrome\signal-1.3.2.tar.gz
(signal-1.3.2.tar.gz, von Signal Package von Sourceforge)
danach muss das Modul noch mit:
pkg load signal
geladen werden.

FIR-Filter Design

FIR-Filter mit Octave/Matlab

Testfile bitte in *.m umbennenen fir_first_test.m

Octave Beispiele

GIT Extensions

Probleme

  • Sollte kein Start von Git Extensions mehr möglich sein, dann liegt es meistens daran das die Settings-Datei beschädigt wurde. Als erstes mal versuchen folgende Datei zu löschen
    C:\Users\xxxBenutzernamexxx\AppData\Roaming\GitExtensions\GitExtensions\GitExtensions.settings

Git

Git Submodule

 git submodule add ssh://andreas@geier99.de/opt/git/Projekte/Tools/diagLogger.git Andreas/diagLogger

Damit dies funktioniert, muss ein eventuell vorhandener Ordner „diagLogger“ aus dem Index erst gelöscht werden. Beim Pull wird dann auch das diaglogger geklont(oder gepullt)

Obiges Beispiel legt ein Submodul in ein bestehendes geklontes Git-Repository an (eventuell vorher den Ordner vom Submodul löschen)

Obiger Befehl legt auch die Datei .gitmodules an:

[submodule "Andreas/diagLogger"]
        path = Andreas/diagLogger
        url = ssh://andreas@geier99.de/opt/git/Projekte/Tools/diagLogger.git

Git Konsole Tipps

Java

Decompiler

OpenOCD mit Buspirate

vscode esp

USB Driver

tipps.txt · Zuletzt geändert: 2024/01/28 08:29 von geier99