====== Tipps und Tricks ====== ===== Hardware Design ===== [[http://www.mantaro.com/resources/impedance-calculator.htm|Impdanze-Kalkulator]]\\ [[http://www.gunthard-kraus.de/LTSwitcherCAD/index_LTSwitcherCAD.html|LT-Spice Tutorials]] ====== STM32 ====== ===== Tutorials ===== * [[https://www.diller-technologies.de/stm32.html|Diller - STM32 Tutorial]] - veraltet, aber trotzdem gut * [[https://stm32f4-discovery.net/2014/09/stm32f4-tutorials-one-place/|tm32f4-tutorials-one-place]] * [[https://vivonomicon.com/?s=stm32|STM32 Bare Metal]] - Blog zu "STM32 Bare Metal"-Programmierung ===== Programmierung / KEIL Compiler (MDK µ-Vision) ===== Als erstes sollte man sich das mal durchlesen:\\ [[http://www2.keil.com/docs/default-source/default-document-library/mdk5-getting-started.pdf|MDK5 getting started]]\\ [[https://www.keil.com/pack/doc/CMSIS/Driver/html/index.html|CMSIS-Driver (Keil) ]]\\ [[http://www.st.com/en/embedded-software/stm32-embedded-software.html?querycriteria=productId=SC961|Tools von ST]]\\ - ( Clock-Konfigurations Tool (Excel), ... )\\ [[http://www.keil.com/appnotes/files/apnt_298.pdf| Keil - Migrate ARM Compiler 5 to ARM Compiler 6]]\\ [[http://www.st.com/en/development-tools/stvp-stm32.html|STVP-STM32 - ST Visual Programmer STM32]]\\ * **Keil - µ-Vsion - Dark-Theme** \\ Dark-Theme Datei:{{ :media:global.prop |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 :-) {{ :media:uv4_2017-01-20_21-12-45.png?nolink&500 |}} {{ :media:global.prop.txt |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' permissionMit 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.\\ {{ :media:keil_stm32f105_simulations_ini.png |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. \\ ({{ :media:stm105_simulation.ini |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.\\ {{ :media:peripherie_klartext.png | 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)\\ -{{ :public:stm32f101_102_103_105_107_dbgmcu.ini | stm32f10x_dbgmcu.ini}}\\ -{{ ::stm32g4xx_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 mittelsset *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: - -D**STM32F10X_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) ==== [[http://www.st.com/content/ccc/resource/technical/document/application_note/group0/91/01/84/3f/7c/67/41/3f/DM00236305/files/DM00236305.pdf/jcr:content/translations/en.DM00236305.pdf| 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; ipwm_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: [[https://www.elektronik-keller.de/index.php/tipps/stm32-programmierung/31-eeprom-emulation|EEPROM Emulation]] ==== Keil / STM32CubeIDE ==== * [[https://www.keil.com/appnotes/files/apnt_323.pdf|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 ===== [[http://www.st.com/content/ccc/resource/technical/document/user_manual/72/52/cc/53/05/e3/4c/98/DM00154093.pdf/files/DM00154093.pdf/jcr:content/translations/en.DM00154093.pdf|UM 1850 - Description of STM32F1 HAL and Low-layer drivers]] ===== App-Notes ST ===== * [[http://www.st.com/content/ccc/resource/technical/document/application_note/6c/a3/24/49/a5/d4/4a/db/CD00164185.pdf/files/CD00164185.pdf/jcr:content/translations/en.CD00164185.pdf|AN2586]] - Getting started with STM32F10xxx hardware development * [[http://www.st.com/content/ccc/resource/technical/document/application_note/group0/91/01/84/3f/7c/67/41/3f/DM00236305/files/DM00236305.pdf/jcr:content/translations/en.DM00236305.pdf|AN4776 - STM32 Timer]] - General-purpose timer cookbook * [[http://www.st.com/content/ccc/resource/technical/document/application_note/82/6c/5d/1d/b8/a3/4b/a8/DM00209695.pdf/files/DM00209695.pdf/jcr:content/translations/en.DM00209695.pdf|AN4724 - STM32Cube firmware examples for STM32F1 Series]] ===== App-Notes von Keil ===== * [[http://www.keil.com/appnotes/files/apnt_268.pdf|268 - Creating a Middleware Application using CMSIS Components with MDK Version 5]] * [[https://www.keil.com/appnotes/files/apnt_298.pdf| 298 - Migrating ARM Compiler 5 to Arm Compiler 6]] ==== Konvertierung eines ST-Links on Board zu J-Link ==== 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: \\ [[https://www.segger.com/products/debug-probes/j-link/models/other-j-links/st-link-on-board/|ST-LINK zu J-Link von Segger]] ===== STM32 Bootloader Projekte ===== * [[https://github.com/bootsector/stm32-hid-bootloader|stm32-hid-bootloader]] * [[https://githubhelp.com/TheKikGen/stm32-tkg-hid-bootloader|stm32-tkg-hid-bootloader]] * [[http://kevincuzner.com/2018/06/28/building-a-usb-bootloader-for-an-stm32|building-a-usb-bootloader-for-an-stm32]] Diverse andere Projekte verwenden auch den Tiny-USB Stack um für Ihren eigenen Bootloader: * [[https://github.com/hathach/tinyusb|tinyusb]] * [[https://github.com/dmitrystu/libusb_stm32| libusb_stm32]] - Lightweight USB Device Stack for STM32 ===== ST-LINK Utility ===== 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: {{ :public:stlink_stm32_swd_programming.jpg?linkonly |SWD Verbindungen}} ==== JTAG Schnittstelle ==== ===== ST-Utility - Klone ===== {{ ::stlink_v2_clone.jpg?direct&300|}}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** oder einen **ST-LINK-V2**, d.h.: * beide Jumper von CN3 entfernen * von BMP/ST-LINK V2 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: * [[public:projekte:stm32:Linux_auf_STM32|Linux_auf_STM32]] - yCLinux auf STM32F429I-Disco1 === 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 all** => **i all** === STM32F429 USB Bootloader === Hier geht's zu meiner Projektseite für [[entwicklung:tipps:stm32:stm32f4:stm32f29_usb_bootloader|STM32F429 USB Bootloader]] [[entwicklung:tipps:stm32:stm32f4:stm32f429_disco1|STM32F429 Disco1 Dev Board]] ===== STLinux ===== ST bietet noch folgendes an: * [[https://www.st.com/en/development-tools/stlinux.html|STLinux]] \\ muss ich mir mal anschauen. * [[http://archive.stlinux.com/|STLinux.com]] ===== TouchGFX Designer ===== Habe ich mit dem 429 Discoveryboard getestet. Hinweise um den Bildschirm zu um 90° zu drehen: * [[https://touchgfx.zendesk.com/hc/en-us/articles/203563972-Display-orientation|Display-orientation]] \\ Hat genauso funktioniert. * Arbeitet man mit Keil und man hat beim ersten mal das exportierte Projekt geöffnet und zu Keil 5 migriert, so funktioniert der TouchGFX Designer nicht mehr, da er das Keil Projekt nicht mehr findet. Hier mein erstes Testprojekt für das Lüftermenü: ==== Alternativen ==== * [[https://www.reddit.com/r/embedded/comments/gar56r/do_you_know_of_viable_alternatives_to_touchgfx|do_you_know_of_viable_alternatives_to_touchgfx]] * [[https://lvgl.io|LVGL]] * [[https://github.com/lbcb/LittlevGL|LittlevGL]] - auf Github * [[https://www.youtube.com/watch?v=SnrHpcujpyU&list=PLfIJKC1ud8ghGES4CUTjHTn_G4gly_atz|Getting started with LVGL on STM32]] * [[https://www.youtube.com/watch?v=PPMKRoJcZw4|Developing Embedded GUI with Open Source LVGL]] * [[https://www.youtube.com/watch?v=2icWdLapbBs|Grafische Benutzeroberflächen mit lvgl für ESP32 und RP2040]] * [[https://github.com/renebohne/pico-lvgl-examples|pico-lvgl-examples]] * [[https://www.embedded-wizard.de|Embedded Wizard]] * [[https://www.st.com/en/partner-products-and-services/segger-emwin.html#product-details|STemWin]] - Segger * **[[https://squareline.io|SquareLine Studio]]** Hier geht's zum meinen [[entwicklung:lvgl:stm32lvgl:lvgl_stm32|LVGL-Notizen]] ===== STM32 unter Linux ===== * [[https://atollic.com/truestudio/|Attolic Truestudio STM32 V9.0.0]] - komplett kostenlos für STM32\\ seit 2018 ([[https://atollic.com/release-news/atollic-truestudio-stm32-9-0-0-released/|news]]) gibt es die Vollversion für STM32 umsonst.\\ Und hier sind noch einige interessante [[http://info.atollic.com/resources/white-papers|White Papers]] hinterlegt. Bei vielen Assertfehler vor dem Starten:export env SWT_GTK3=0 ausführen. * [[https://launchpad.net/gcc-arm-embedded|gcc-arm-embedded]]\\ PPA is available at https://launchpad.net/~team-gcc-arm-embedded/+archive/ubuntu/ppa .\\ . * [[http://www.openstm32.org/HomePage|Open STM32 AC6 (Eclipse basierend)]]\\ Hinweis: Eclipse needs GTK2 (s.[[http://www.openstm32.org/faq1#q22|FAQ - Eclipse Bug]]) \\ [[https://community.st.com/servlet/JiveServlet/downloadBody/1644-102-1-7091/SW4MCU_User_Training-full-v1.1.pdf|User Training Full V1.1.pdf]] ---- [[https://www.youtube.com/watch?v=FNDp1G0bYoU|Step-by-Step: STM32 Development Environment with OpenOCD and Visual Studio Code (Linux)]] * [[https://github.com/libopencm3/libopencm3-examples]] * [[http://libopencm3.org/]] * [[https://github.com/mikisama/libopencm3_cmake.git|libopencm3_cmake.git]] - Wie man Cmake mit libopencm3 verwenden kann. ---- [[https://blog.teststation.org/ubuntu/2016/05/12/installing-32-bit-software-on-ubuntu-16.04/| 32 Runtime Libs unter Ubuntu 16.04]]\\ [[http://littlesvr.ca/grumble/2012/12/12/install-all-the-dev-and-doc-packages-in-debianubuntumint/| 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)\\ {{ :media:gateway.cpp |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 \\ {{ :media:obd_simulator.cpp |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 \\ - {{ :media:kwp_2000.h |kwp_2000.h}} \\ - {{ :media:kwp_2000.c |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: * **{{ :public:vscode:busmaster:c_cpp_properties.json |c_cpp_properties.json}}** - Konfiguration für IntelliSense * **{{ :public:vscode:busmaster:tasks.json |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 ==== [[https://github.com/crazy-max/dokuwiki-plugin-syntaxhighlighter4|SyntaxHighlighter 4 on Github]] ... code/text ... 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|pi1_tipps]] \\ [[pi3_tipps|pi3_tipps]]\\ [[https://www.computerhilfen.de/info/raspberry-pi-3-update-alte-sd-karte-im-raspberry-3-nutzen.html|Upgrade von Rpi2 zu Rpi3]] - System Upgrade von einer Rpi2 SD-Karte auf 3 [[entwicklung:tipps:raspi_i2c|I²C Schnittstelle und Raspi - Beispiele mit Python]] [[https://www.raspberrypi.org/forums/viewtopic.php?t=75033|I2C-Sniffer]] [[http://abyz.co.uk/rpi/pigpio/|pigpio]] [[http://tuxbabe.eu/raspalyzer.html|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 * [[https://www.raspberrypi.org/forums/viewtopic.php?t=82618|B+ HAT Eagle CAD template]]\\ [[http://www.flyfish-tech.com/pub/RasPi-BplusHAT.zip|RasPi-BplusHAT.zip]] * [[https://github.com/haldean/rpi-gpio-eagle|rpi-gpio-eagle]] - Eagle library for the shrouded Raspberry Pi GPIO header * [[https://www.raspberrypi.org/blog/introducing-raspberry-pi-hats/|RaspberryPi Hats Einführung]] * [[https://github.com/raspberrypi/hats|Spezifikation Hats]] * [[https://github.com/raspberrypi/hats/blob/master/designguide.md|Hats Design Guide]] * [[https://www.raspberrypi.org/forums/viewtopic.php?t=108134|EEPROM für HATs einrichten]] ===== SD-Karte klonen ===== Mit diesem kleine Windowstool kann man die kompletter SD-Karte inkl. aller Partitionen klonen: * [[http://www.roadkil.net/program.php/P12/Disk%20Image| Roadkil's DiskImage]] * für nur eine Partion oder zu Schreiben eines kompletten images auf SD-Karte:\\ [[https://sourceforge.net/projects/win32diskimager|Win32 Diskimager]] ( oder für alles obiges tool nehmen) * ([[https://www.partitionwizard.com/free-partition-manager.html|MiniTool Partition Wizard Free Edition 10.2]]) - Partitionstool 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 ===== [[https://www.sdcard.org/downloads/formatter_4/index.html| SD-Kart Formater]] ---- ===== 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 [[http://linuxwiki.de/Fail2Ban#Filters_und_Jail.conf|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===== [[https://esp-idf.readthedocs.io/en/latest/get-started/get-started-pico-kit.html|Get Started with ESP32-Pico-Kit]] ===== ESP32 CAM DEV===== Hier eine kurze Beschreibung vom Modul: \\ [[https://blog.hackster.io/seeed-taking-pre-orders-for-esp32-cam-dev-board-with-2mp-camera-f072d831246d|ESP32-CAM Dev Board]] ==== Links ==== * [[https://github.com/donny681/ESP32_CAMERA_QR/wiki| ESP32 QR-Code]] * [[https://github.com/SeeedDocument|Seed Documents]] * [[http://wiki.ai-thinker.com/esp32]] ===== 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** \\ ({{ :public:signal-1.3.2.tar.gz |}}, von [[https://octave.sourceforge.io/signal/|Signal Package von Sourceforge]])\\ danach muss das Modul noch mit:\\ **pkg load signal**\\ geladen werden. ==== FIR-Filter Design ==== [[https://www.allaboutcircuits.com/technical-articles/design-of-fir-filters-design-octave-matlab|FIR-Filter mit Octave/Matlab]] Testfile bitte in *.m umbennenen {{ :entwicklung:fir_first_test.txt | fir_first_test.m}} ==== Octave Beispiele ==== * {{ :entwicklung:octave:octave_test_sinus.txt |test_sinus.txt}} * {{ :entwicklung:octave:octave_adc_valudes.txt |adc_values.txt}} ===== 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 ===== [[https://www.dreamincode.net/forums/topic/190944-creating-an-updater-in-java/|Creating an Updater in Java]] ==== Decompiler ==== * [[http://www.javadecompilers.com/|Online Java und APK Decompiler]] * JD-GUI - ({{ :entwicklung:java:jd-gui-windows-1.6.4.zip |JD-Gui Windows V1.6.4}}) * [[entwicklung:java:javadebugging|Java Debugging]] ===== GNU Toolchain Links ===== * [[http://gnutoolchains.com/download/]] * [[https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm| GNU Arm Embedded Toolchain]] - offizelle ARM Version (etwas älter) * [[https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads|downloads]] - direkt zu den Downloads ===== OpenOCD mit Buspirate ===== * [[https://research.kudelskisecurity.com/2014/05/01/jtag-debugging-made-easy-with-bus-pirate-and-openocd/]] ===== vscode esp ===== * [[https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools]] * [[https://github.com/espressif/esp-idf/issues/303]] * [[https://gojimmypi.blogspot.com/2017/05/vscode-remote-debugging-of-embedded.html]] * [[https://github.com/VirgiliaBeatrice/esp32-devenv-vscode/blob/master/tutorial.md]] ===== USB Driver ===== * [[https://zadig.akeo.ie|Zadig - Easy USB Driver Installation]]\\ [[https://github.com/pbatard/libwdi/wiki/Zadig|Guide Zadig]] * [[https://github.com/libusb/libusb|libusb]]\\ [[https://sourceforge.net/p/libusb-win32/wiki/Home|libusb-win]] - veraltet, man sollte libusb nehmen