Skip to content

Instantly share code, notes, and snippets.

@xsrf
Created August 26, 2024 15:59
Show Gist options
  • Select an option

  • Save xsrf/95522c0329f2a52c0f8900f439051f74 to your computer and use it in GitHub Desktop.

Select an option

Save xsrf/95522c0329f2a52c0f8900f439051f74 to your computer and use it in GitHub Desktop.
CH32V003 TIM1 ISR Debug LEDs
#include "ch32v003fun.h"
#include <stdio.h>
// LEDs on A1 and A2 (to GND)
#define LED_PORT GPIOA
#define LED_PIN1 1
#define LED_PIN2 2
void TIM1_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM1_UP_IRQHandler(void) {
if (TIM1->INTFR & TIM_UIF) {
LED_PORT->BSHR = 1<<(LED_PIN2+16); // LED2 OFF
}
if (TIM1->INTFR & ~TIM_UIF) { // TIM_UIF is 0x01 so this is true for every IF that's not 0x01
LED_PORT->BSHR = 1<<(LED_PIN1+16); // LED1 OFF
}
TIM1->INTFR = 0;
}
int main()
{
SystemInit();
RCC->APB2PCENR |= RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_TIM1 | RCC_APB2Periph_AFIO;
LED_PORT->CFGLR &= ~(0xf<<(4*LED_PIN1));
LED_PORT->CFGLR &= ~(0xf<<(4*LED_PIN2));
LED_PORT->CFGLR |= (GPIO_Speed_50MHz | GPIO_CNF_OUT_PP)<<(4*LED_PIN1);
LED_PORT->CFGLR |= (GPIO_Speed_50MHz | GPIO_CNF_OUT_PP)<<(4*LED_PIN2);
LED_PORT->BSHR = 1<<(LED_PIN1+0); // Set LED1 ON
LED_PORT->BSHR = 1<<(LED_PIN2+0); // Set LED2 ON
Delay_Ms(100);
LED_PORT->BSHR = 1<<(LED_PIN1+16); // Set LED1 ON
LED_PORT->BSHR = 1<<(LED_PIN2+16); // Set LED2 ON
Delay_Ms(100);
LED_PORT->BSHR = 1<<(LED_PIN1+0); // Set LED1 ON
LED_PORT->BSHR = 1<<(LED_PIN2+0); // Set LED2 ON
// LED1/2 (100ms steps): 10.. (see below)
// Reset TIM1 to init all regs
RCC->APB2PRSTR |= RCC_APB2Periph_TIM1;
RCC->APB2PRSTR &= ~RCC_APB2Periph_TIM1;
TIM1->PSC = 48000-1; // 1kHz
TIM1->ATRLR = 500-1; // 500ms
// Timer CNT resets to 0 regardless of TIM_ARPE set or not
TIM1->CTLR1 |= TIM_OPM; // | TIM_ARPE; // One-Pulse-Mode + Auto-Reload
TIM1->DMAINTENR |= TIM_UIE;
TIM1->SWEVGR |= TIM_UG; // REQUIRED to set the PSC correctly!!!
TIM1->INTFR &= ~TIM_UIF; // Clears the Interrupt Flag set by TIM_UG before so it won't fire immediately!
TIM1->CTLR1 |= TIM_CEN;
NVIC_EnableIRQ(TIM1_UP_IRQn); // TIM1-Interrupt im NVIC aktivieren
// By now LED1 is turned off because the Interrupt Handler is called immediately
// LED2 is still untouched
while(0) {
;
} // Result: LED1 off after 500ms, LED2 off after 1s; OK
// LED1 (100ms steps): ..000000000000000..0
// LED2 (100ms steps): ..111110000000000..0
while(0) {
Delay_Ms(10);
} // Result: LED1 off after 500ms, LED2 off after 1s; OK
// LED1 (100ms steps): ..000000000000000..0
// LED2 (100ms steps): ..111110000000000..0
while(0) {
Delay_Ms(99);
LED_PORT->BSHR = 1<<(LED_PIN1+0); // Set LED_PIN1 HIGH
LED_PORT->BSHR = 1<<(LED_PIN2+0); // Set LED_PIN2 HIGH
} // Result: LED1 blinks off for 100ms; Both turn off after 1s; They never turn on again; ERR
// LED1 (100ms steps): ..011110000000000..0
// LED2 (100ms steps): ..111110000000000..0
while(0) {
Delay_Ms(100);
LED_PORT->BSHR = 1<<(LED_PIN1+0); // Set LED_PIN1 HIGH
LED_PORT->BSHR = 1<<(LED_PIN2+0); // Set LED_PIN2 HIGH
} // Result within ~16s after cold start: LED1 blinks off for 100ms; Both turn off after 1s; They never turn on again; ERR
// LED1 (100ms steps): ..011110000000000..0
// LED2 (100ms steps): ..111110000000000..0
// Result after ~16s: LED1 blinks off for 100ms then both STAY ON forever; OK
// LED1 (100ms steps): ..011111111111111..1
// LED2 (100ms steps): ..111111111111111..1
while(0) {
Delay_Ms(105);
LED_PORT->BSHR = 1<<(LED_PIN1+0); // Set LED_PIN1 HIGH
LED_PORT->BSHR = 1<<(LED_PIN2+0); // Set LED_PIN2 HIGH
} // Result (<16s): LED1 blinks off for 100ms; Both turn off after 1s; They never turn on again; ERR
// LED1 (100ms steps): ..011110000000000..0
// LED2 (100ms steps): ..111110000000000..0
// Result (>16s): LED1 blinks off for 100ms then both STAY ON forever; OK
// LED1 (100ms steps): ..011111111111111..1
// LED2 (100ms steps): ..111111111111111..1
while(0) {
Delay_Ms(400);
LED_PORT->BSHR = 1<<(LED_PIN1+0); // Set LED_PIN1 HIGH
LED_PORT->BSHR = 1<<(LED_PIN2+0); // Set LED_PIN2 HIGH
} // Result: LED1 blinks 100ms ON before both turn off after 1s; They never tun on again; ERR
// LED1 (100ms steps): ..000010000000000..0
// LED2 (100ms steps): ..111110000000000..0
while(0) {
Delay_Ms(600);
LED_PORT->BSHR = 1<<(LED_PIN1+0); // Set LED_PIN1 HIGH
LED_PORT->BSHR = 1<<(LED_PIN2+0); // Set LED_PIN2 HIGH
} // Result within 16s: Result: LED1 off after 500ms, LED2 off after 1s; They never turn on again! ERR
// LED1 (100ms steps): ..000000000000000..0
// LED2 (100ms steps): ..111110000000000..0
// Result after 16s cold start:
// LED1 (100ms steps): ..000001111111111..1
// LED2 (100ms steps): ..111111111111111..1
while(1) {
Delay_Ms(1000);
LED_PORT->BSHR = 1<<(LED_PIN1+0); // Set LED_PIN1 HIGH
LED_PORT->BSHR = 1<<(LED_PIN2+0); // Set LED_PIN2 HIGH
Delay_Ms(1000);
LED_PORT->BSHR = 1<<(LED_PIN1+16); // Set LED_PIN1 LOW
LED_PORT->BSHR = 1<<(LED_PIN2+16); // Set LED_PIN2 LOW
} // Result within ~16s: Result: LED1 off after 500ms, LED2 off after 1s; They never turn on again! ERR
// LED1 (100ms steps): ..000000000000000..0
// LED2 (100ms steps): ..111110000000000..0
// Result after ~16s cold start: LED1 is turned ON after 500ms (+init above) even though it should still be in the 1s delay!
// LED1 (100ms steps): ..00000111111111100000000001111111111000..
// LED2 (100ms steps): ..11111111111111100000000001111111111000..
/*
The Chip is connected just with 5V, GND and SWD and a 0.1uF decoubling on 5V/GND.
"cold boot" means I shorted 5V to GND (obviously with supply disconnected).
Without "cold boot" the chip keeps some values like SysTick even after reset via minichlink/upload or just disconnecting 5V,
probably because of current supplied by SWD and the cap.
*/
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment