Jump to content


  • Content Count

  • Joined

  • Last visited

Community Reputation

0 Neutral

About philb

  • Rank
  1. Hello Bill, thanks for the offer of help, however I think you didn't quite get what I was trying to do - it was all about determining the address of functions and manipulating the address to make it suitable for modifying the code at runtime. * Issue 1: No, the function pointer is the correct type (i.e. pointer to function of "void foo (void)") - it's not the return value of the function I want, but the address of the function. As a "function pointer" is a pointer to a function, it should contain the address of the function being pointed to (which is fine on other architectures, but as Pavel has pointed out, won't work here...) * Issue 2: Actually no, odd as it seems you don't need the ampersand here. * Issue 3: As per Issue 1, it's not a function call, so the code is correct from a C point of view, and works fine on (say) x86, sadly it won't work on this architecture. * How to do it... well Pavel suggests fixing the address of functions using the language extensions so that I know at coding time what they are, rather than determining them at link time - of course it's very specific to PIC/BoostC, but that's not really a problem for me, so that's what I'll settle on. thanks Phil.
  2. Thanks for the clarification. OK, so it's a 'speciality' of PICs that this sort of code wont work. Perhaps you can suggest how I get the address of a function into a 16-bit variable... is it only possible using assembler? btw: I need the address of a function as my application performs self-modification to switch between sets of interrupt handlers (i.e. it reads/modifies/writes the first 64-bytes to change the jump addresses for the high/low priority interrupt handlers) - this allows each (separate) mode of operation to have optimal interrupt performance. To do this I need to know the address of the functions to switch to (the addresses of the ones I'm switching from can be deduced from reading the flash) regards Phil.
  3. Sorry I disagree - this form of code is fine on various platforms using various compilers (e.g. GCC on x86) - how else would you generate function pointer based callback jump tables in code such as DLLs/shared objects? A function pointer is a variable of a standard type - it must have a size and location, and in essence is the same as any other pointer. If you initialise a function pointer variable to the address of a function, then the storage associated with the function pointer should be initialised to the address of the function. What you later choose to do with the contents of that location via casting is somewhat irrelevant. Of course if you call the function via the function pointer it should then generate an indirect function call using the contents of the location assigned to the function pointer - but fundamentally the location associated with the function pointer should be initialised. For example, on x86 using GCC: typedef void (*fp) (void); void testfp (void) { fp high = test1; //some function fp low = test2; //some other function printf("\nValue of test1: 0x%X, value of test2: 0x%X",(unsigned long)test1,(unsigned long)test2); printf("\nValue of high: 0x%X, value of low: 0x%X",(unsigned long)high,(unsigned long)low); printf("\nSize of fp: %d\n",sizeof(fp)); } will result in: Value of test1: 0x8048344, value of test2: 0x80448358 Value of high: 0x8048344, value of low: 0x80448358 Size of fp: 4 And objdump confirms that the address of the functions is indeed as printed. Why do you think that the example code I provided is invalid? regards Phil
  4. Hello. v6.95 on WinXP, compiling for 18F24k20. When I try to use function pointers I get weird results, for example: typedef void (*fp) (void); void TestFP (void) { //determine the values to input fp low = InitCapture; //any global function with the write signature fp high = ClearRDSState; //ditto unsigned short adrs = (unsigned short)high >> 1; puts("\nhigh value is: "); puthex(adrs>>8); puthex(adrs); adrs = (unsigned short)low >> 1; puts("\nlow value is: "); puthex(adrs>>8); puthex(adrs); } the output shows values of 0 or 1 being output for the function addresses - looking at part of the assembler from the casm file: fp low = InitCapture; 1944 0E01 MOVLW 0x01 1946 0100 MOVLB 0x00 1948 6FF3 MOVWF TestFP_00000_1_low, 1 fp high = ClearRDSState; 194A 0E02 MOVLW 0x02 194C 6FF4 MOVWF TestFP_00000_1_high, 1 unsigned short adrs = (unsigned short)high >> 1; 194E 6FF5 MOVWF TestFP_00000_1_adrs, 1 1950 6BF6 CLRF TestFP_00000_1_adrs+D'1', 1 1952 90D8 BCF STATUS,C 1954 33F6 RRCF TestFP_00000_1_adrs+D'1', F, 1 1956 33F5 RRCF TestFP_00000_1_adrs, F, 1 Which seems to think that the function pointer has a size of 1 byte only, and that value is a constant of 1 or 2 (InitCapture & ClearRDSState respectively). Surely the size of a function pointer must be 2 bytes to accommodate the address range? fwiw looking at the map file, the functions are actually at addresses 0x370 and 0x350 respectively. The manual says that function pointers are supported, but perhaps in a very constrained way? The only restriction I saw was not supporting arrays of function pointers...
  5. Yep, as I realised. Of course it was my mistake to assume that it did, I'm still slightly confused by the failure mechanism, but will double check the PIC manuals (for my own understanding). On searching the Boost C manual, I couldn't find any mention of the extended instruction set (+ve or -ve) - so it doesn't explicitly state that it does support it, but then again it doesn't explicitly state that it doesn't. Can I request that you update the docs to make it clear (just to stop others falling into the same trap as I did). Also, any plans to support it (allegedly it can give better code for array/structure operations)? Thanks.
  6. Finally. So with my suspicions raised regarding why it suddenly fails when changing to the 18F24K20, it turns out that I had (stupidly?) assumed that the extended instruction set would be supported/targetted by the compiler - as soon as I disabled the configuration for xinst, everything burst into life. However from reading the manual only the usage of FSR2 gets affected by enabling xinst, so as the code I was looking at used FSR0, I'm not sure what was going on... any ideas/comments? btw: some failing simple test code seemed fine on the simulator, but failed on real hardware. So the obvious questions are: 1) Does the toolchain support the xinst configuration? 2) If so is there a switch? 3) Any ideas why code built with it enabled would fail (specificallyin using the FSR0 registers)? thanks
  7. Well, I've spent quite a lot of time (on and off) with this, as the problem came and went with different builds. Having checked the hardware, tried 2 different boards etc... and given that for a given build the errors I got were consistent for each run, I did some more investigation... There is a circular buffer of 16 shorts which is used to store capture values - values get added within the interrupt handler, and get popped off in the handler loop... it turns out that instead of the values being stored in elements 0-15 of the array, they actually are being stored in elements -4 to 11! That means that whatever happens to be mapped before the array in memory, gets corrupted - hence the bizarre errors I saw. Now the problem is why is the array 'offset' in memory by -4 (8 bytes)? I can make the app run by forcing the location of the array, and allocating an unused buffer in the 8 bytes preceding it. Honestly at this point I have no idea! The C code was used previously on other chips without a problem. I've looked through the asm code, and it all makes sense, I can't see anything obvious - I'm in the process of trying to construct a simple example for the problem both in order to find out what it is, and if it turns out to be a compiler error, then to provide it to you (the current code is analysis a number of digital signals and decoding them so I can't just send it to you). In general, it seems to be a problem with arrays/pointers and indirection on this particular combination of chip/compiler (18f24k20/6.95) - but exactly what is eluding me. I'll keep you posted when I have more.
  8. Oops, sorry about that - I was using the old one. Yep, it's clear in the current manual, my mistake. regards Phil.
  9. Hmm, most odd that it works for you on v6.95 - as I said, it was always OK until I upgraded - but there is of course a possibility that there is an error elsewhere in my code that the upgrade has exposed - I'll double check (that may take a little time). Certainly the generated code looks OK to me... regards Phil.
  10. No problem. However the compiler error message is somewhat cryptic. May I suggest you update the user doc's to make it clear that the only valid syntax is the multi-line one. thanks. Phil.
  11. Hello, thanks for the reply, but surely using p (which could have any value from 0 to 255) as the array index is bound to fail? The idea is to limit the array index to a value between 0 and 15 based on the upper, and then lower nibbles of the input character. Otherwise you'll index past the end of the array and end up with garbage output. I've been using this 'coding trick' to convert from binary to ascii for many years on many platforms ranging from workstations down to PICs, usually it generates compact and fast code. It's only after upgrading (both to v6.95 and to 18f24k20 from v6.91 on 18f2431) that this stopped working. regards Phil.
  12. v6.95, win XP, 18f24k20 Now I know this is a bit odd, but... I'm toying with dynamically switching the interrupt handlers, by reflashing the first 32 bytes so that the GOTO's point to different handlers. So I need to have multiple instances of high and low priority interrupts. Part of the experiments in this area have been to create the correct prolog/epilog code in the new handlers... which mimics the code in the default handlers. The below code compiles and links.... extern unsigned char Int1Context[4]; void my_interrupt_high (void) { asm { MOVFF _fsr0h,_Int1Context MOVFF _fsr0l,_Int1Context+1 MOVFF _prodh,_Int1Context+2 MOVFF _prodl,_Int1Context+3 } //stuff goes here asm { MOVFF _Int1Context+3,_prodl MOVFF _Int1Context+2,_prodh MOVFF _Int1Context+1,_fsr0l MOVFF _Int1Context,_fsr0h RETFIE 1 } } But looking at the assembler output, the epilog MOVFF instructions are correctly using the '_Int1Context' symbol, while the prolog MOVFF instructions are all using some 'gbl_Int1Context' symbol, which of course is wrong. Disassembling the hex shows that the epilog is indeed correct, and the prolog code resolves the base address of 'gbl_Int1Context' to 0xFFF which is wrong. I think there are 2 errors here: 1) The inline assembler is inconsistent between the prolog and epilog usage of the same symbol 2) The linker doesn't complain that the 'gbl_Int1Context' doesn't actually have any storage allocated, and puts its start address to -1 (note that the extern in the code example is required to make it compile, but doesn't actually declare any storage) Of course there may be a better way to achieve what I want (e.g. using the command line to have no automatic context save/restore code in the standard handlers, and then doing it all manually myself in all handlers), but that doesn't excuse the errors I'm seeing :-) regards Phil.
  13. v6.95, on WinXP, compiling for 18f24k20 After a bit of chasing around it seems that the compiler is very picky on the placement of the curly braces when using inline asm - i.e. the curly braces must be on separate lines... code of the form void foo (void) { //some C code asm { tblrd*+ } //some more C code } will cause the compiler to throw a 'missing paren' error on the following function. whereas: void foo (void) { //some C code asm { tblrd*+ } //some more C code } is fine. From memory I think that even void foo (void) { //some C code asm { tblrd*+ } //some more C code } causes problems (but not 100% sure on that) regards Phil.
  14. Hello. V6.95, compiling for 18F24k20 on Win XP. The below code has been used on various PICs (18f2431,16f690,16f886,16f688) using previous versions of SourceBoost C, and has until now always been fine - last known working version was 6.91. Now the output is garbage, most notably, it's not just that the output is wrong (i.e. wrong hex value displayed, but non-printable ASCII is output, which should never happen). static const char conv[] = "0123456789ABCDEF"; inline void putc(unsigned char byte) { /* output one byte */ while((pir1 & TX_TXIF) == 0); txreg = byte; } void puthex (unsigned char p) { putc(conv[((p>>4) & 0x0F)]); putc(conv[(p & 0x0F)]); } I took a look at the generated asm, and it seems to make sense, but simply doesn't work... (PS: other character/string functions still work fine, so it's not the UART setup, and if I modify the function not to use the string array, it works) regards Phil.
  • Create New...