Skip to content

Commit 532191a

Browse files
committed
improved test function, assembler version of pinMode
- Hand-optimized version of pinMode works, 168 Bytes. More potential left. - Added a simulator target in the Makefile. - the test results are shown in the simulator memory dump
1 parent b75a79a commit 532191a

7 files changed

Lines changed: 274 additions & 25 deletions

File tree

docs/api/migration.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ names. The preprocessor does not allow for variable macro names. That means
9696
`_Generic` would work with fixed name like `Serial`, but it wouldn't work
9797
for `SoftwareSerial` with no standard instance name.
9898
99+
[This](https://mort.coffee/home/obscure-c-features/) is a good introduction
100+
into the use of `_Generic`.
99101
100102
101103

test/pinmode/Makefile

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
BASENAME=$(shell basename $$(pwd))
2-
EXECUTABLE=$(BASENAME).ihx
2+
EXECUTEABLE=$(BASENAME).ihx
33

44
#SDCCBASE=/usr/local
55
SDCCBASE=/opt/sdcc
@@ -23,11 +23,11 @@ SRCS=pinmode-c.c pinmode-asm.c main.c
2323
BUILDDIR=build
2424
OBJECTS=$(SRCS:%.c=$(BUILDDIR)/%.rel)
2525

26-
.PHONY: all clean flash statistics
26+
.PHONY: all clean flash statistics sim
2727

28-
all: $(EXECUTEABLE) statistics
28+
all: $(EXECUTEABLE) statistics sim
2929

30-
$(EXECUTABLE): $(OBJECTS)
30+
$(EXECUTEABLE): $(OBJECTS)
3131
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@
3232

3333
$(OBJECTS) : $(BUILDDIR)/%.rel : %.c
@@ -46,6 +46,12 @@ readopt:
4646
statistics: $(OBJECTS)
4747
cd $(BUILDDIR); awk '/ CODE/ {print FILENAME "\t" strtonum("0x"$$4)}' *.sym
4848

49+
sim: $(EXECUTEABLE)
50+
@. ./sim
51+
52+
# @. ./sim | grep "0x0001 00 00 00 00 00 00"
53+
# . ./sim | grep "0x0001 00 00 00 00 00 00" || echo "fail"
54+
4955

5056
# grep "[0-9] _" $(BASENAME).rst |\
5157
# awk 'BEGIN {print "length\tfunction\n------\t----------";}{ a=strtonum("0x"$$1);if (name) print a-s "\t" name; s=a; name=$$3}'

test/pinmode/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,33 @@ after first commit (176 bytes):
77
0081B4 269 _pinMode_asm:
88
008264 410 _setup:
99
00826E 424 _loop:
10+
11+
Reihenfolgen:
12+
INPUT |-CR2, -CR1, -DDR
13+
INPUT_PULLUP |-CR2, -DDR, +CR1
14+
OUTPUT_FAST |+CR1, +DDR, +CR2
15+
OUTPUT_OD_FAST |-CR1, +DDR, +CR2
16+
OUTPUT_OD |-CR1, -CR2, +DDR
17+
OUTPUT |+CR1, -CR2, +DDR
18+
19+
mode CR2
20+
21+
22+
sstm8 -tS003 -S uart=1,port=10000 mini.ihx
23+
24+
25+
CR1: pullup bzw. open-drain
26+
27+
CR2: in: INT, out: fast
28+
- input: als erstes reset
29+
- output: als letztes setzen (nach DDR)
30+
31+
32+
Schritt 1: CR2 (in: INT, out: fast)
33+
- set: OUTPUT_FAST, OUTPUT_OD_FAST
34+
- reset: sonst
35+
36+
37+
## Simulator
38+
39+
-i m: info memory

test/pinmode/main.c

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
/*
2-
* test spi functions
1+
/**
2+
* Test the optimized Versions of pinMode
3+
*
4+
* After each test the content of the GPIO registers is checked against
5+
* the expected values. The table results[] contains the number of mismatched
6+
* bytes after each test.
7+
*
8+
* Expected result: all bytes in results[] == 0x00
39
*/
410

511
#define ARDUINO_MAIN
@@ -9,44 +15,69 @@
915
void pinMode_c(uint8_t pin, uint8_t mode);
1016
void pinMode_asm(uint8_t pin, uint8_t mode);
1117

18+
// select which function should be used for the test
19+
#define pinMode_test pinMode_asm
20+
21+
uint8_t results[6];
1222

23+
/**
24+
* checks a memory area for an expected content
25+
*
26+
* @returns: number of mismatched bytes (0=ok)
27+
*/
1328
uint8_t checkresult(uint16_t adr, uint8_t *data)
1429
{
15-
uint8_t i,ok;
30+
uint8_t i,err;
1631

17-
ok = 1;
32+
err = 0;
1833
for (i=0; i<3; ++i) {
19-
if (((uint8_t*)adr)[2+i] != data[i]) ok=0;
34+
if (((uint8_t*)adr)[2+i] != data[i]) err++;
2035
}
21-
return ok;
36+
return err;
2237
}
2338

39+
/**
40+
* fills a memory area with zeros
41+
*
42+
* The simulator does not clear the memory and does not properly
43+
* initialize the IO registers after reset. Use this instead.
44+
*/
45+
void _memset(unsigned char *adr, unsigned int cnt)
46+
{
47+
while (cnt--) *adr++=0;
48+
}
2449

2550
void main(void)
2651
{
52+
unsigned char *r = results;
53+
54+
_memset((unsigned char *)GPIOA_BaseAddress, 20);
55+
2756
// expected result: xx xx 00 00 00
28-
pinMode_asm(PA1,INPUT);
29-
checkresult(GPIOA_BaseAddress, "\x00\x00\x00");
57+
pinMode_test(PA1,INPUT);
58+
*r++ = checkresult(GPIOA_BaseAddress, "\x00\x00\x00");
3059

3160
// expected result: xx xx 20 20 00
32-
pinMode_asm(PB5,OUTPUT);
33-
checkresult(GPIOB_BaseAddress, "\x20\x20\x00");
61+
pinMode_test(PB5,OUTPUT);
62+
*r++ = checkresult(GPIOB_BaseAddress, "\x20\x20\x00");
3463

3564
// expected result: xx xx 00 10 00
36-
pinMode_asm(PC4,INPUT_PULLUP);
37-
checkresult(GPIOC_BaseAddress, "\x00\x10\x00");
65+
pinMode_test(PC4,INPUT_PULLUP);
66+
*r++ = checkresult(GPIOC_BaseAddress, "\x00\x10\x00");
3867

3968
// expected result: xx xx 20 10 00
40-
pinMode_asm(PC5,OUTPUT_OD);
41-
checkresult(GPIOC_BaseAddress, "\x20\x10\x00");
69+
pinMode_test(PC5,OUTPUT_OD);
70+
*r++ = checkresult(GPIOC_BaseAddress, "\x20\x10\x00");
4271

4372
// expected result: xx xx 02 02 02
44-
pinMode_asm(PD1,OUTPUT_FAST);
45-
checkresult(GPIOD_BaseAddress, "\x02\x02\x02");
73+
pinMode_test(PD1,OUTPUT_FAST);
74+
*r++ = checkresult(GPIOD_BaseAddress, "\x02\x02\x02");
4675

4776
// expected result: xx xx 42 02 42
48-
pinMode_asm(PD6,OUTPUT_OD_FAST);
49-
checkresult(GPIOD_BaseAddress, "\x42\x02\x42");
77+
pinMode_test(PD6,OUTPUT_OD_FAST);
78+
*r++ = checkresult(GPIOD_BaseAddress, "\x42\x02\x42");
79+
80+
for(;;); // endless loop
5081
}
5182

5283
/*

test/pinmode/pinmode-asm.c

Lines changed: 168 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,173 @@
44

55
#include <stdint.h>
66

7+
#define DDR 2
8+
#define CR1 3
9+
#define CR2 4
10+
11+
#define BIT_CLEAR(REG) \
12+
ld a,yh\
13+
and a,(REG,x)\
14+
ld (REG,x),a
15+
16+
#define BIT_SET(REG) \
17+
ld a,yl\
18+
or a,(REG,x)\
19+
ld (REG,x),a
20+
21+
22+
void pinMode_asm(uint8_t pin, uint8_t mode)
23+
{
24+
(void) pin; // empty code to avoid warning
25+
(void) mode;
26+
__asm
27+
28+
; my optimized code
29+
; nicht mehr benötigte Stack-Variablen:
30+
; (0x01, sp) war bit
31+
; (0x07, sp) war port-ID
32+
; (0x08, sp) war port-ID
33+
34+
sub sp, #8
35+
; pinmode-c.c: 9: uint8_t bit = digitalPinToBitMask(pin);
36+
clrw x
37+
ld a, (0x0b, sp)
38+
ld 0x0100,a
39+
ld xl, a
40+
addw x, #(_digital_pin_to_bit_mask_PGM + 0)
41+
ld a, (x)
42+
ld 0x0101,a
43+
ld yl,a ; yl = bit
44+
cpl a
45+
ld yh,a ; yh = ~bit
46+
; pinmode-c.c: 10: uint8_t port = digitalPinToPort(pin);
47+
; es könnte auch subw x, #(NUM_DIGITAL_PINS) sein
48+
clrw x
49+
ld a, (0x0b, sp)
50+
ld xl, a
51+
addw x, #(_digital_pin_to_port_PGM + 0)
52+
ld a, (x) ; port-ID. Z-Flag wird gesetzt
53+
; pinmode-c.c: 13: if (port == NOT_A_PORT) return;
54+
; jreq 00118$
55+
56+
57+
;
58+
; Zuordung port-ID => Port-Addresse
59+
;
60+
61+
00102$:
62+
; pinmode-c.c: 15: gpio = (GPIO_TypeDef *) portOutputRegister(port);
63+
;******
64+
clrw x
65+
sll a ; 8 bit shift is sufficient
66+
ld xl, a
67+
addw x, #(_port_to_output_PGM + 0)
68+
ldw x, (x) ; jetzt ist gpio in x
69+
ldw 0x0102,x
70+
71+
72+
;
73+
; case INPUT
74+
;
75+
; pinmode-c.c: 17: if (mode == INPUT) {
76+
ld a, (0x0c, sp)
77+
jrne 00116$
78+
79+
; pinmode-c.c: 19: gpio->CR2 &= ~bit; // first: deactivate interrupt
80+
; pinmode-c.c: 20: gpio->CR1 &= ~bit; // release top side
81+
; pinmode-c.c: 21: gpio->DDR &= ~bit; // now set direction
82+
sim
83+
BIT_CLEAR(CR2)
84+
BIT_CLEAR(CR1)
85+
BIT_CLEAR(DDR)
86+
rim
87+
jp 00118$
88+
89+
;
90+
; case INPUT_PULLUP
91+
;
92+
00116$:
93+
; pinmode-c.c: 23: } else if (mode == INPUT_PULLUP) {
94+
cp a, #0x02
95+
jrne 00113$
96+
; pinmode-c.c: 25: gpio->CR2 &= ~bit; // first: deactivate interrupt
97+
; pinmode-c.c: 26: gpio->DDR &= ~bit; // set direction before
98+
; pinmode-c.c: 27: gpio->CR1 |= bit; // activating the pull up
99+
sim
100+
BIT_CLEAR(CR2)
101+
BIT_CLEAR(DDR)
102+
BIT_SET(CR1)
103+
rim
104+
jp 00118$
105+
106+
;
107+
; case OUTPUT_FAST
108+
;
109+
00113$:
110+
; pinmode-c.c: 29: } else if (mode == OUTPUT_FAST) {// output push-pull, fast
111+
cp a, #0x05
112+
jrne 00110$
113+
114+
; pinmode-c.c: 31: gpio->CR1 |= bit;
115+
; pinmode-c.c: 32: gpio->DDR |= bit; // direction before setting CR2 to
116+
; pinmode-c.c: 33: gpio->CR2 |= bit; // avoid accidental interrupt
117+
sim
118+
BIT_SET(CR1)
119+
jra 010$
120+
121+
;
122+
; case OUTPUT_OD_FAST
123+
;
124+
00110$:
125+
; pinmode-c.c: 35: } else if (mode == OUTPUT_OD_FAST) { // output open drain, fast
126+
cp a, #0x07
127+
jrne 00107$
128+
129+
; pinmode-c.c: 37: gpio->CR1 &= ~bit;
130+
; pinmode-c.c: 38: gpio->DDR |= bit; // direction before setting CR2 to
131+
; pinmode-c.c: 39: gpio->CR2 |= bit; // avoid accidental interrupt
132+
sim
133+
BIT_CLEAR(CR1)
134+
010$: BIT_SET(DDR)
135+
BIT_SET(CR2)
136+
rim
137+
jra 00118$
138+
139+
;
140+
; case OUTPUT_OD
141+
;
142+
00107$:
143+
; pinmode-c.c: 41: } else if (mode == OUTPUT_OD) { // output open drain, slow
144+
cp a, #0x03
145+
jrne 00104$
146+
147+
; pinmode-c.c: 43: gpio->CR1 &= ~bit;
148+
; pinmode-c.c: 44: gpio->CR2 &= ~bit;
149+
; pinmode-c.c: 45: gpio->DDR |= bit;
150+
sim
151+
BIT_CLEAR(CR1)
152+
jra 004$
153+
154+
;
155+
; case default
156+
;
157+
00104$:
158+
; pinmode-c.c: 49: gpio->CR1 |= bit;
159+
; pinmode-c.c: 50: gpio->CR2 &= ~bit;
160+
; pinmode-c.c: 51: gpio->DDR |= bit;
161+
sim
162+
BIT_SET(CR1)
163+
004$: BIT_CLEAR(CR2)
164+
BIT_SET(DDR)
165+
rim
166+
167+
00118$:
168+
; pinmode-c.c: 54: }
169+
addw sp, #8
170+
__endasm;
171+
}
172+
173+
/*
7174
void pinMode_asm(uint8_t pin, uint8_t mode)
8175
{
9176
(void) pin; // empty code to avoid warning
@@ -170,5 +337,4 @@ and a,(2,x)
170337
addw sp, #16
171338
__endasm;
172339
}
173-
174-
340+
*/

test/pinmode/pinmode-c.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ void pinMode_c(uint8_t pin, uint8_t mode)
1010
uint8_t port = digitalPinToPort(pin);
1111
volatile GPIO_TypeDef *gpio;
1212

13-
if (port == NOT_A_PIN) return;
13+
if (port == NOT_A_PORT) return;
1414

1515
gpio = (GPIO_TypeDef *) portOutputRegister(port);
1616

test/pinmode/sim

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/bash
2+
3+
sstm8 -t S103 pinmode.ihx << EOF
4+
fill ram_chip 0 1023 0
5+
fill io_chip 0 44 0
6+
s 10000
7+
du io_chip 0 4
8+
du io_chip 5 9
9+
du io_chip 10 14
10+
du io_chip 15 19
11+
du ram_chip 1 6
12+
du ram_chip 0x0100
13+
quit
14+
EOF

0 commit comments

Comments
 (0)