This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hello!
I have few questions regarding programming my RM46 microcontroller. This is a bit long post where I am trying to explain what I've done so far and the issues I am not certain of and I would need your help with these.
I have tried to program it without using HALCoGen and hence hit a giant wall that surpasses that of Great Wall of China (go figure, lol).
I want to point out that I do not want to use HALCoGen and I want to write everything down myself. If you are wondering why I will give you two reasons as I fear that the discussion will go 'USE THE HALCOGEN' way and I want to avoid it:
So, let's just, for example, speak about me writing my own GPIO. I downloaded the technical reference manual (approx. 2000 page long - the longest one I read so far) to get myself familiar with what I need to write in each register to get the desired result. Let's say I want to turn on the GPIO. I need to use GIOGCR0 register. It says that if I write 1 on bit0 it will enable the GPIO. But what is extremely weird is that I am not getting any error and my program compiles as long as I write GIOGCR0 in .h file (I found this being weird latter). I get the warning, though: 'THIS DECLARATION HAS NO STORAGE CLASS OR TYPE SPECIFIER'. I haven't payed much attention to it at first, since I was working with Eclipse to program Arduino long time ago, and warnings arose with every register name. The fork when I started taking the warning seriously was when I started writing the function that utilises GIODIN. I can't really write that in header file, so I jumped out to write it in .c file whilst writing the function prototype in header file. What got me astonished is that I got two major errors. First one is that Code Composer Studio does not understand the uint32_t nor uint32 type. The second issue was that GIODIN register cannot be found. This got me wondering and so I decided to do the stupidest thing I could think of >> let's remove gio.c and write to GIODIN register in .h file, and so I got even more confusing result. Compilation passed with few warnings only. That is when I realised that compiler cannot find the memory address of the register which should have resulted in error, but it didn't. Weird, no?
Then I've decided to go to Google and try to find the library with defined memory locations of each and every register. There was none since everyone uses HALCoGen... It seems I'm the only weirdo out there and that's why were here. Then I've decided to pick the lengthy technical manual once again, since I have no other option then write my own register file for the first time ever, and I have no clue how to do this, so I need your help. What I firstly found was:
Table 2-3. Module Registers / Memories Memory-Map (continued)
GIO PS[16] 0xFFF7_BC00 0xFFF7_BCFF 256B 256B Reads return zeros, writes have no effect
Let's also say that I have no clue what PS[16] should stand for or the explanation that it is memory select.
From this I realised that GIO port is addressed from 0xFFF7BC00 to 0xFFF7BCFF which is good but I can't do a lot with that information unless I know memory addresses of each register mapped in that location.
Next thing I noticed is, if I want to use GIODIR for PORTB offset 54h is given on table 25-1. of GIO Control Register. What is 'h' in this case of an offset? Does this affect anything?
What I want to know is if the address of that register is 0xFFF7_BC54 and how do I specify that it should only be up untill 0xFFF7_BC58 which is the address where GIODIN register starts? I presume using uint32, since it is the length inbetween two registers, would help with the #define statement but Code Composer Studio still has no clue what uint32 is and that is annoying for a microcontroller based IDE not to know.
So far I haven't had the need to write this down myself, so I am not sure how to do this since I am still getting errors.
Let's say that I have gio_register.h file where I will write down:
#define GIOGCR0 ((uint32_t *) 0xFFF7BC00)
#define GIOINTDET ((volatile uint32_t *) 0xFFF7BC08)
#define GIOPOL ((unti32_t *) 0xFFF7BC0C)
.
.
.
#define GIODIRB ((uint32_t *) 0xFFF7BC54)
#define GIODINB ((volatile uint32_t *) 0xFFF7BC58)
.
.
.
#define GIOPSLB ((uint32_t *) 0xFFF7BC70)
Will this work? Do I need to specify that each register is volatile? I am not exactly sure of that. It looks to me like only registers that change in time like GIODIR need that, but like GIOGCR0 do not, since they are only initialised at the start. What do you think about this? I am not a fan of turning off optimisation if it does not need to be turned off although it won't have any noticeable results in this case since TI has amazing processor. When I was introduced to 'volatile' keyword for first time I was told: 'ADD IT EVERYWHERE JUST IN CASE'... I can't settle with that statement.
Apparently, even if this would work, I am still left with a problem that Code Composer Studio has no clue what uint32 is unlike some other IDEs for microcontrollers. I understand that uint32 is a typedef but why is it not being recognised by Code Composer Studio by default? What's to be done?
Also, I have to ask something else in reference with questions so far.
What I've seen in HALCoGen generated code is: #define gioREG ((gioBASE_t *)0xFFF7BC00U)
Which is later referenced as, for example: gioREG->GCR0 = 1U;
Since GCR0 is a first member of typedef structure it reserves first 32 bits in that structure so it's address is 0xFFFF7BC00 without any doubt. But what is this U appended to address (0xfff7bc00U) and number that is assigned to the GCR0 member of gioREG (1U)? Does it have soemthing to do with that 'h' in offset (56h for example)? Does it mean UNSIGNED? Or what is it?
So, when assigning value to gioREG->GCR0 in case of HALCoGen generated code, are all four the same?
If not what could be the differences?
And can the U from address be omitted? Are these two the same?
On contrary to this solution from HALCoGen which seems elegant, I do not want to assign new volatile typedefs or even bit fields. I just want each register to be defined with its exact memory location and directly used, so this: #define GIODIN ((volatile uint32_t *) 0xSOME_ADDRESS) and then latter called like GIODIN = 0x01;
One more thing and I will conclude this, what is rather an essay. Since I know that Eclipse IDE does not support word CLASS, for example, unlike Microsoft Visual Studio for C programming, I am wondering does it support ' or _ for binary / octal / hexadecimal definitions, for example:
GIOGCR0 = 0b0000'0000'0000'0000'0000'0000'0000'0000;
or
#define REG_NAME ((uint8_t *) 0x1234_5678)
Will this pass without any error with Code Composer Studio?
Thank you in advance for reading all this and hopefully helping me with my problems!
Nemanja,
I see questions related to the controller, to HALCoGen generated code, the compiler and to general C.
I'll address the general C one:
> First one is that Code Composer Studio does not understand the uint32_t nor uint32 type.
uint32_t defined in stdint.h and
uint32 defined in HALCoGen generated HL_hal_stdtypes.h
> And can the U from address be omitted? Are these two the same?
> 0xFFF7BC00U
> 0xFFF7BC00
The U means that it is explicitly predefined as an UNSIGNED constant.
The fact if a compiler treats it as an unsigned or signed when you don't specify the U suffix is a bit complex,
Dependent on size of the variable it fits in, architecture of the device you are programming, ...
> 'THIS DECLARATION HAS NO STORAGE CLASS OR TYPE SPECIFIER'
Are you trying to use a C++ construct in a C program?
Jan Cumps said:> 'THIS DECLARATION HAS NO STORAGE CLASS OR TYPE SPECIFIER'
Are you trying to use a C++ construct in a C program?
Thank you for your answer. I understand everything you wrote.
Unfortunately, I think you misunderstood what happened with that warning. No, I am not using C++. That's why I tried explaining what I was doing, to avoid that confusion, so I'll try again in different manner.
This warning is due to this line:
GIOGCR0 = 0x01;
In other words I am assigning value of 1 to GIOGCR0 register to turn it on.
As I have noted it seems that GIOGCR0 register cannot be found. When HALCoGen generates code it generates library called reg_gio.h among others where it stores memory addresses for registers using typedef struct.
What I need to do now, not having that HALCoGen generated code is to create that location myself.
When I write (I've included stdint.h):
#define GIOGCR0 ((uint32_t *) 0xFFF7BC00
or
#define GIOGCR0 ((uint32_t *) 0xFFF7BC00U
and then later say
GIOGRC0 = 0x01;
or
GIOGCR0 = 1U;
I am getting both warning and error.
The warning stays unchanged >> 'THIS DECLARATION HAS NO STORAGE CLASS OR TYPE SPECIFIER'
The error says >> 'uint32_t HAS ALREADY BEEN DECLARED IN THE CURRENT SCOPE'
Now not only does it not understand what GIOGCR0 is, it does not interpret it as an address whatsoever.
Any thoughts on how to fix this?
I've tested this construct with another compiler (GCC).
your define "GIOGRC" is literally replaced with "((uint32_t *) 0xFFF7BC00)" in the code (edit: this happens by the pre-processor at the very start, before the compiler compiles the code)
((uint32_t *) 0xFFF7BC00 can't get an integrer assigned in C.
../main.c:106:31: error: lvalue required as left operand of assignment ((uint32_t*) 0xFFF7BC00) = 0x01;
If you create a struct that holds a unit32_t, and make your pointer point to that, you can assign a value.
in the header:
typedef volatile struct GCR0 { int GCR0; /**< 0x0000: Global Control Register */ } GCR0_t; #define GCR0REG ((GCR0_t *)0xFFF7BC00U)
In your .c file:
GCR0REG -> GCR0 = 0x01U;
Nemanja Tomovic said:Aye! Thanks for all the help! :) This works.
Also, it works if I only do this:
#define GIOGCR0 ((uint32 *) 0xFFF7BC00U)
GIOGCR0 = 0x00;
There is no problem anymore.
So, the only problem was with uint32_t... :(
Thank you so much once again! :)
My tests fail on this:
#define GIOGCR0 ((uint32 *) 0xFFF7BC00U) GIOGCR0 = 0x00;
in GCC: error: lvalue required as left operand of assignment
in TI compiler: error #138: expression must be a modifiable lvalue
That's a linker warning to point out that your linker definition file is not as expected.
a look ahead when continuing on the HALCoGen-less path:
You will find that very likely, once you are able to load your binary to the controller, your program will not really run.
The Hercules is complex, and there are a number of registers that need to be set before starting main(). (check the HL_sys_core.asm and HL_sys_startup.c file for an impression of the code that runs before main() is called).
You need to define and initialise the interrupt vector, make the parts where you load your code executable, set memory cache options, initialise PLL and clock domains, power domains, ...
A brave exercise if you can complete it and control a GIO pin.