cancel
Showing results for 
Search instead for 
Did you mean: 

Issue with STM8S103F3 using wait for interrupt assembly call

JEREMYB
Associate

Hello,

First off, I'd really like to thank the community for being there to help, and I really appreciate any help or guidance offered. I am trying to put an STM8S103F3 MCU into wait mode until an external interrupt on port A triggers. I make the assembly call to wait for interrupt, but the main loop keeps running without the port A external interrupt being fired to resume normal device operation. The two interrupts I am using are irq3 for the port A external interrupt and irq23 for Timer4. Is it possible that when the Timer4 Update/Overflow interrupt fires, it acts as an external interrupt and thus wakes the device Which would force the MCU to come out of halt mode every time timer4 hits. If this is so, how can I disable only the Timer4 interrupt and then re-enable that interrupt when the port A external interrupt fires (which is when the device is supposed to wake up).

Relevant section of main.c:

void Init_Tim4(void) {
    TIM4_IER  = 0x01;
    TIM4_EGR  = 0x01;
    TIM4_PSCR = 0x04;
    TIM4_ARR  = 0x30;
    TIM4_CNTR = 0xff;
    TIM4_CR1  = 0x01;
}
 
void Init_GPIO(void) {
    PA_DDR = 0x08;
    PA_CR1 = 0x0C;
    PA_CR2 = 0x00;
 
    PC_DDR = 0xa8;
    PC_CR1 = 0xa8;
    PC_CR2 = 0x00;
 
    PD_DDR = 0x10;
    PD_CR1 = 0x0f;
    PD_CR2 = 0x00;
}
 
void main(void) {
    unsigned char i;
    Init_GPIO();
    Init_Tim4();
    in_halt_mode = false;
    _asm("rim");
    red_LED   = 1;
    halt_counter = 0;
    while (1) {
        // Enter sleep mode after 1 minute
        if (halt_counter++ >= 300) {
            // Turn LED off for 2.5s
            red_LED = 1;
            for (i = 1; i < 50; i++) {
                DelayMS(50);
            }
            red_LED = 0;
            in_halt_mode = true;
            _asm("wfi");
        }
        for (i = 1; i < 4; i++) {
            DelayMS(50);
        }
    }
}
 
/*
 * Port A Halt Mode External Interrupt - Wake the device
 */
@far @interrupt void extia_int(void)
{
    if (in_halt_mode == true) {
        in_halt_mode = false;
        halt_counter = 0;
        _asm("iret");
    }
}
 
/*
 * LED Blinking - Timer 4 Overflow Interrupt 
 */
@far @interrupt void TIM4_UPD_OVF_IRQHandler(void) {
    TIM4_SR = 0x00;
    time_us++;
    if (time_us == 100) {
        time_us = 0;
        if ((time_ms++) >= 61) {
            time_ms = 0;
        }
        if (time_led == 1) {
            if (time_ms == 12) {
                time_ms = 0;
                red_LED = !red_LED;
            }
        }
        if (time_led == 2) {
            if (time_ms == 27) {
                time_ms = 0;
                red_LED = !red_LED;
            }
        }
        if (time_led == 3) {
            if (time_ms == 55) {
                time_ms = 0;
                red_LED = !red_LED;
            }
        }
    }
}

stm8_interrupt_vector.c:

/*	BASIC INTERRUPT VECTOR TABLE FOR STM8 devices
 *	Copyright (c) 2007 STMicroelectronics
 */
 
typedef void @far (*interrupt_handler_t)(void);
 
struct interrupt_vector {
	unsigned char interrupt_instruction;
	interrupt_handler_t interrupt_handler;
};
 
@far @interrupt void NonHandledInterrupt (void)
{
	/* in order to detect unexpected events during development, 
	   it is recommended to set a breakpoint on the following instruction
	*/
	return;
}
 
extern @far @interrupt void extia_int(void);
extern @far @interrupt void TIM4_UPD_OVF_IRQHandler(void);
//extern @far @interrupt void TIM1_timecont  (void);
extern void _stext();     /* startup routine */
 
struct interrupt_vector const _vectab[] = {
	{0x82, (interrupt_handler_t)_stext}, /* reset */
	{0x82, NonHandledInterrupt}, /* trap  */
	{0x82, NonHandledInterrupt}, /* irq0  */
	{0x82, NonHandledInterrupt}, /* irq1  */
	{0x82, NonHandledInterrupt}, /* irq2  */
	{0x82, extia_int}, /* irq3  */
	{0x82, NonHandledInterrupt}, /* irq4  */
	{0x82, NonHandledInterrupt}, /* irq5  */
	{0x82, NonHandledInterrupt}, /* exitd_int  */
	{0x82, NonHandledInterrupt}, /* irq7  */
	{0x82, NonHandledInterrupt}, /* irq8  */
	{0x82, NonHandledInterrupt}, /* irq9  */
	{0x82, NonHandledInterrupt}, /* irq10 */
	{0x82, NonHandledInterrupt}, /* TIM1_timecont */
	{0x82, NonHandledInterrupt}, /* irq12 */
	{0x82, NonHandledInterrupt}, /* TIM2_UPD_OVF_IRQHandler */
	{0x82, NonHandledInterrupt}, /* TIM2_comp */
	{0x82, NonHandledInterrupt}, /* irq15 */
	{0x82, NonHandledInterrupt}, /* irq16 */
	{0x82, NonHandledInterrupt}, /* irq17 */
	{0x82, NonHandledInterrupt}, /* irq18 */
	{0x82, NonHandledInterrupt}, /* irq19 */
	{0x82, NonHandledInterrupt}, /* irq20 */
	{0x82, NonHandledInterrupt}, /* irq21 */
	{0x82, NonHandledInterrupt}, /* irq22 */
	{0x82, TIM4_UPD_OVF_IRQHandler}, /* irq23 */
	{0x82, NonHandledInterrupt}, /* irq24 */
	{0x82, NonHandledInterrupt}, /* irq25 */
	{0x82, NonHandledInterrupt}, /* irq26 */
	{0x82, NonHandledInterrupt}, /* irq27 */
	{0x82, NonHandledInterrupt}, /* irq28 */
	{0x82, NonHandledInterrupt}, /* irq29 */
};

1 REPLY 1
JEREMYB
Associate

Okay, I figured out I can disable the Timer4 interrupt with TIM4_IER = 0x00; and then reinitialize it with TIM4_IER = 0x01; in the ISR.

Also, I figured out I was not initializing PA2 as an external interrupt, so I changed PA_CR2 = 0x00; to PA_CR2 = 0x04;

Thanks again to the community, without writing the problem out, I don't think I could have solved the issue myself.