makefilelinkerinterruptsdccstm8

Interrupt STM8s issue with SDCC compiler


I want to use interrupts on the SMT8S003K3 (STM8SVL-DISCOVERY) and somehow it does not get recognized when I use the interrupt on a other file where my main() is located.

I made two tests: - first I modified this code to Standard Peripheral Library:

uint8_t main(){
      CLK->CKDIVR=0;
     TIM1->PSCRH=0;
     TIM1->PSCRL=0x80;
     TIM1->CR1=1;
     TIM1->IER=1;

     GPIOD->DDR = 1;
     GPIOD->CR1 = 1;
     enableInterrupts();

     while(1){
     }
}

void TIM1_overflow_Handler() __interrupt(11)
{
  TIM1->SR1 &= ~1; //reset interrupt
  GPIOD->ODR ^= 1; //toggle LED
}

and it works...

Now to use UnitTests I putted this function into an other file: main_internal (just a simple example):

#ifdef STM8S003
#include "stm8s.h"
#endif
#include "main_internal.h"

void main_internal() {

     CLK->CKDIVR=0;
     TIM1->PSCRH=0;
     TIM1->PSCRL=0x80;
     TIM1->CR1=1;
     TIM1->IER=1;
     GPIOD->DDR = 1;
     GPIOD->CR1 = 1;
     enableInterrupts();

     while(1){
     }
}

void TIM1_overflow_Handler() __interrupt(11)
{
  TIM1->SR1 &= ~1; //reset interrupt
  GPIOD->ODR ^= 1; //toggle LED
}

with the main function:

#include "main_internal.h"

int main(){
  main_internal();
  return 0;
}

and it does nothing... well it flows around in the deep memory of the STM8S003 (as I have seen with the debugger). Is this a linking issue?

This is my Makefile:

ST_TARGET      = main
INCLUDEDIR  = Libraries/inc include
ST_LIBSRCDIR   = Libraries/src
#ST_LIBSRC      = $(ST_LIBSRCDIR)/stm8s_adc1.c  $(ST_LIBSRCDIR)/stm8s_awu.c
#ST_LIBSRC     += $(ST_LIBSRCDIR)/stm8s_beep.c  $(ST_LIBSRCDIR)/stm8s_clk.c
#ST_LIBSRC     += $(ST_LIBSRCDIR)/stm8s_exti.c  $(ST_LIBSRCDIR)/stm8s_flash.c
#ST_LIBSRC     += $(ST_LIBSRCDIR)/stm8s_gpio.c  $(ST_LIBSRCDIR)/stm8s_i2c.c
#ST_LIBSRC     += $(ST_LIBSRCDIR)/stm8s_itc.c   $(ST_LIBSRCDIR)/stm8s_iwdg.c
#ST_LIBSRC     += $(ST_LIBSRCDIR)/stm8s_rst.c   $(ST_LIBSRCDIR)/stm8s_spi.c
#ST_LIBSRC     += $(ST_LIBSRCDIR)/stm8s_tim1.c  $(ST_LIBSRCDIR)/stm8s_wwdg.c

SRC_DIR        = src
SRC_ALL = $(shell find -L $(SRC_DIR) -name '*.c')

SRCS = $(filter-out $(SRC_DIR)/$(ST_TARGET).c,$(SRC_ALL))

ST_OBJS        = $(ST_LIBSRC:.c=.rel)
ST_LIB_FILES := $(addprefix $(ST_BUILD_DIR)/,$(notdir $(ST_OBJS)))
LIBD_FILES := $(addprefix $(ST_DEBUG_DIR)/,$(notdir $(ST_OBJS)))
PR_ST_OBJS       = $(SRCS:.c=.rel)
ST_SRC_FILES := $(addprefix $(ST_BUILD_DIR)/,$(notdir $(PR_ST_OBJS)))
SRCD_FILES := $(addprefix $(ST_DEBUG_DIR)/,$(notdir $(PR_ST_OBJS)))
ST_OBJS += $(PR_ST_OBJS)
STD_OBJS= $(ST_OBJS)
MCU         = STM8S003
ST_COMPILER    = __SDCC__
DEFINES     = -D$(ST_COMPILER) -D$(MCU) -DUSE_STDPERIPH_DRIVER

ST_CFLAGS      = -mstm8 $(DEFINES)
ST_LDFLAGS     = $(addprefix -I ,$(INCLUDEDIR))
ST_DEBUG_FLAGS =  --out-fmt-elf --all-callee-saves --debug --stack-auto --fverbose-asm --float-reent --no-peep

IHX         = $(ST_BUILD_DIR)/$(ST_TARGET).ihx
ELF         = $(ST_DEBUG_DIR)/$(ST_TARGET).elf

$(info $$ srcfiles is [${ST_OBJS}])
$(info $$ srcfiles is [${LIBD_FILES}])
ifdef st-debug
        ST_OUT_DIR=$(ST_DEBUG_DIR)
else
        ST_OUT_DIR=$(ST_BUILD_DIR)
endif

################### BUILD PROCESS ###################
.PHONY: all st-build st-clean st-flash st-debug st-wipe

#all: clean st-build
st: st-clean st-build st-flash

st-debug: $(STD_OBJS) $(ELF)# ST_CFLAGS+=$(ST_DEBUG_FLAGS)
st-debug: ST_CFLAGS+=$(ST_DEBUG_FLAGS)
st-debug: ST_OUT_DIR=$(ST_DEBUG_DIR)
$(STD_OBJS): 

$(ELF): $(SRC_DIR)/$(ST_TARGET).c
        @echo $(ST_OUT_DIR)
        #ST_CFLAGS += $(ST_DEBUG_FLAGS)
        $(ST_CC) $(ST_CFLAGS) $(ST_LDFLAGS) -o $(ST_OUT_DIR)/ $< $(SRCD_FILES) $(LIBD_FILES)
        $(SIZE) $@
        $(SIZE) $@ >> $(MEMORY_USAGE_DIR)/$(MEMORY_USAGE)
        @echo Success!!!!\\n\\n
st-build: $(ST_OBJS) $(IHX)

$(ST_OBJS): 

$(IHX): $(SRC_DIR)/$(ST_TARGET).c $(SRCS:.c)
        $(ST_CC) $(ST_CFLAGS) $(ST_LDFLAGS) -o $(ST_OUT_DIR)/ $< $(ST_SRC_FILES) $(ST_LIB_FILES)
        $(SIZE) $@
        $(SIZE) $@ >> $(MEMORY_USAGE_DIR)/$(MEMORY_USAGE)
        @echo Success!!!!\\n\\n

This would be the code without Standard Peripheral library:

#include <stdint.h>

#define CLK_DIVR    (*(volatile uint8_t *)0x50C6)

#define TIM1_CR1    (*(volatile uint8_t *)0x5250)
#define TIM1_IER    (*(volatile uint8_t *)0x5254)
#define TIM1_SR1    (*(volatile uint8_t *)0x5255)
#define TIM1_CNTRH    (*(volatile uint8_t *)0x525E)
#define TIM1_CNTRL    (*(volatile uint8_t *)0x525F)
#define TIM1_PSCRH    (*(volatile uint8_t *)0x5260)
#define TIM1_PSCRL    (*(volatile uint8_t *)0x5261)

#define PD_ODR    (*(volatile uint8_t *)0x500f)
#define PD_DDR    (*(volatile uint8_t *)0x5011)
#define PD_CR1    (*(volatile uint8_t *)0x5012)

void main(void)
{
     CLK_DIVR = 0x00; // Set the frequency to 16 MHz

     TIM1_PSCRH = 0x00; // Configure timer
     TIM1_PSCRL = 0x80;

     TIM1_CR1 = 0x01; //Enable timer
     TIM1_IER = 0x01; //Enable interrupt - update event

     PD_DDR = 1;
     PD_CR1 = 1;
     __asm__ ("rim");

     while(1){
     }
}

void TIM1_overflow_Handler() __interrupt(11)
{
     TIM1_SR1 &= ~1; //reset interrupt
     PD_ODR ^= 1; //toggle LED
}

Here I have a diff from gdb of the two versions:

15c15
< 00008034:   int     0x0080d7 ;0x80d7 <TIM1_overflow_Handler>
---
> 00008034:   int     0x000000
44c44
< 00008098:   ld      A,(0x80fd,X) ;0x80fd <TIM1_overflow_Handler+38>
---
> 00008098:   ld      A,(0x8114,X) ;0x8114 <TIM1_overflow_Handler+38>
54c54
<  27              CLK_DIVR = 0x00; // Set the frequency to 16 MHz
---
>  8          main_internal();
56,163c56,136
< 000080b1:   neg     (0x50,SP) ;0x50
< 000080b3:   ld      A,0x3500 ;0x3500
<  29              TIM1_PSCRH = 0x00; // Configure timer
< 000080b4:   mov     0x0052,#0x60 ;0x60
<  30              TIM1_PSCRL = 0x80;
< 000080b8:   mov     0x8052,#0x61 ;0x61
<  32              TIM1_CR1 = 0x01; //Enable timer
< 000080bc:   mov     0x0152,#0x50 ;0x50
<  33              TIM1_IER = 0x01; //Enable interrupt - update event
< 000080c0:   mov     0x0152,#0x54 ;0x54
<  35              PD_DDR = 1;
< 000080c4:   mov     0x0150,#0x11 ;0x11
<  36              PD_CR1 = 1;
< 000080c8:   mov     0x0150,#0x12 ;0x12
<  37              __asm__ ("rim");
< 000080cc:   rim     
<  39              while(1){
< 000080cd:   jp      0x80cd ;0x80cd <main+41>
<  41         }
< 000080d0:   pop     0x0001 ;0x1
< 000080d3:   pop     0x0002 ;0x2
< 000080d6:   ret     
<  43         void TIM1_overflow_Handler() __interrupt(11)
<           TIM1_overflow_Handler:
< 000080d7:   push    0x0002 ;0x2
< 000080da:   push    0x0001 ;0x1
< 000080dd:   ldw     Y,SP
< 000080df:   ldw     0x0001,Y ;0x1
<  45              TIM1_SR1 &= ~1; //reset interrupt
< 000080e3:   ldw     X,#0x5255 ;0x5255
< 000080e6:   ld      A,(X)
< 000080e7:   and     A,#0xfe ;0xfe
< 000080e9:   ldw     X,#0x5255 ;0x5255
< 000080ec:   ld      (X),A
<  46              PD_ODR ^= 1; //toggle LED
< 000080ed:   ldw     X,#0x500f ;0x500f
< 000080f0:   ld      A,(X)
< 000080f1:   xor     A,#0x01 ;0x1
< 000080f3:   ldw     X,#0x500f ;0x500f
< 000080f6:   ld      (X),A
<  47         }
< 000080f7:   pop     0x0001 ;0x1
< 000080fa:   pop     0x0002 ;0x2
< 000080fd:   iret    
< 000080fe:   and     A,#0xfe ;0xfe
< 00008100:   ldw     X,#0x5255 ;0x5255
< 00008103:   ld      (X),A
< 00008104:   ldw     X,#0x500f ;0x500f
< 00008107:   ld      A,(X)
< 00008108:   xor     A,#0x01 ;0x1
< 0000810a:   ldw     X,#0x500f ;0x500f
< 0000810d:   ld      (X),A
< 0000810e:   pop     0x0001 ;0x1
< 00008111:   pop     0x0002 ;0x2
< 00008114:   iret    
< 00008115:   ld      (X),A
< 00008116:   ldw     X,#0x5230 ;0x5230
< 00008119:   ld      A,(X)
< 0000811a:   and     A,#0x80 ;0x80
< 0000811c:   cp      A,#0x80 ;0x80
< 0000811e:   jrne    0x8116 ;0x8116
< 00008120:   ret     
< 00008121:   jra     0x8116 ;0x8116
< 00008123:   ret     
< 00008124:   ldw     X,#0x5235 ;0x5235
< 00008127:   ld      A,(X)
< 00008128:   or      A,#0x20 ;0x20
< 0000812a:   ld      (X),A
< 0000812b:   ret     
< 0000812c:   ldw     X,#0x5235 ;0x5235
< 0000812f:   ld      A,(X)
< 00008130:   or      A,#0x20 ;0x20
< 00008132:   ld      (X),A
< 00008133:   ldw     X,#0x5230 ;0x5230
< 00008136:   ld      A,(X)
< 00008137:   and     A,#0xd0 ;0xd0
< 00008139:   ld      (X),A
< 0000813a:   ldw     X,#0x5231 ;0x5231
< 0000813d:   ld      A,(X)
< 0000813e:   ret     
< 0000813f:   sub     SP,#0x08 ;0x8
< 00008141:   mov     0x0050,#0xc6 ;0xc6
< 00008145:   mov     0x0052,#0x60 ;0x60
< 00008149:   mov     0x8052,#0x61 ;0x61
< 0000814d:   mov     0x0152,#0x50 ;0x50
< 00008151:   mov     0x0152,#0x54 ;0x54
< 00008155:   mov     0x0150,#0x11 ;0x11
< 00008159:   mov     0x0150,#0x12 ;0x12
< 0000815d:   rim     
< 0000815e:   ldw     X,#0x525e ;0x525e
< 00008161:   ld      A,(X)
< 00008162:   ldw     X,#0x5231 ;0x5231
< 00008165:   ld      (X),A
< 00008166:   ldw     X,#0x5230 ;0x5230
< 00008169:   ld      A,(X)
< 0000816a:   and     A,#0x80 ;0x80
< 0000816c:   cp      A,#0x80 ;0x80
< 0000816e:   jrne    0x8166 ;0x8166
< 00008170:   ldw     X,#0x1388 ;0x1388
< 00008173:   clr     (0x02,SP) ;0x2
< 00008175:   clr     (0x01,SP) ;0x1
< 00008177:   subw    X,#0x0001 ;0x1
< 0000817a:   ldw     (0x07,SP),X ;0x7
< 0000817c:   ld      A,(0x02,SP) ;0x2
< 0000817e:   sbc     A,#0x00
< 00008180:   ld      (0x06,SP),A ;0x6
< 00008182:   ld      A,(0x01,SP) ;0x1
< 00008184:   sbc     A,#0x00
---
> 000080b1:   iret    
> .........   add     A,0x5f ;0x5f
>  9          return 0;
> 000080b3:   clrw    X
> 10        }
> 000080b4:   pop     0x0001 ;0x1
> 000080b7:   pop     0x0002 ;0x2
> 000080ba:   ret     
>           main_internal:
> 000080bb:   push    0x0002 ;0x2
> 000080be:   push    0x0001 ;0x1
> 000080c1:   ldw     Y,SP
> 000080c3:   ldw     0x0001,Y ;0x1
> ......... ...
> 00ffffff:   neg     (0xa5,SP) ;0xa5
> 01000001:   cpl     (0xf9,SP) ;0xf9
> 01000003:   neg     (0xf7,SP) ;0xf7
> 01000005:   xor     A,0x6f ;0x6f
> 01000007:   cpw     X,#0xc9ac ;0xc9ac
> 0100000a:   scf     
> 0100000b:   int     0x1ee2a7 ;0x1ee2a7
> 0100000f:   sll     0x9b ;0x9b
> 01000011:   clr     (0x99,SP) ;0x99
> 01000013:   jrne    0xffffef ;0xffffef
> 01000015:           
> 01000016:   addw    SP,#0x11 ;0x11
> 01000018:   or      A,(0xaa,SP) ;0xaa
> 0100001a:   sim     
> 0100001b:   mul     X,A
> 0100001c:   xor     A,(0x3d,SP) ;0x3d
> 0100001e:   sub     A,0x63 ;0x63
> 01000020:   adc     A,0x53 ;0x53
> 01000022:   ld      (0xf8,SP),A ;0xf8
> 01000024:   push    0xd95c ;0xd95c
> 01000027:   pop     A
> 01000028:   sbc     A,(0x53,SP) ;0x53
> 0100002a:   cp      A,(0x3e,SP) ;0x3e
> 0100002c:   cpl     0x13 ;0x13
> 0100002e:   sra     (0xc0,X) ;0xc0
> 01000030:   call    (0xa2c9,X) ;0xa2c9
> 01000033:   ld      A,XH
> 01000034:   tnzw    X
> 01000035:   subw    X,#0x59cf ;0x59cf
> 01000038:   ld      (0x22,SP),A ;0x22
> 0100003a:   decw    X
> 0100003b:   cpl     (0xe9,X) ;0xe9
> 0100003d:   and     A,(0x7775,X) ;0x7775
> 01000040:   sub     A,(0x7e1c,X) ;0x7e1c
> 01000043:   xor     A,(X)
> 01000044:   clrw    X
> 01000045:   swap    0xd5 ;0xd5
> 01000047:   rlwa    X,A
> 01000048:   jreq    0x100006b ;0x100006b
> 0100004a:   inc     0x22 ;0x22
> 0100004c:           
> 0100004d:   sra     0xdf ;0xdf
> 0100004f:   cpw     X,#0xb73f ;0xb73f
> 01000052:   ld      (0x0566,X),A ;0x566
> 01000055:   sbc     A,#0x4c ;0x4c
> 01000057:   sll     (X)
> 01000058:   add     A,0x40 ;0x40
> 0100005a:   adc     A,#0x05 ;0x5
> 0100005c:   ld      (0xc2,SP),A ;0xc2
> 0100005e:   ld      XL,A
> 0100005f:   incw    X
> 01000060:   ldw     (0xc8fe,X),Y ;0xc8fe
> 01000063:   call    0x27e5 ;0x27e5
> 01000066:   ldw     X,(0xd0,X) ;0xd0
> 01000068:   cpw     X,0xc159 ;0xc159
> 0100006b:   mov     0xc5,0xe8 ;0xe8
> 0100006e:   cp      A,(X)
> 0100006f:   bcp     A,(0xcb,SP) ;0xcb
> 01000071:   cpw     Y,(X)
> 01000072:   xor     A,(X)
> 01000073:   pop     CC
> 01000074:   swap    (0x1b,SP) ;0x1b
> 01000076:   ldw     X,#0x44cc ;0x44cc
> 01000079:   div     X,A
> 0100007a:   rlc     A
> 0100007b:   sbc     A,0xa8 ;0xa8
> 0100007d:   inc     (0x9b,X) ;0x9b

Surprisingly the line: 00008034: int 0x0080d7 ;0x80d7 is missing in the second version in the main_internal.

Any help would be appreciated


Solution

  • facepalm

    I did not included the interrupt handler in the main_internal.h file:

    void TIM1_overflow_Handler() __interrupt(11);

    In the SDCC Compiler User Guide page 40 :

    If you have multiple source files in your project, interrupt service routines can be present in any of them, but a prototype of the isr MUST be present or included in the file that contains the function main.

    So be sure you always make your isr visible to the main function.