Jump to content


  • Content Count

  • Joined

  • Last visited

Community Reputation

0 Neutral

About guzewski

  • Rank
  1. We have been using Andrew Smallridge's I2C driver with great success for a long time, but now something is up and I can't explain it. Maybe someone here can. The new design is using I2C(1) as a slave and I2C(2) as a master (on a secondary I2C bus). The chip is the 18F46K22. Problem summary: Master I2C init fails with PIR3.SSP2IF == 0 and PIR3.BCL2IF == 1. Andrew's I2C init code calls 12c_stop as the last instruction. The stop function asserts SSPCON2.PEN to initiate the stop condition, and then gets stuck in an infinite loop waiting for PIR3.SSP2IF to assert. It never does, but I notice that a bus collision is detected. The only other devices on that secondary I2C bus are two MCP23017 I/O expanders. I can't see how a bus collision can be possible. As an experiment, I try initializing I2C(1) as a master and it works fine. The bus is actually not even connected to anything, and the pull-ups are off-board. The board build is very good: checked for solder bridges, cold solder joints, and any other possible shorting conditions. We are really scratching our heads over this. Any diagnostic suggestions would be very welcome. -Mark Guzewski PS: For reference purposes, here are the definitions that I'm using for Andrew's I2C code template. I have checked these a thousand times and I'm convinced it's OK. #define PORTD_ 0xf83 #define TRISD_ 0xf95 #define e_ClkBit 0 #define e_DataBit 1 #define e_SSPCON1 0xf6c #define e_SSPCON2 0xf6b #define e_SSPSTAT 0xf6d #define e_SmpBit 7 #define e_SSPADD 0xf6e #define e_SSPBUF 0xf6f #define e_SSPIF_PIR 0xfa4 #define e_BCLIF_PIR 0xfa4 #define e_SspifBit 7 #define e_BclifBit 6
  2. The following line of code used to compile fine: unsigned char *pFrame = (unsigned char *)&(txFrame.destAddrHi); I always put brackets around expressions that I'll take the address of. It's just a habit and I don't want to worry about operator precedence. After upgrading to 7.11, that line of code produces the following errors: error: failed to generate expression error: error in expression The error can be avoided by taking out one pair of brackets. I have to do this in hundreds of places :-( unsigned char *pFrame = (unsigned char *)&txFrame.destAddrHi; However, I think the original code is syntactically correct. Anyone care to comment?
  3. That makes perfect sense. The library must use the same index size as the code. I'm using SB7.03, but I do not use the IDE. Instead, I use Source Insight for editing and GNU make for building, so I have to manage my own makefiles. I'll find the large library and start using that. Thanks! -mark
  4. I'm using SB7 and I have a project that compiles and links fine. However, I need to increase an array to be larger than 256 bytes, so I thought the [b]-idx 2[/b] option would be suitable. I had to add the option to both the compiler and linker for it to work. When I do that, I suddenly get a lot of linker errors. Here is a snippet: When I remove the option, it compiles fine again. Anyone have any ideas about this? -Mark Guzewski
  5. So I went ahead and purchased an upgrade license for 7.01, after using 6.95 for a while. I'm not sure what I was expecting, but certainly not the following. I installed 7.01 in a separate directory (called SourceBoost7) as I did not want to blow away my 6.95 installation. I use gnu make and it was a pretty straightforward to point to the new install directory. For some reason the executables changed names (e.g. boostc.pic18.exe became boostc_pic18.exe). No biggie. Now when I make I get two bad things happening: (1) My little bit of inline assembler gives an error of "label not found". The assembler code is a 16-bit usec timer and looks like this: asm { tstfsz _usec goto declo goto dechi declo: nop nop decf _usec,1 bnz declo dechi: tstfsz _usec+1 goto dechi goto usecwaitdone decf _usec+1,1 goto declo usecwaitdone: } The error states that the label "dechi" is not defined. But it is and this compiles fine with 6.95. I commented out the assembler code just to move on. And then the linker complained that every library function I used was undefined. My -ld option is unchanged except for the directory where sourceboost is installed, and I'm linking in the file libc.pic18.lib just like before. So any idea what's up with this? thanks -Mark Guzewski
  6. I'm trying to define a value in my program, using the compiler command line option -d. It seems that this option does not behave like the gcc -D option, where you can supply a value with the definition (e.g. -Dfoo=bar will have the effect of #define foo bar in the source code) With the SourceBoost C compiler, anything I put after the -d option has a value of 1. I have tried stuff like -d foo=bar but foo always has a value of 1. Is there some way to make this option do what I need, or perhaps there is another way? regards, -mark guzewski
  7. You are correct - if you have a 2 Kbyte bootloader then you simply add the option -rb 0x800 to the linker command line and that offsets everything by 2 Kb. We do this all the time for our 18F4550-based products. I can't remember where we got the bootloader... it was a while ago and I just followed links from the MicroChip site. I remember I had to change how to power-up into the bootloader vs into the app. On all our boards we have a boot button that is read by the bootloader on reset. If the button is pressed it continues running the bootloader, otherwise it jumps to the code entry point 2 Kb upwards. Of course, first you have to get the bootloader into the chip, and we just use ICSP for that in the latter stages of board production. There are also PIC USB drivers out there that you will need to install on your develoment PC. Also, there are components (DLLS etc) that enable you to write Windows apps in VB, and maybe C# now, for downloading hex files to the bootloader. It's a bit of a pain to set up initially, but we have to support application upgrades in the field, and the USB bootloader is the only way to go for that. However, one issue I have is that the existing 32-bit USB drivers do not work on 64-bit OSes, but that will have to wait until I have more time for a resolution. The bootloader we found needed the HiTech compiler but we just used a 30-day eval for that and then went with Sourceboost C for our app development, largely because of cost considerations. I never tried compiling it with SourceBoost C. Keep in mind that the -rb option also offsets the reset and interrupt vectors, so that your bootloader has to take this into account. Anyway, hope this helps.
  8. The 18F4550 data sheet includes the instructions DECFSZ and DCFSNZ, however these produce an error when used within an asm block. Is there something I'm missing? -mark
  9. Pavel, I see how that could work quite well, and it is something to consider in the future. For now I'm working on porting other sub-systems and I'll revisit this later. thanks, -mark
  10. Hi Pavel, I must admit I'm a bit skeptical of the effectiveness of C++ on an architecture like the PIC. My C++ on Linux and Windows code pretty much demands STL, accesst to large 3rd party classes, and things like that, so I'm not used to worrying about memory usage etc in that domain. On a PIC, going from assembler to C is such a huge productivity gain in itself that I would need a pretty compelling reason to use C++ on that platform. I may consider it in the future. tahnks & regards, -mark
  11. Pavel, I have been considering other strategies and I think I have settled on something that involves one function per screen, which is responsible for rendering the LCD contents (from ROM storage) and handling the various key strokes in a switch statement. The only other thing that is needed is a pointer to the current menu handler function. It's pretty easy to implement. In fact it should also be reasonably maintainable (always a concern) since all the functionality for a particular screen is encapsulated in one function. My current PicBasic implementation uses a lot of function pointers, so I end up with many tiny functions pointed to by the menu structures. I was trying to do a more-or-less straight port from PicBasic but it seems that is not possible in this case. The big advantage to my current solution is that it uses very little ROM for what it accomplishes. My only concern with this new strategy outlined above is that I suspect the resulting code will be larger, since what used to be a single function pointer in a table now has to be a case in a switch statement somewhere. But how much larger remains to be determined. Thanks for your help. Unless you have any other comments or suggestions, I consider this matter closed. Regards, -mark
  12. Pavel, first of all thanks for the update. I understand what you say about function addresses not being known at compile time, and your suggestion to hard-code function addresses with the DATA pragma merits some consideration. I would probably write a tool that does the job for me, which would compile everything, extract the interesting function addresses, automatically edit the source code to replace the addresses in the DATA pragma, and then re-compile everything. At this point it sounds a bit painful but I'll try. But while I have your attention, I was wondering if you could tell me why this does not work. The label test1_00000 was determined by examining the asm file after compilation but before the asm{} section was added. I also tried to use just test1 and got the same failure. #include <system.h> char test1( void ) { return 'a'; } void main( void ) { char c = test1(); while( 1 ); } asm { data test1_00000 } My theory is that there no assembler in the tool chain, and the compiler probably outputs straight to object code. So the asm{} is actually compiled, which is why the terms test1_00000 or test1 do not resolve to anything. By the way, I always get an error when I try to put a label in the asm{} block (the error is internal error: can't add label 'myTable'): asm { myTable: data test1_00000 } Upon reflection, I think that the hard-coded function addresses in a DATA pragma that you described earlier would be too difficult to maintain, and automating it would be too much work. I'll consider using the so-called function pointers (which are really indices of all the functions pointed to) for my next run at this problem, unless you have any other suggestions. Thanks, -mark
  13. Pavel, that is the direction that I was heading. But the problem with this is that all of the tables must be in RAM and so must be initialized at system start-up. As it turns out, that requires more ROM and RAM than I'm willing to part with. Essentially, I would like the tables to simply exist and be addressable in ROM, rather than having to go through the exercise of creating them programatically in RAM. I have nearly 20 different screens, and each screen must handle between 3 and 16 buttons. The way I see it, in C, the menu structure would look something like this: struct buttonHandler { char keyCode; // The key that was pressed. void (*buttonFunc)( char keyCode ); // Function to execute when this key pressed. }; struct menu { char menuType; char *LcdLine1; char *LcdLine2; char *LcdLine3; char *LcdLine4; void (*menuEntryFunc)( char param ); void (*menuExitFunc)( char param ); struct buttonHandler[MAX_BUTTONS]; }; If I had a bunch of these in ROM, where each had an addressable label, then it's a simple matter of writing some code that would consist of a current menu pointer and some simple functions to render the LCD contents and find the appropriate function to invoke depending on the key code. In MPASM, it's pretty easy to use the "declare" directives (db, da and the like) to create as many of these stuctures as you need. Currently, in PicBasic, I can get the address of any of these structures by name, and then use the READCODE instruction to extract the data to process it any way I need. There seem to bo some limitations in SourceBoost C that prevent me from accomplishing this. I wonder if I'm making my self clear in this this approach?
  14. I'm having trouble figuring this out, and my forum searches are not turning up any solutions.The documentation doesn not provide a lot of detail here either. I often need to store function addresses in ROM. In my PicBasic application, I have some menu code that presents some information on an LCD and handles button presses depending on which screen of information is currently displayed. This code relies heavily on storing functions in ROM (e.g. menu entry function, menu exit function, button handlers, etc). Astonishingly, this was actually pretty easy to implement in PicBasic, using a bit of in-line assembler. Now I'm considering re-writing the thing is SourceBoost C and I cannot for the life of me get the following code to compile (I get the "error in built-in assembly" message). I have tried decorating the function names in the ASM section a thousand different ways, and in fact the doc says that labels must have a : after them so I tried that first. Getting this to work is a real prerequisite to using this C compiler. - Is there any way to use real MPASM in the AMS{} block? - Can I mix MPASM code with SourceBoost C in any way? - Any other keywords to search in the forums? (tried "computed goto", "jump table", and other variations) #include <system.h> // Three functions char test1( void ) { return 'a'; } char test2( void ) { return 'b'; } char test3( void ) { return 'z'; } // Addresses of the 3 functions in ROM. asm { data test1: data test2: data test3: } void main( void ) { test1(); // So linker doesn't optimise this out test2(); // So linker doesn't optimise this out test3(); // So linker doesn't optimise this out while( 1 ); }
  • Create New...