Jump to content

Ian Harris

EstablishedMember
  • Content Count

    87
  • Joined

  • Last visited

Everything posted by Ian Harris

  1. Hi Mike, I'm not sure what the static keyword on a function is meant to do, but for boostc, you need to put the inline function's full source in when it is defined (unfortunately). This means, generally, that you move the body from the .c to the .h and whack an "inline" at the front. It's a little messy, since you can't play with inline / non-inline functions very easily, but it works. cheers Ian.
  2. long fpu_readLong(void) { long t; t =12345; return t; } void flash() { long x; x = fpu_readLong(); lata.0 = 1; delay_ms(200); lata.0 = 0; delay_ms(200); } This works in 6.96. Try upgrading? cheers Ian.
  3. Yep, I'd vote for that too. As you switch away and switch back, you have to end up clicking into the window to get the cursor back. cheers Ian.
  4. When you add a file to a project using right-click - add, it adds the file with a relative path to the project file itself When you add a file by dragging from windows explorer, it adds the file with an absolute path The first behaviour is preferable, and presumably, quite easy to fix. cheers Ian.
  5. If you do a replace in the IDE, and you type your search string in lower case, if there are examples of that string in upper case, it will find them, but when you press <Replace> the string is not replaced. For lower case strings that it finds, it will find then. cheers Ian.
  6. David, After some searching: I'm not sure it would compile under sourceboost, and pointer arithmetic on PICs is never going to be an efficient way to do anything, and PICs don't have a general purpose set of registers per se... Still the concept is interesting. The smaller the thing you need to do multiple times, the more the "loop management" overhead costs you overall. In the draw library I'm creating for PicPack, the idea is to buffer the display before sending it out - meaning that things like clearing the display (or rather, the buffer) and the act of sending out the buffer to the device become costly. There's some sort of trade off between matching the buffer to the hardware (ie, y=0 top left or bottom left, horizontal alignment of buffer or vertical alignment) which makes the "paint" quicker and matching the buffer to how easy it is to calculate which pixel to turn on / off (which makes drawing onto the buffer quicker). I'm still exploring both. Ian.
  7. Hi Henry, My (updated) original do/while loop: - 13 instructions Your three suggestions: - 14 instructions - 11 instructions - 27 instructions Nice work! It would be interesting to see how many *executed* instructions it takes. Probably the quickest would be to unroll the loop: draw_buffer[0] = 0; draw_buffer[1] = 1; etc at the cost of 256 instructions (but at a cost of ROM). uns8 count; draw_buffer0[0] = 0; 068A 0100 MOVLB 0x00 068C 6B80 CLRF gbl_draw_buffer0, 1 for( count = 255; count; --count ) 068E 69B1 SETF main_1_count, 1 0690 label61 0690 53B1 MOVF main_1_count, F, 1 0692 E009 BZ label62 06A2 07B1 DECF main_1_count, F, 1 06A4 D7F5 BRA label61 06A6 label62 draw_buffer0[count] = 0; 0694 EE00F080 LFSR 0x00, gbl_draw_buffer0 0698 50E9 MOVF FSR0L, W 069A 51B1 MOVF main_1_count, W, 1 069C 26E9 ADDWF FSR0L, F 069E 0E00 MOVLW 0x00 06A0 6EEF MOVWF INDF0 // And my experience with SourceBoost has been that it can often optimize // a do-while loop more than a for loop. Not sure why. So use your code above // with the following mod. Note that testing for non-zero is usually faster than // testing for a specific number such as 255. count =255; 06A6 69B1 SETF main_1_count, 1 draw_buffer0[0] = 0; 06A8 6B80 CLRF gbl_draw_buffer0, 1 do { 06AA label63 draw_buffer0[count] = 0; 06AA EE00F080 LFSR 0x00, gbl_draw_buffer0 06AE 50E9 MOVF FSR0L, W 06B0 51B1 MOVF main_1_count, W, 1 06B2 26E9 ADDWF FSR0L, F 06B4 0E00 MOVLW 0x00 06B6 6EEF MOVWF INDF0 count--; 06B8 07B1 DECF main_1_count, F, 1 } while( count ); 06BA E1F7 BNZ label63 // And using a pointer is probably faster than either of the above. // My understanding is that's how most memset/memcpy algorithms work except that they // can sometimes further optimize by using larger variable sizes such as combining 4 chars // into 1 long and then writing to memory 1/4 as often. May not work on 8-bit architecture. unsigned char *p = draw_buffer0; 06BC 0E00 MOVLW HIGH(gbl_draw_buffer0+D'0') 06BE 6FB3 MOVWF main_1_p+D'1', 1 06C0 0E80 MOVLW LOW(gbl_draw_buffer0+D'0') 06C2 6FB2 MOVWF main_1_p, 1 while( p < draw_buffer0 + 256 ) 06C4 label64 06C4 0E00 MOVLW HIGH(gbl_draw_buffer0+D'0') 06C6 6FB5 MOVWF CompTempVar1071, 1 06C8 0E80 MOVLW LOW(gbl_draw_buffer0+D'0') 06CA 6FB4 MOVWF CompTempVar1070, 1 06CC 0E00 MOVLW 0x00 06CE 27B4 ADDWF CompTempVar1070, F, 1 06D0 0E01 MOVLW 0x01 06D2 23B5 ADDWFC CompTempVar1071, F, 1 06D4 51B5 MOVF CompTempVar1071, W, 1 06D6 5DB3 SUBWF main_1_p+D'1', W, 1 06D8 E102 BNZ label65 06DA 51B4 MOVF CompTempVar1070, W, 1 06DC 5DB2 SUBWF main_1_p, W, 1 06DE label65 06DE E209 BC label66 06F0 D7E9 BRA label64 06F2 label66 *p++ = 0; 06E0 51B3 MOVF main_1_p+D'1', W, 1 06E2 6EEA MOVWF FSR0H 06E4 51B2 MOVF main_1_p, W, 1 06E6 6EE9 MOVWF FSR0L 06E8 4BB2 INFSNZ main_1_p, F, 1 06EA 2BB3 INCF main_1_p+D'1', F, 1 06EC 0E00 MOVLW 0x00 06EE 6EEF MOVWF INDF0 You have an infinite loop when testing for unsigned char < 256 but the above solution is also dangerous. Just because we all see and use a lot of code that relys on numbers rolling over to 0, especially with timers etc, doesn't mean we should do it if we don't have to. It's poor coding and makes for big headaches when porting to new platforms or even re-using code on the same platform. A good example will be when SourceBoost releases the next version of the compiler that allows > 256 byte arrays for 18f devices. You will still be on the same platform and your code is now difficult to update. I haven't tested this but I think it produces the same or fewer instructions than your rollover solution above: draw_buffer0[0] = 0; for( count = 255; count; --count ) draw_buffer0[count] = 0; // And my experience with SourceBoost has been that it can often optimize // a do-while loop more than a for loop. Not sure why. So use your code above // with the following mod. Note that testing for non-zero is usually faster than // testing for a specific number such as 255. count =255; draw_buffer0[0] = 0; do { draw_buffer0[count] = 0; count--; } while( count ); // And using a pointer is probably faster than either of the above. // My understanding is that's how most memset/memcpy algorithms work except that they // can sometimes further optimize by using larger variable sizes such as combining 4 chars // into 1 long and then writing to memory 1/4 as often. May not work on 8-bit architecture. unsigned char *p = draw_buffer0; while( p < draw_buffer0 + 256 ) *p++ = 0; I'm curious what the SourceBoost optimizations are on each of the above... -Henry
  8. Thanks Reynard, yes, almost! I still think this is broken: unsigned char x,y; for (x =0; x < 256; x++) { y = x; } Resulting in: for (x =0; x < 256; x++) { 009E 6A3D CLRF main_1_x 00A0 label8 00A4 2A3D INCF main_1_x, F 00A6 D7FC BRA label8 y = x; 00A0 503D MOVF main_1_x, W 00A2 6E3E MOVWF main_1_y } <further code not compiled> And yes, it does give a warning - expression always true. But looking at the code - it's just broken, it never actually gets to the y=x bit, if that was actually your intention. The result in real life would be a warning and a random hang (interrupts aside). Looks like this code will do the trick (until sourceboost has > 256 byte arrays): void draw_clear_screen() { uns8 count; #if DRAW_TOTAL_BUFFER_SIZE < 256 count = 0; do { draw_buffer0[count] = 0; count++; } while (count < DRAW_TOTAL_BUFFER_SIZE); #else count = 0; do { draw_buffer0[count] = 0; count++; } while (count != 0); #if DRAW_TOTAL_BUFFER_SIZE < 512 do { draw_buffer1[count] = 0; count++; } while (count < DRAW_TOTAL_BUFFER_SIZE - 256); #else do { draw_buffer1[count] = 0; count++; } while (count != 0); #if DRAW_TOTAL_BUFFER_SIZE < 768 do { draw_buffer2[count] = 0; count++; } while (count < DRAW_TOTAL_BUFFER_SIZE - 512); #else do { draw_buffer2[count] = 0; count++; } while (count != 0); #if DRAW_TOTAL_BUFFER_SIZE < 1024 do { draw_buffer3[count] = 0; count++; } while (count < DRAW_TOTAL_BUFFER_SIZE - 768); #else do { draw_buffer3[count] = 0; count++; } while (count != 0); #endif #endif #endif #endif }
  9. Ahh yes. The compiler is not seeing 256 as a 16 bit number and hence isn't promoting the comparison to 16 bits. Yet I want an 8 bit variable to loop through all the values...something like this should work: count = 0; do { draw_buffer0[count] = 0; count++; } while (count != 0); (I have "All warnings" turned on and it didn't complain.) cheers Ian.
  10. David, Well done. The unsigned short works, including getting the return at the end of the subroutine - unsigned char generates crazy behaviour. I've been using unsigned char for some time, perhaps this is a fault with the new compiler. cheers Ian.
  11. Hi all, I'm having a look at the code generated by Sourceboost, and perhaps I've got confused, but this doesn't seem right. This is the routine. void draw_clear_screen() { uns8 count,count1; for(count = 0; count < sizeof(draw_buffer0); count++) { draw_buffer0[count] = 0; } #if DRAW_TOTAL_BUFFER_SIZE > 256 #warning "Got greater than 256" for(count = 0; count < sizeof(draw_buffer1); count++) { draw_buffer1[count] = 0; } #endif #if DRAW_TOTAL_BUFFER_SIZE > 512 for(count = 0; count < sizeof(draw_buffer2); count++) { draw_buffer2[count] = 0; } #endif #if DRAW_TOTAL_BUFFER_SIZE > 768 for(count = 0; count < sizeof(draw_buffer3); count++) { draw_buffer3[count] = 0; } #endif } Note the use of multiple buffers since Sourceboost doesn't handle > 256 byte arrays yet. In this case, there are two buffers, one 256 bytes, the second 248. DRAW_TOTAL_BUFFER_SIZE is defined as 504 I put the #warning in to see if the define is correct - it is, a #warning shows up during compilation. But this is what I get out the other end: void draw_clear_screen() { uns8 count,count1; for(count = 0; count < sizeof(draw_buffer0); count++) { 0326 6A44 CLRF draw_clear_0001E_1_count 0328 label31 0338 2A44 INCF draw_clear_0001E_1_count, F 033A D7F6 BRA label31 draw_buffer0[count] = 0; 0328 0101 MOVLB 0x01 032A EE01F000 LFSR 0x00, gbl_draw_buffer0 032E 50E9 MOVF FSR0L, W 0330 5044 MOVF draw_clear_0001E_1_count, W 0332 26E9 ADDWF FSR0L, F 0334 0E00 MOVLW 0x00 0336 6EEF MOVWF INDF0 } #if DRAW_TOTAL_BUFFER_SIZE > 256 #warning "Got greater than 256" for(count = 0; count < sizeof(draw_buffer1); count++) { draw_buffer1[count] = 0; } #endif #if DRAW_TOTAL_BUFFER_SIZE > 512 for(count = 0; count < sizeof(draw_buffer2); count++) { draw_buffer2[count] = 0; } #endif #if DRAW_TOTAL_BUFFER_SIZE > 768 for(count = 0; count < sizeof(draw_buffer3); count++) { draw_buffer3[count] = 0; } #endif } void draw_setup_io() { Note that the second loop has been (presumably) optimised away! Even if I remove the #if, it gives the same result. But if I do this: void draw_clear_screen() { uns8 count,count1; for(count = 0; count < sizeof(draw_buffer1); count++) { draw_buffer1[count] = 0; } for(count = 0; count < sizeof(draw_buffer0); count++) { draw_buffer0[count] = 0; } #if DRAW_TOTAL_BUFFER_SIZE > 512 for(count = 0; count < sizeof(draw_buffer2); count++) { draw_buffer2[count] = 0; } #endif #if DRAW_TOTAL_BUFFER_SIZE > 768 for(count = 0; count < sizeof(draw_buffer3); count++) { draw_buffer3[count] = 0; } #endif } void draw_clear_screen() { uns8 count,count1; for(count = 0; count < sizeof(draw_buffer1); count++) { 0326 6A44 CLRF draw_clear_0001E_1_count 0328 label31 0328 0EF8 MOVLW 0xF8 032A 6044 CPFSLT draw_clear_0001E_1_count 032C D00A BRA label32 033E 2A44 INCF draw_clear_0001E_1_count, F 0340 D7F3 BRA label31 0342 label32 draw_buffer1[count] = 0; 032E 0103 MOVLB 0x03 0330 EE03F000 LFSR 0x00, gbl_draw_buffer1 0334 50E9 MOVF FSR0L, W 0336 5044 MOVF draw_clear_0001E_1_count, W 0338 26E9 ADDWF FSR0L, F 033A 0E00 MOVLW 0x00 033C 6EEF MOVWF INDF0 } for(count = 0; count < sizeof(draw_buffer0); count++) { 0342 6A44 CLRF draw_clear_0001E_1_count 0344 label33 0354 2A44 INCF draw_clear_0001E_1_count, F 0356 D7F6 BRA label33 draw_buffer0[count] = 0; 0344 0101 MOVLB 0x01 0346 EE01F000 LFSR 0x00, gbl_draw_buffer0 034A 50E9 MOVF FSR0L, W 034C 5044 MOVF draw_clear_0001E_1_count, W 034E 26E9 ADDWF FSR0L, F 0350 0E00 MOVLW 0x00 0352 6EEF MOVWF INDF0 } #if DRAW_TOTAL_BUFFER_SIZE > 512 for(count = 0; count < sizeof(draw_buffer2); count++) { draw_buffer2[count] = 0; } #endif #if DRAW_TOTAL_BUFFER_SIZE > 768 for(count = 0; count < sizeof(draw_buffer3); count++) { draw_buffer3[count] = 0; } #endif } void draw_setup_io() { It generates the other loop. Swapping them back: void draw_clear_screen() { uns8 count,count1; for(count = 0; count < sizeof(draw_buffer0); count++) { draw_buffer0[count] = 0; } for(count = 0; count < sizeof(draw_buffer1); count++) { draw_buffer1[count] = 0; } #if DRAW_TOTAL_BUFFER_SIZE > 512 for(count = 0; count < sizeof(draw_buffer2); count++) { draw_buffer2[count] = 0; } #endif #if DRAW_TOTAL_BUFFER_SIZE > 768 for(count = 0; count < sizeof(draw_buffer3); count++) { draw_buffer3[count] = 0; } #endif } generates: void draw_clear_screen() { uns8 count,count1; for(count = 0; count < sizeof(draw_buffer0); count++) { 0326 6A44 CLRF draw_clear_0001E_1_count 0328 label31 0338 2A44 INCF draw_clear_0001E_1_count, F 033A D7F6 BRA label31 draw_buffer0[count] = 0; 0328 0101 MOVLB 0x01 032A EE01F000 LFSR 0x00, gbl_draw_buffer0 032E 50E9 MOVF FSR0L, W 0330 5044 MOVF draw_clear_0001E_1_count, W 0332 26E9 ADDWF FSR0L, F 0334 0E00 MOVLW 0x00 0336 6EEF MOVWF INDF0 } for(count = 0; count < sizeof(draw_buffer1); count++) { draw_buffer1[count] = 0; } #if DRAW_TOTAL_BUFFER_SIZE > 512 for(count = 0; count < sizeof(draw_buffer2); count++) { draw_buffer2[count] = 0; } #endif #if DRAW_TOTAL_BUFFER_SIZE > 768 for(count = 0; count < sizeof(draw_buffer3); count++) { draw_buffer3[count] = 0; } #endif } void draw_setup_io() { It vanishes again. I'm also slightly puzzled by the lack of a return at the end of the routine. Any thoughts anyone? kind regards Ian.
  12. I've been meaning to give it a try, but haven't gotten around to it yet. I've seen positive feedback from others that have used it standalone. I'll give it a shot in a few days. What settings ect need to be done in boostc to use it? BR /J├Ârgen In order to get a program bootloaded, I would expect you would compile it with -rb 2048 in the options / linker params. cheers Ian.
  13. Tim, love to have a look at the stuff you're doing as well - imharris at gmail.com Raghunathan, you should definitely be able to use it each time, every time, but you have to watch how windows magically creates and destroys com ports as you plug / unplug. If you leave the device connected (or have code to handle the com port vanishing when you unplug) then you'll be fine, otherwise, as Time suggests, there may be better way (eg, HID class allows you access to USB data back and forth using default drivers). cheers Ian.
  14. Amazing. These dudes have done the USB stack in assembler. It looks like it bounces the interrupt high/low vectors from the normal addresses into the program at the same addresses above its origin - meaning that every interrupt takes another couple of clock cycles. Aside from that side effect, it's a neat way of not having to do tricky boot vector relocations. Given that mplab compiles the program out of the box, there doesn't seem much point in porting it, esp given that its in assembler anyway. Just use it if it works for you. cheers Ian. I've been meaning to give it a try, but haven't gotten around to it yet. I've seen positive feedback from others that have used it standalone. I'll give it a shot in a few days.
  15. There is no way yet. This is on our todo list. Regards Dave I can confirm that the updated linker fixes the problem - downloaded to 18f2620 and confirmed working. I agree with Mac - a pragma for the -rb option would be much nicer than having to use the ide command line settings dialog - means the bootloader config could be automated before building. cheers Ian.
  16. Thanks Dave. Happy to test on the bootloader code if you have a build available. cheers Ian.
  17. Done. Thanks Dave. Looking forward to see what you come up with. cheers Ian.
  18. Upgraded to 6.95, -rb linker option doesn't actually locate the code at the specific location. The linker seems to think that it has (it reports less ROM space) but when you look at the code, it just plonks everything from the beginning of memory (0x0000). -rt doesn't seem to work either. Went back to 6.89, works fine (locates code at correct location). 6.92 seems to be fine too. 6.93 is broken, so presumably somewhere between 6.92 and 6.93 the linker took a hit. cheers Ian.
  19. The behaviour of sourceboost changed from putting the .obj files in the current (project) directory to putting it in the same directory as the source itself. This would be handy when you use the same compiled .obj in exactly the same way in different projects. Unfortunately, the PicPack library was happily reliant on the original behaviour - it meant that compiled files with particular compiler defined created local copies of .obj files, and several projects could use the same library files but compile them in different ways. This is even more important with compiling for 18f and 16f chips alternately, since the .obj files are incompatible. .obj files were dumped in the local project directory and may have been compiled completely differently than one in a different directory. Then the -obj parameter was added. This works - and puts the .obj file in the directory you specify (I use "-obj .\" to try and put the obj file in the current (project) directory as the original behaviour was), but then the linker can't find the .obj file, and there's no command line parameter for the linker to tell it where to find the .obj files. In fact, the ide creates the link command line without knowning that the compiler has already put the .obj files somewhere else. A switch to return to the default behaviour would be great, otherwise something that tells the linker where to find the .obj file would get things going again. Any suggestions? kind regards Ian.
  20. Hi Steven, I haven't used the hardware SPI function, but you can find software SPI libraries here: Embedded Adventures. uns8 is normally #defined as unsigned char or similar - you can find such defines in the pic_utils.h from the website - eg: #define int8 char #define uns8 unsigned char #define uns16 unsigned int #define int16 int #define uns32 unsigned long #define int32 long cheers Ian.
  21. Sweet! Great work guys. Mind if I make a post about this on the web site? cheers Ian. Reynard, Thanks for the suggestion. It helped to find the source of the problem by changing the timing a bit more and it is now working. It turns out that the problem was disabling the UART before the reset. Taking out the statements txsta = 0; rcsta = 0; from the reset sequence resolved the problem and I can upload new firmware automatically and wirelessly! Thanks, RJS
  22. Hi Techie, I'm looking at doing similar things. I've raised the request before - to be able to store "rom" subroutines, which could be used by both bootloader and by the main application. Have a look in the Enhancements forum list. This seems to me to be a very handy and not-too-hard to implement feature - it does mean storing where the "hard" subroutines store their variables to be passed in and out, and reporting any conflicts, but this could certainly be handled. I'm impressed you got your USB code done in assembly, it's hard enough getting it all working in C! Well done! You can certainly place data in specific locations of ROM by using the pragma data keywords; you would just need your own routines to read this out of a specific ROM location. You could use ROM strings, but only the linker knows where this string resides, so it's no use for sharing this data between bootloader / main application. I would be interested to hear how you get on. cheers Ian.
  23. I understand they were introduced in C99. Still, it's a nice feature, given that BoostC also supports things like templates that aren't standard it would be nice to support this as well. cheers Ian.
  24. typedef union _CTRL_TRF_SETUP { struct { uns8 _byte[8]; }; struct { uns8 bmRequestType; uns8 bRequest; uns16 wValue; uns16 wIndex; uns16 wLength; }; } CTRL_TRF_SETUP; [/code] Using 6.87, it isn't possible to compile the above code (which works fine in other compilers). You need to name each struct: typedef union _CTRL_TRF_SETUP { struct { uns8 _byte[8]; } y; struct { uns8 bmRequestType; uns8 bRequest; uns16 wValue; uns16 wIndex; uns16 wLength; } x; } CTRL_TRF_SETUP; This compiles - and you can use it with the names, but it's pretty clumsy. It would be nice just to be able to use the struct members without having to specify the struct they come from. regards Ian.
  25. Using 6.87: typedef struct _mystruct { char thing; char other_thing[2]; int bigger_thing; } mystruct; mystruct a_struct; mystruct *array_of_mystructs[1] = { &a_struct, }; BoostC says: error: incompatible types 'mystruct*' and 'unsigned char*' It seems to think everything that's an array is really a char*. So if you do this: typedef struct _mystruct { char thing; char other_thing[2]; int bigger_thing; } mystruct; mystruct a_struct; char *array_of_mystructs[1] = { (char *)&a_struct, }; ...it compiles. But is obviously not a desirable workaround, since then you need to typecast everything back to a mystruct. regards Ian.
×
×
  • Create New...