why isn’t it destroyed by interrupts?
The compiler arranges for registers W8-W15 to be preserved across ordinary function
calls. Registers W0-W7 are available as scratch registers. For interrupt functions, the
compiler arranges for all necessary registers to be preserved, namely W0-W15 and
RCOUNT.
#include <string.h>
#include <xc.h>
unsigned char framebuffer[1024]__attribute__((aligned (2)));
int main() {
memset(framebuffer,0,sizeof(framebuffer));
while(1) {
Nop();
}
return 0;
}
02E4 MOV W0,W3
02E6 BRA 0x2EC ;This points to three lines lower, 0x2EC is the absolute address
02E8 MOV.B W1, [W3++]
02EA DEC W2,W2
02EC CP0 W2
02EE BRA NZ, 0x2E8 ;This points to three lines UP
02F0 RETURN
02E4 MOV #0x1000, W0
02E6 REPEAT #0x1FF
02E8 CLR [W0++]
;memset(framebuffer,1,sizeof(framebuffer));
02E4 MOV #0x0101, W2
02E6 MOV #0x1000, W0
02E8 REPEAT #0x1FF
02EA MOV W2, [W0++]
instead of clearing, the repeated instruction is a copy from one register to the memory location pointed to by W0. W2 is loaded to 0x0101 because (of course) the memory in the dsPIC is word addressable so one 16bit move takes 1 cycle, 8 bit move takes 1 cycle (so better combine them) 32 bit move however takes 2 cycles.;char framebuffer[1025];
;memset(framebuffer,2,sizeof(framebuffer));
02E4 MOV #0x0202, W2
02E6 MOV #0x1000, W0
02E8 REPEAT #0x1FF
02EA MOV W2, [W0++]
02EC MOV.B W2, [W0++]
same code, with a single MOV.B added. don't have to modify W2 because with byte instructions (.B) only the lower byte of the accumulator is used
asm volatile ("MOV #_framebuffer,W0"); // clear framebuffer
asm volatile ("Repeat #511");
asm volatile ("CLR [W0++]");
asm volatile ("MOV #_imagebuffer,W0"); // clear image buffers
asm volatile ("Repeat #1023");
asm volatile ("CLR [W0++]");
/*
clrfb = 0;
while (clrfb < 512) { // clear entire frame buffer
framebuffer[clrfb] = 0; // clear framebuffer
imagebufferwide[clrfb] = 0; // clear first image
imagebufferwide[clrfb+512] = 0; // clear second image
clrfb++;
} // clrfb
*/
int foo(void) __attribute__((optimize("-O3")));
int foo(void) {
// do stuff
}
I started out that way, but the chip is full, and it will no longer compile for speed.
There’s no pin for pin replacement. It would be nice if there were a dsPic33FJ256GP802.
JPortici, Where did you get the generated assembler? I assume you put NOPs in there to help find it
if ((configbits & 0b00010000) == 0b00000000) {bit flag was clear} else {bit flag was set}
asm volatile ("Repeat #4999"); // number of repeats - 1
asm volatile ("nop"); // dead delay
It costs the same as the C call to a C delay function, to just write small delays.int i = 0;
while (i < 1024) {
imagebuffer[i] = framebuffer[i];
i++; // increment count
}
I have tried a zero overhead DOSTART loop. I think this probably works, but doesn’t like C code inside it.
It would have been to replace something like this:Code: [Select]int i = 0;
while (i < 1024) {
imagebuffer[i] = framebuffer[i];
i++; // increment count
}
asm volatile ("MOV #_framebuffer,W0");
asm volatile ("MOV #_imagebuffer,W1");
asm volatile ("REPEAT #1023");
asm volatile ("MOV [W0++],[W1++]");
int clibuf = 0; // clear the first image buffer
while (clibuf < 1024) {imagebuffer[clibuf] = 0; clibuf++;}
/*
asm volatile ("MOV #_imagebuffer,W0");
asm volatile ("Repeat #511");
asm volatile ("CLR [W0++]");
*/
It compiles, and saves a couple of words, but doesn’t work however.
The dsPic doesn’t reset, but since this is all copying image data, I just see nothing on the display.
This is a simpler example that should work, but doesn’t work to replace the C code above it.
push w1
... your code here
pop w1
I’d like to do more, such as xor a value from one buffer with a literal, and copy the result to the other,
but it’s hard to get adventurous when the simple stuff can break it.
mov.b #literal,w2
repeat #2047
xor.b w2,[w0++],[w1++]
mov #literal,w2
repeat #1023
xor w2,[w0++],[w1++]
// copy the selected image buffer to the frame buffer
// imageselect can be zero, or offset for image b 1024.
void copyimgtoframebuf(int imageselect) {
int i = 0;
while (i < 1024) {
framebuffer[i] = imagebuffer[i+imageselect];
i++;
} // i
}
…
// copy the selected image buffer to the frame buffer
void copyimgtoframebuf() {
asm volatile ("MOV #_framebuffer,W1"); //
asm volatile ("MOV #_imagebuffer,W0"); //
asm volatile ("BTSC _imageselect,#10"); //
asm volatile ("MOV #_imagebuffer+1024,W0"); //
asm volatile ("REPEAT #511"); //
asm volatile ("MOV [W0++],[W1++]"); //
}
Everything I tried that didn’t work this morning, is now working, in fact everything I’ve tried is now successful.
If any of those small routines did not work in a given location, they do if I replace W0,W1 with W1,W2. So I guess C was still doing something with W0.
mov _imageselect,w2
add w0,w2,w0
void invertframe() {
asm volatile ("MOV #_framebuffer,W1");
asm volatile ("MOV #_imagebuffer,W0");
asm volatile ("MOV.B #255,W2");
asm volatile ("REPEAT #1023");
asm volatile ("XOR.B W2,[w0++],[w1++]");
}
That sort of thing has never broken yet. This function can be called from inside a C loop as well.void invertframe() {
asm volatile ("MOV #_framebuffer,W1");
asm volatile ("MOV #_imagebuffer,W0");
asm volatile ("MOV #0xFFFF,W2");
asm volatile ("REPEAT #511");
asm volatile ("XOR W2,[W0++],[W1++]");
}