Interrupt STM8s issue with SDCC compiler - makefile
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
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.
Related
Stupid Sort of uint16_t halfwords?
This is the first code for sorting whole signed words (int32_t): sort: SUB R1,R1,#1 //--n void StupidSort(int a[], int n) ADD R12,R0,#4 //нач.адрес+4 { ADD R1,R0,R1,LSL#2 //краен адрес int tmp, i = 0; L1: LDR R3,[R0] //*a do { LDR R2,[R0,#4]! //*++a ___ if (a[i] > a[i+1]) { CMP R3,R2 // \ tmp = a[i+1]; BLE L2 // \ a[i+1] = a[i]; STMDA R0,{R2,R3} // \ a[i] = tmp; CMP R0,R12 // \ if (i) i--; SUBHI R0,R0,#8 // \___ } else i++; L2: CMP R0,R1 // } while (i < n - 1); BLT L1 // } BX LR This is what I have done until now: sort: SUB R1,R1,#1 //--n void StupidSort(int a[], int n) ADD R12,R0,#2 //нач.адрес+4 { ADD R1,R0,R1,LSL#1 //краен адрес int tmp, i = 0; L1: LDRH R3,[R0] //*a do { LDRH R2,[R0,#2]! //*++a ___ if (a[i] > a[i+1]) { CMP R3,R2 // \ tmp = a[i+1]; BLE L2 // \ a[i+1] = a[i]; STRH R2,[R0,#2] STRH R3,[R0] // \ a[i] = tmp; CMP R0,R12 // \ if (i) i--; SUBHI R0,R0,#4 // \___ } else i++; L2: CMP R0,R1 // } while (i < n - 1); BLT L1 // } BX LR I tried to change it to sort uint16_t unsigned halfwords. I'm almost done but something is missing in the code. The problem is the sort, the architecture is ARM (in ARM mode, not Thumb);Also i don't know what the sign ! behind LDRH function do also i think on ldrd r3 and r2 should rotate their places.
The ! stands for pre-increment, exactly as in the comment *++a. Thus, the offset #2 is added to the base r0 before memory access, but also the register r0 is updated. L1: LDRH R3,[R0] //*a do { LDRH R2,[R0,#2]! //*++a ___ if (a[i] > a[i+1]) { CMP R3,R2 // \ tmp = a[i+1]; BLE L2 // \ a[i+1] = a[i]; STRH R2,[R0,#-2] // *** \ STRH R3,[R0] // *** \ a[i] = tmp; CMP R0,R12 // \ if (i) i--; SUBHI R0,R0,#4 // \___ } else i++; L2: CMP R0,R1 // } while (i < n - 1); The sections marked with *** have been modified to compensate the effect of *++a; Generally there are probably better ways to implement an insertion or bubble sort; this algorithms e.g. reads the same element in the next round which was written on the previous iteration. Also it would probably make more sense to use conditional swap/move instead of explicit branch. The corresponding 32-bit code writes the swapped values with a clever (obfuscated) way with STMDA R0,{R2,R3}, which relies on the R2, R3 having been read in the order of R3, R2. This instruction stands for STore Multiple, Decrement After, writing R2 to R0 - 4 and R3 to R0. But because that variant is not available for 16-bit registers, one needs to write R2 to R0 - 2 and R3 to R0.
C getting a raw keypress with no stdlib
I am working an a very basic operating system for a learning experience, and I am trying to start with key presses. I am making a freestanding executable, so no standard library. How would I go about taking input from a keyboard? I have figured out how to print to the screen through video memory. /* * kernel.c * */ void cls(int line) { // clear the screen char *vidptr = (char*) 0xb8000; /* 25 lines each of 80 columns; each element takes 2 bytes */ unsigned int x = 0; while (x < 80 * 25 * 2) { // blank character vidptr[x] = ' '; // attribute-byte - light grey on black screen x += 1; vidptr[x] = 0x07; x += 1; } line = 0; } void printf(const char *str, int line, char attr) { // write a string to video memory char *vidptr = (char*) 0xb8000; unsigned int y =0, x = 0; while (str[y] != '\0') { // the character's ascii vidptr[x] = str[y]; x++; // attribute byte - give character black bg and light gray fg vidptr[x+1] = attr; x++; y++; } } void kmain(void) { unsigned int line = 0; cls(line); printf("Testing the Kernel", line, 0x0a); } and my assembly: ;; entry point bits 32 ; nasm directive - 32 bit global entry extern _kmain ; kmain is defined in the c file section .text entry: jmp start ;multiboot spec align 4 dd 0x1BADB002 ; black magic dd 0x00 ; flags dd -(0x1BADB002 + 0x00) ; checksum. m+f+c should be zero start: cli ; block interrupts mov esp, stack_space ; set stack pointer call _kmain hlt ; halt the CPU section .bss resb 8192 ; 8KB for stack stack_space:
How the LLVM handle the debug location information of continue keyword and right brace?
Let me show you the following simple C code: int main() { int i; for (i = 0; i < 256; i++) { i++; } } In this simple C code, if we use Clang to compile it and debug it: We will get something like this: (gdb) b main Breakpoint 1 at 0x100000f7b: file a.c, line 5. (gdb) r Starting program: a.out [New Thread 0x1403 of process 23435] warning: unhandled dyld version (15) Thread 2 hit Breakpoint 1, main () at a.c:5 5 for (i = 0; i < 256; i++) (gdb) n 7 i++; (gdb) 5 for (i = 0; i < 256; i++) (gdb) 7 i++; That is to say, the right brace of location LLVM doesn't emit. However if we have the continue keyword: int main() { int i; for (i = 0; i < 256; i++) { continue; i++; } } Then we compile and debug it: Thread 2 hit Breakpoint 1, main () at a.c:5 5 for (i = 0; i < 256; i++) (gdb) n 7 continue; (gdb) 5 for (i = 0; i < 256; i++) (gdb) 7 continue; (gdb) 5 for (i = 0; i < 256; i++) (gdb) 7 continue; We will stop the line of continue. But if we compare the LLVM IR between them: The right brace and continue keyword both are the following the br instruction and !dbg !23. Except that the line number of !dbg !23 not the same. ; :6: ; preds = %3 br label %7, !dbg !23 The question is how LLVM know whether to generate the debug location(generate for the continue keyword line, but not for the loop's right brace)? Because they are the same instruction and others are the same.
The brace is just a syntactic scope, there is no difference for the compiler between: for (i = 0; i < 256; i++) { i++; } and for (i = 0; i < 256; i++) i++; The parser is using the scope you create to group statement together, but this will not appear in the LLVM IR. The LLVM IR represent more the instructions that the program needs to execute. When you using n in a debugger, you are asking to continue executing the program until you reach an instruction that corresponds to a different source line. The brace does not correspond to any instruction in the executable.
" Invalid expression" Error for bulian in MiKroc For AVR
I am writing one ds1307 timer with MiKroc For AVR so my code is : // Lcd module connections sbit LCD_RS at PORTC2_bit ; sbit LCD_EN at PORTC3_bit; sbit LCD_D4 at PORTC4_bit ; sbit LCD_D5 at PORTC5_bit ; sbit LCD_D6 at PORTC6_bit ; sbit LCD_D7 at PORTC7_bit ; sbit LCD_RS_Direction at DDC2_bit; sbit LCD_EN_Direction at DDC3_bit; sbit LCD_D4_Direction at DDC4_bit; sbit LCD_D5_Direction at DDC5_bit; sbit LCD_D6_Direction at DDC6_bit; sbit LCD_D7_Direction at DDC7_bit; int Temp1; int Temp2; int Temp3; unsigned short Temp4; #define inc(x) x=x+1; #define lo(x) Lo(x); #define hi(x) Hi(x); #define and &&; #define mod %; #define Mod %; #define div /; #define or ||; void shamsi_to_milady(int ShamsiMonth,int ShamsiDay,int ShamsiYear ) { // Declare a constant array which holds number of days in each month: //const Gmonth_a as byte[12] = (31,28,31,30,31,30,31,31,30,31,30,31) int miladiYear2,miladiYear,marchDayDiff,Temp5,remainDay ; int farvardin1st_iMonth; int farvardin1st_iDay; int dayCount; int i ; //dim miladiDate_iMonth,miladiDate_iDay,miladiDate_iYear as integer char Mmonth_a[12]; //const char ss=1; /* struct farvardin1st_2 { int iMonth; int iDay ; } */ //ss=1; //const Mmonth_a as byte[12] = (30,31,30,31,31,30,31,30,31,31,28,31) Mmonth_a[1] = 30 ; Mmonth_a[2] = 31; Mmonth_a[3] = 30 ; Mmonth_a[4] = 31 ; Mmonth_a[5] = 31 ; Mmonth_a[6] = 30 ; Mmonth_a[7] = 31 ; Mmonth_a[8] = 30 ; Mmonth_a[9] = 31 ; Mmonth_a[10] = 31 ; Mmonth_a[11] = 28; Mmonth_a[12] = 31; miladiYear = ShamsiYear + 621; miladiYear2=miladiYear; Temp1 = miladiYear2 % 4; Temp2 = miladiYear2 % 100; Temp3 = miladiYear2 % 400; Temp4 = (( Temp2 <> 0) && (Temp1 = 0)); Temp5=((Temp2 = 0) && (Temp3 == 0) ); } void main() { Lcd_Init() ; Lcd_Cmd(_LCD_CLEAR); // Clear display Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off Lcd_Out(1,6,txtw); } i got error in this line: Temp4 = (( Temp2 <> 0) && (Temp1 = 0)); this error: Invalid expression I think the error must be from miss matching in variables. main code is in attachment. Thanks a lot. Attachments: file
Temp4 = (( Temp2 <> 0) && (Temp1 = 0)); must be : Temp4 = (( Temp2 != 0) && (Temp1 == 0));
Compile error: Kernel module
I am a newbie at kernel programming & I wish to run this kernel module (posted below)... and i ran the makefile (posted below) for that, but I am getting the following errors: Can someone please help me understand how to overcome this: The kernel program should run error free as it is taken from Intel's implementation: obj-m += hello-1.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean This is the error: snehil#ubuntu:~/Desktop/measure$ make make -C /lib/modules/3.0.0-12-generic/build M=/home/snehil/Desktop/measure modules make[1]: Entering directory `/usr/src/linux-headers-3.0.0-12-generic' CC [M] /home/snehil/Desktop/measure/measure1.o /home/snehil/Desktop/measure/measure1.c: In function ‘hello_start’: /home/snehil/Desktop/measure/measure1.c:108:2: error: implicit declaration of function ‘kmalloc’ [-Werror=implicit-function-declaration] /home/snehil/Desktop/measure/measure1.c:108:8: warning: assignment makes pointer from integer without a cast [enabled by default] /home/snehil/Desktop/measure/measure1.c:115:11: warning: assignment makes pointer from integer without a cast [enabled by default] /home/snehil/Desktop/measure/measure1.c:124:12: warning: assignment makes pointer from integer without a cast [enabled by default] /home/snehil/Desktop/measure/measure1.c:130:13: warning: assignment makes pointer from integer without a cast [enabled by default] cc1: some warnings being treated as errors make[2]: *** [/home/snehil/Desktop/measure/measure1.o] Error 1 make[1]: *** [_module_/home/snehil/Desktop/measure] Error 2 make[1]: Leaving directory `/usr/src/linux-headers-3.0.0-12-generic' make: *** [all] Error 2 snehil#ubuntu:~/Desktop/measure$ gcc measure1 gcc: error: measure1: No such file or directory gcc: fatal error: no input files compilation terminated. This is the kernel module code: #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/hardirq.h> #include <linux/preempt.h> #include <linux/sched.h> #define SIZE_OF_STAT 100000 #define BOUND_OF_LOOP 1000 #define UINT64_MAX (18446744073709551615ULL) void inline Filltimes(uint64_t **times) { unsigned long flags; int i, j; uint64_t start, end; unsigned cycles_low, cycles_high, cycles_low1, cycles_high1; volatile int variable = 0; asm volatile ("CPUID\n\t" "RDTSC\n\t" "mov %%edx, %0\n\t" "mov %%eax, %1\n\t": "=r" (cycles_high), "=r" (cycles_low)::"%rax", "%rbx", "%rcx", "%rdx"); asm volatile ("CPUID\n\t" "RDTSC\n\t" "CPUID\n\t" "RDTSC\n\t" "mov %%edx, %0\n\t" "mov %%eax, %1\n\t": "=r" (cycles_high), "=r" (cycles_low):: "%rax", "%rbx", "%rcx", "%rdx"); asm volatile ("CPUID\n\t" "RDTSC\n\t"::: "%rax", "%rbx", "%rcx", "%rdx"); for (j=0; j<BOUND_OF_LOOP; j++) { for (i =0; i<SIZE_OF_STAT; i++) { variable = 0; preempt_disable(); raw_local_irq_save(flags); asm volatile ( "CPUID\n\t" "RDTSC\n\t" "mov %%edx, %0\n\t" "mov %%eax, %1\n\t": "=r" (cycles_high), "=r" (cycles_low):: "%rax", "%rbx", "%rcx", "%rdx"); /*call the function to measure here*/ asm volatile( "CPUID\n\t" "RDTSC\n\t" "mov %%edx, %0\n\t" "mov %%eax, %1\n\t": "=r" (cycles_high1), "=r" (cycles_low1):: "%rax", "%rbx", "%rcx", "%rdx"); raw_local_irq_restore(flags); preempt_enable(); start = ( ((uint64_t)cycles_high << 32) | cycles_low ); end = ( ((uint64_t)cycles_high1 << 32) | cycles_low1 ); if ( (end - start) < 0) { printk(KERN_ERR "\n\n>>>>>>>>>>>>>> CRITICAL ERROR IN TAKING THE TIME!!!!!!\n loop(%d) stat(%d) start = %llu, end = %llu, variable = %u\n", j, i, start, end, variable); times[j][i] = 0; } else { times[j][i] = end - start; } } } return; } uint64_t var_calc(uint64_t *inputs, int size) { int i; uint64_t acc = 0, previous = 0, temp_var = 0; for (i=0; i< size; i++) { if (acc < previous) goto overflow; previous = acc; acc += inputs[i]; } acc = acc * acc; if (acc < previous) goto overflow; previous = 0; for (i=0; i< size; i++){ if (temp_var < previous) goto overflow; previous = temp_var; temp_var+= (inputs[i]*inputs[i]); } temp_var = temp_var * size; if (temp_var < previous) goto overflow; temp_var =(temp_var - acc)/(((uint64_t)(size))*((uint64_t)(size))); return (temp_var); overflow: printk(KERN_ERR "\n\n>>>>>>>>>>>>>> CRITICAL OVERFLOW ERROR IN var_calc!!!!!!\n\n"); return -EINVAL; } static int __init hello_start(void) { int i = 0, j = 0, spurious = 0, k =0; uint64_t **times; uint64_t *variances; uint64_t *min_values; uint64_t max_dev = 0, min_time = 0, max_time = 0, prev_min =0, tot_var=0, max_dev_all=0, var_of_vars=0, var_of_mins=0; printk(KERN_INFO "Loading hello module...\n"); times = kmalloc(BOUND_OF_LOOP*sizeof(uint64_t*), GFP_KERNEL); if (!times) { printk(KERN_ERR "unable to allocate memory for times\n"); return 0; } for (j=0; j<BOUND_OF_LOOP; j++) { times[j] = kmalloc(SIZE_OF_STAT*sizeof(uint64_t), GFP_KERNEL); if (!times[j]) { printk(KERN_ERR "unable to allocate memory for times[%d]\n", j); for (k=0; k<j; k++) kfree(times[k]); return 0; } } variances = kmalloc(BOUND_OF_LOOP*sizeof(uint64_t), GFP_KERNEL); if (!variances) { printk(KERN_ERR "unable to allocate memory for variances\n"); return 0; } min_values = kmalloc(BOUND_OF_LOOP*sizeof(uint64_t), GFP_KERNEL); if (!min_values) { printk(KERN_ERR "unable to allocate memory for min_values\n"); return 0; } Filltimes(times); for (j=0; j<BOUND_OF_LOOP; j++) { max_dev = 0; min_time = 0; max_time = 0; for (i =0; i<SIZE_OF_STAT; i++) { if ((min_time == 0)||(min_time > times[j][i])) min_time = times[j][i]; if (max_time < times[j][i]) max_time = times[j][i]; } max_dev = max_time - min_time; min_values[j] = min_time; if ((prev_min != 0) && (prev_min > min_time)) spurious++; if (max_dev > max_dev_all) max_dev_all = max_dev; variances[j] = var_calc(times[j], SIZE_OF_STAT); tot_var += variances[j]; printk(KERN_ERR "loop_size:%d >>>> variance(cycles): %llu; max_deviation: %llu ;min time: %llu", j, variances[j], max_dev, min_time); prev_min = min_time; } var_of_vars = var_calc(variances, BOUND_OF_LOOP); var_of_mins = var_calc(min_values, BOUND_OF_LOOP); printk(KERN_ERR "\n total number of spurious min values = %d", spurious); printk(KERN_ERR "\n total variance = %llu", (tot_var/BOUND_OF_LOOP)); printk(KERN_ERR "\n absolute max deviation = %llu", max_dev_all); printk(KERN_ERR "\n variance of variances = %llu", var_of_vars); printk(KERN_ERR "\n variance of minimum values = %llu", var_of_mins); for (j=0; j<BOUND_OF_LOOP; j++) { kfree(times[j]); } kfree(times); kfree(variances); kfree(min_values); return 0; } static void __exit hello_end(void) { printk(KERN_INFO "Goodbye Mr.\n"); } module_init(hello_start); module_exit(hello_end);
If you are using kmalloc or kzalloc() for memory allocation you have to include #include<linux/slab.h>. They are called as slab allocators, these slab are chunks i.e. "cache" present in RAM and are physically contiguous. These slab allocator use underlying "Buddy System Algorithm", buddy allocator to provide more fine-grained allocation. Fore more referrence go through the below link: http://en.wikipedia.org/wiki/Slab_allocation http://en.wikipedia.org/wiki/Buddy_algorithm Hope this answers your question!!!!!.
You haven't included the header for kmalloc. Add #include <linux/slab.h> to your code.