|
|
View previous topic :: View next topic |
Author |
Message |
kda406
Joined: 17 Sep 2003 Posts: 97 Location: Atlanta, GA, USA
|
rom #org & multiple compilation unit woes |
Posted: Wed Sep 01, 2021 12:48 pm |
|
|
I am looking for advice or a trick to help #org work better with rom stored data when multiple compilation units are in play. Without assistance, CCS overlaps the ROM tables.
Today I'm working with a PIC18F67K40 and 5.104, but I have struggled with this problem with the CCS compilers for decades. My work-arounds so far have been time consuming and problematic.
The current project is only medium complexity with 40 .c files and about 55 .h files.
Tables for conversion data and strings are stored in program memory using the CCS "rom" type qualifier.
Without #org statements, the CCS compiler puts the rom data all on top of each other. It is a REAL PROBLEM! A peek at an example symbol file reveals:
Code: | User Memory space: rom
01FCE0-01FFFF c_cMenuMain
01EC74-01FFFF gczmR410ATempFromPress
01FFB0-01FFFF c_cSettingCategories |
WHOOPS! All the data tables are in the same place!
All these data are stored in libraries and are included in different projects in different combinations. I cannot just put a #org 0xXXXXX into the library as it will be the wrong place on the next project. So I use preprocessor naming for each project to name the segments. In the ProjectConfig.h: Code: | /*
___ ___ __ __ _ _ _
| _ \/ _ \| \/ | /_\ __| |__| |_ _ ___ ______ ___ ___
| / (_) | |\/| | / _ \/ _` / _` | '_/ -_|_-<_-</ -_|_-<
|_|_\\___/|_| |_| /_/ \_\__,_\__,_|_| \___/__/__/\___/__/
*/
///// Locations where we store data tables in program memory /////
#define ROM_THERMISTOR2880 0x1E62E // 1604 (0x644) byte 2880 table, 0x1E62E - 0x1EC73
#define ROM_R410APT 0x1EC74 // 5002 (0x138A) byte P-T table, 0x1EC74 - 0x1FFFF | In a typical library that uses this: Code: | #ORG ROM_R410APT
rom INT16 gczmR410ATempFromPress[] = {... |
As the projects grow the complexity increases. One issue is that you cannot create the #org statements until you know the sizes of each of the tables. You must compile to find the sizes and overlaps. Iteratively, I find the sizes of each rom section for each system, slowly untangling the overlapping rom data.
Then, the customer asks me to make one minor change to one user menu and WHOOPS, the entire table set are overlapped and messed up with no warning from the complier or linker!
I wish I had a computer to figure this out for me, but instead, I have to think for the computer.
So I've tried to simplify an example of a nightmare I face with every project. What do you do to manage your program memory stored data with CCS and MCUs, and how might I manage mine better?
Thanks,
Kyle |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9269 Location: Greensville,Ontario
|
|
Posted: Wed Sep 01, 2021 12:58 pm |
|
|
My solution (Ok, I'm a dinosaur..started with PCM 2.435 +-) is to never,ever use MCU (Multiple Compilation Units).
I've never had 40 + '#include xxx.c' files for one project(15-20 max) though I suspect the compiler would be happy to figure it all out....
Historically CCS didn't do MCU well, maybe the newer compiler will ? Others far younger than me, can answer that..... |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1941 Location: Norman, OK
|
|
Posted: Thu Sep 02, 2021 9:12 am |
|
|
Can we assume you have reported this to CCS? _________________ Google and Forum Search are some of your best tools!!!! |
|
|
kda406
Joined: 17 Sep 2003 Posts: 97 Location: Atlanta, GA, USA
|
|
Posted: Thu Sep 02, 2021 9:28 am |
|
|
dyeatman wrote: | Can we assume you have reported this to CCS? | I have not. This has been a problem for decades; surely CCS knows about it. I am seeking suggestions of how other users work around this problem.
Thanks,
Kyle |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19589
|
|
Posted: Thu Sep 02, 2021 11:46 am |
|
|
Why do you use rom?. Consts are c6rrectly handled across MCU's and
given that for strings you can use the PASS_STRINGS option to allow
pointers, it might be much easier to not use the rom declaration.
However, CCS is very clear that if you use the rom format, and MCU's
then you have to ensure these do not overlap. What about generating a
macro to handle generating the addresses. Use a couple of values for start
and size, and have it automatically increment the start by the size each time
it is called.
I have to agree with the comments about not using MCU's. Generally things
work much better without them, and the compilation speed is usually fast
enough that there is no real advantage to using them. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9269 Location: Greensville,Ontario
|
|
Posted: Thu Sep 02, 2021 1:09 pm |
|
|
re: the compilation speed is usually fast
enough that there is no real advantage to using them.
it's lightning fast compared to how we erased PICs, back in the good old days.... 15 minutes under the UV bulb.....ah, coffee break times !!!
Jay |
|
|
kda406
Joined: 17 Sep 2003 Posts: 97 Location: Atlanta, GA, USA
|
|
Posted: Thu Sep 02, 2021 1:16 pm |
|
|
Quote: | Why do you use rom? |
I use const for some things, but it is buggy on large programs. Once the compiled program exceeds 20~30KB the const arrays start having problems.
I just grabbed a small test menu as an example. Code: | #ORG 0x1D000
rom char c_cSettingCategories[4][20] = {
"Frequency [Hz]",
"Compressor [T]",
"Blower/Fan [CFM]",
"TXV [Steps]"
}; | This prints correctly when used with a printing routine that expects a rom char * argument.
Now I change it to a const: Code: | const char c_cSettingCategories[4][20] = {
"Frequency [Hz]",
"Compressor [T]",
"Blower/Fan [CFM]",
"TXV [Steps]"
}; | And change the print routine to expect a char * argument, along with the "#device PASS_STRINGS=IN_RAM" directive. Code: | Frequency [Hz]
Compressor [T]
Blower/Fan [CFM(
TXV [Steps] | Notice the incorrect character. I have put it into a loop for printing and every time it comes out with the exact same problem I show in this example. I can print it 10X and it still has a ( instead of a ] every time. Print problems is one thing, but we cannot tolerate mistakes like this in the data tables that control motors and valves(!).
I have seen this across various PIC18F families (87Kxx, 67Kxx, 46Kxx). This problem only manifests after the program gets large in size. It seems to get worse as the program gets larger.
I have never had the data get corrupted like this when I use rom instead of const. So I use rom. But that brings up the woes from the original post.
It seems there is no simple solution to the #org problem, but I appreciate everyone's input.
Thanks,
Kyle |
|
|
kda406
Joined: 17 Sep 2003 Posts: 97 Location: Atlanta, GA, USA
|
|
Posted: Thu Sep 02, 2021 1:21 pm |
|
|
temtronic wrote: | it's lightning fast compared to how we erased PICs, back in the good old days.... 15 minutes under the UV bulb.....ah, coffee break times !!!
Jay |
"Back in the day," I had two PIC16C54s and I was always erasing one while programming/testing with the other.
Code: | ; I wrote everything in assembly back then. |
|
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1358
|
|
Posted: Thu Sep 02, 2021 6:00 pm |
|
|
Have you tried declaring all of your rom variables together in a single file and using "extern" versions in your libraries? If that works it would ensure they don't overlap while allowing your library to work as long as you link in the file with the defined variables:
library.h
- Has typedef for your data structure
- has public interface to your library
library.c
- externs a known variable by name that has the type defined in library.h. I don't know if you can extern a rom variable or not or if you still need to have "rom" in the type definition or not, but something to play with
rom_defs.c
- #includes the library.h file for the typedef
- allocates a variable of that type with the same name as the extern'ed variable in library.c.
- has other rom variables declared here too, #includes appropriate .h files for them
Again, I haven't tried any of this. I avoid MCU's altogether cause the compiler doesn't have an actual linker, just a emulated linker stage and it has always caused me trouble. An actual linker would allow you to specify the memory map of your program separate from the code (which is what the rom_defs.c file is trying to emulate in my thought process).
Alternatively, if that doesn't work you could try adding a library init function that takes a "rom pointer" to your rom type for the library and assigns it to in internal global pointer and use that in your library instead of the rom variable directly. Then you again would define all of your rom variables in a single file and just call the various library init functions at the start of your program to assign them to the library |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19589
|
|
Posted: Thu Sep 02, 2021 10:13 pm |
|
|
Agree totally with Jeremiah.
Having multiple separate declarations, is asking for trouble, Single set
of declarations that all the modules then access, would seem by far
the easiest, and most likely to work. |
|
|
kda406
Joined: 17 Sep 2003 Posts: 97 Location: Atlanta, GA, USA
|
|
Posted: Fri Sep 03, 2021 7:53 am |
|
|
That's a great concept, Jeremiah. I'm going to give this a try. This is exactly the kind of suggestion I was hoping to get from this great forum.
Many thanks,
Kyle |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|