Re: Creating a microcontroller startup file

2015-04-10 Thread Jens Bauer via Digitalmars-d-learn

On Wednesday, 8 April 2015 at 23:18:41 UTC, Mike wrote:
You may also wnat to compile with -nodefaultlibs -nostdlib 
-nostartfiles.  That removes the cruntime and libgcc.


I forgot about those. Yes, when excluded those and added a 
/DISCARD/ for the exidx and armexidx, I finally got rid of the 
huge overhead.

Thank you so much!

I guess that the CTFE optimizes any function calls if they reside 
in the startup.d file, because if I keep it in the startup.d, 
then the size stays small, but as soon as I move a called 
function out from the startup.d into its own file, then the 
overhead shows up.


-But it's no longer a problem. ;)


Re: Creating a microcontroller startup file

2015-04-10 Thread Jens Bauer via Digitalmars-d-learn

On Thursday, 9 April 2015 at 10:47:42 UTC, Artur Skawina wrote:

On Tuesday, 7 April 2015 at 20:33:26 UTC, Jens Bauer wrote:


-It would be neat, if @attribute(weak) and 
@attribute(alias,function) could be combined into one, but 
I haven't found a way to do that


http://forum.dlang.org/post/mailman.2672.1403379235.2907.digitalmar...@puremagic.com


Thank you, Artur.

This is what I did (it's very close to the above; just slightly 
modified):


enum weak = gcc.attribute.attribute(weak);
alias Tuple(A...) = A;
alias rst = Tuple!(weak, gcc.attribute.attribute(alias, 
defaultResetHandler));
alias exc = Tuple!(weak, gcc.attribute.attribute(alias, 
defaultExceptionHandler));


So now the code is much easier to read ...

@rst extern(C) void Reset_Handler();
@exc extern(C) void NMI_Handler();
@exc extern(C) void HardFault_Handler();
...
...
@exc extern(C) void LTDC_ER_IRQHandler();
@exc extern(C) void DMA2D_IRQHandler();



Re: Creating a microcontroller startup file

2015-04-10 Thread Jens Bauer via Digitalmars-d-learn

On Friday, 10 April 2015 at 00:05:29 UTC, Mike wrote:

On Wednesday, 8 April 2015 at 15:25:20 UTC, Jens Bauer wrote:

Question number 2: Is it possible to change the VectorFunc 
to be a real function pointer, rather than a void* ?


Can you successfully cast(ISR)_stack ?


I don't know if that's a constraint of the language or a 
limitation of the current CTFE implementation, but either way, 
I never really liked it.
I don't really like typecasting myself, but I know a function 
pointer and a stack pointer are both pointers, thus they're the 
same size.


I know the C folks do this stuff all the time, but I think it's 
kinda janky.


True, but I need to write my files flexible, so that the majority 
of people will be able to use it out-of-the-box. I have to keep 
in mind that there are people who will make a part of their code 
in C during the transition phase, and I have to keep in mind that 
those who wrote the library in C, probably won't provide a 
complete library in D within the first week. ;)


I agree with you on the 'minimal' style. I too hate all the junk 
that's added. 'printf' has always been prohibited in my 
microcontroller code - I don't have a file system on my 
microcontroller; no screen, no keyboard and no harddisk, thus I 
don't want anything that has any connection to printf or a file 
system. ;)


Basically my startup.d will be very similar to the startup.s you 
already know (I translated my startup.s into a startup.c a long 
time ago - because I didn't want one for each type of assembler).



I know of two potential alternatives:
1)  Do it in the linker script (my current method):


Two things makes me little fond of this solution:
1: The LONG type. If it had been PTR or UINT32, then it 
would be more attractive, but I do not expect those types exist.
2: I like people to be able to define the stack location inside 
the sources if they want to.
That means: Typically the linker script will provide it, but some 
people need to move the stack, and I don't want them to need to 
change the linker script (if at all possible).



2) Use a union (See pp. 10 here:

This solution is probably more appealing to me.
I'll need to make some more tests.

My initial attempt was to create a function, which did the type 
conversion via a CTFE function, buuut it didn't like that the 
symbol was undefined and not a constant, so I'll have to make a 
few more attempts.


Thank you again for your valuable help. I hope that my fiddling 
will bring you something useful too. ;)


Re: Creating a microcontroller startup file

2015-04-09 Thread Artur Skawina via Digitalmars-d-learn
On 04/08/15 18:10, Jens Bauer via Digitalmars-d-learn wrote:
 On Wednesday, 8 April 2015 at 11:17:12 UTC, Mike wrote:
 On Tuesday, 7 April 2015 at 20:33:26 UTC, Jens Bauer wrote:

 enum weak = gcc.attribute.attribute(weak);
 enum isrDefault = gcc.attribute.attribute(alias, defaultHandler);

 extern @weak @isrDefault void NMI_Handler();
 extern @weak @isrDefault void HardFault_Handler();
 
 This is indeed helpful. I've now reduced each of the approximately 100 lines 
 declaring exception vectors to something like these:
 
 @weak @ar void Reset_Handler();
 @weak @ae void NMI_Handler();
 
 -It would be neat, if @attribute(weak) and @attribute(alias,function) 
 could be combined into one, but I haven't found a way to do that 

http://forum.dlang.org/post/mailman.2672.1403379235.2907.digitalmar...@puremagic.com

artur


Re: Creating a microcontroller startup file

2015-04-08 Thread Mike via Digitalmars-d-learn

On Tuesday, 7 April 2015 at 20:33:26 UTC, Jens Bauer wrote:



Question number 2: Is it possible to change the VectorFunc to 
be a real function pointer, rather than a void* ?




I did something along these lines (modified to match your 
example) and it worked fine for me:


alias VectorFunc = void function();

@attribute(weak) @attribute(alias, defaultHandler)
extern void Reset_Handler();

@attribute(weak) @attribute(alias, defaultHandler)
extern void NMI_Handler()

@attribute(weak) @attribute(alias, defaultHandler)
extern void HardFault_Handler();

@attribute(section,.isr_vector.ro)
immutable ISR[3] g_pfnVectors =
[
  Reset_Handler
, NMI_Handler
, HardFault_Handler
];

I did this before weak, alias, and section attributes were 
added, however.  To see my original code, look at the slide in 
the presentation here: https://youtu.be/o5m0m_ZG9e8?t=2332.  My 
original code had everything decorated with extern(C) as well so 
I could refer to the symbol directly in my linker scripts.  That 
may not be needed for you, so I left it out.


Question number 3: How can I call an external function and keep 
the binary file size down ?


Are you compiling with -ffunction-sections -fdata-sections and 
linking with --gc-sections? You may need to in order to get rid 
of some things.


What do you using for your D runtime?  Perhaps some code in your 
runtime is implicitly linking to some code you're not directly 
calling.


I also add the following to my linker scripts to get rid of stuff 
I don't find necessary:


/DISCARD/ :
{
   *(.ARM.extab*)
   *(.ARM.exidx*)
}

/DISCARD/ :
{
   *(.ARM.attributes*)
   *(.comment)
}

You can see the latest incarnation of my linker script here: 
https://github.com/JinShil/stm32f42_discovery_demo/blob/master/linker/linker.ld



Question number 4: How can I reduce the function declaration of 
the Reset_Handler and NMI_Handler shown above ?


Try something along these lines.

enum weak = gcc.attribute.attribute(weak);
enum isrDefault = gcc.attribute.attribute(alias, 
defaultHandler);


extern @weak @isrDefault void NMI_Handler();
extern @weak @isrDefault void HardFault_Handler();

I use this idiom briefly in my code here: 
https://github.com/JinShil/stm32f42_discovery_demo/blob/master/source/start.d


The enum thing kinda bugs me about D, but you'll see it used 
everywhere, especially phobos.  It's called a manifest constant, 
and you can find a short blurb about it at the bottom of this 
page:  http://dlang.org/enum.html


Mike


Re: Creating a microcontroller startup file

2015-04-08 Thread Johannes Pfau via Digitalmars-d-learn
Am Tue, 07 Apr 2015 20:38:52 +
schrieb Jens Bauer doc...@who.no:

 On Tuesday, 7 April 2015 at 20:33:26 UTC, Jens Bauer wrote:
  Question number 1: How can a C subroutine be made optional, so 
  it's called only if it linked ?
 
 Question 1 might be answered by the following thread:
 http://forum.dlang.org/thread/mg1bad$30uk$1...@digitalmars.com
 -So no need to answer question 1. ;)

I actually saw these errors when I first tested your examples, but I
thought that was a mistake in the example code. I didn't even know that
extern weak symbols get default values in C ;-)


Re: Creating a microcontroller startup file

2015-04-08 Thread Jens Bauer via Digitalmars-d-learn

On Wednesday, 8 April 2015 at 08:02:35 UTC, Johannes Pfau wrote:
I actually saw these errors when I first tested your examples, 
but I thought that was a mistake in the example code. I didn't 
even know that extern weak symbols get default values in C ;-)


Don't feel bad about that. I think I found out by looking at
someone else's source-code. ;)
It's not really information that is easy to find on the net.


Re: Creating a microcontroller startup file

2015-04-08 Thread Jens Bauer via Digitalmars-d-learn
Something tells me that now is when I have to start doing some 
hard work. ;)

-Sorry, I need to split this up into short replies/questions.

On Wednesday, 8 April 2015 at 11:17:12 UTC, Mike wrote:

On Tuesday, 7 April 2015 at 20:33:26 UTC, Jens Bauer wrote:
Question number 2: Is it possible to change the VectorFunc to 
be a real function pointer, rather than a void* ?



immutable ISR[3] g_pfnVectors =
[
  cast(ISR)_stack
, Reset_Handler
, NMI_Handler
, HardFault_Handler
];


In your example, you do not have the initial stack pointer.
The above code gives me the following:
src/test.d:24:13: error: reinterpreting cast from uint* to 
void()* is not supported in CTFE

cast(ISR)_stack
 ^

-That's the only reason I needed to change it to from function() 
to void*.

Can you successfully cast(ISR)_stack ?


Re: Creating a microcontroller startup file

2015-04-08 Thread Mike via Digitalmars-d-learn

On Wednesday, 8 April 2015 at 11:17:12 UTC, Mike wrote:

On Tuesday, 7 April 2015 at 20:33:26 UTC, Jens Bauer wrote:



Question number 2: Is it possible to change the VectorFunc to 
be a real function pointer, rather than a void* ?




I did something along these lines (modified to match your 
example) and it worked fine for me:


alias VectorFunc = void function();


[...]


@attribute(section,.isr_vector.ro)
immutable ISR[3] g_pfnVectors =
[
  Reset_Handler
, NMI_Handler
, HardFault_Handler
];



Sorry, but that code should be:

@attribute(section,.isr_vector.ro)
immutable VectorFunc[3] g_pfnVectors =
[
  Reset_Handler
, NMI_Handler
, HardFault_Handler
];




Re: Creating a microcontroller startup file

2015-04-08 Thread Jens Bauer via Digitalmars-d-learn

On Wednesday, 8 April 2015 at 11:17:12 UTC, Mike wrote:
I did something along these lines (modified to match your 
example) and it worked fine for me:


alias VectorFunc = void function();

@attribute(weak) @attribute(alias, defaultHandler)
extern void Reset_Handler();


Strange; I can't get it to build without extern(C).
Also, if I remove extern(C) from for instance HardFault_Handler, 
then a HardFault_Handler written in C is not found by the linker.


Re: Creating a microcontroller startup file

2015-04-08 Thread Jens Bauer via Digitalmars-d-learn

On Wednesday, 8 April 2015 at 11:17:12 UTC, Mike wrote:

On Tuesday, 7 April 2015 at 20:33:26 UTC, Jens Bauer wrote:

Question number 3: How can I call an external function and 
keep the binary file size down ?


Are you compiling with -ffunction-sections -fdata-sections and 
linking with --gc-sections? You may need to in order to get rid 
of some things.


I had -fdata-sections for the compiler and --gc-sections for the 
linker, but I was missing -ffunction-sections. Thank you for 
letting me know about this.

Unfortunately, it did not reduce the size of the output file.


What do you using for your D runtime?


minlibd by Timo Sintonen.


 Perhaps some code in your runtime is implicitly linking
to some code you're not directly calling.


Maybe that's what's causing it, but I find it strange that 
calling an empty function outside the source file will cause that 
huge difference.

-But of course, there's a logic explanation somewhere. ;)

Note: I can rename the 'main()' function to 
'My1Own2Weird3Function4Name567()' and the same thing happens, so 
it's not because main() is special.


I also add the following to my linker scripts to get rid of 
stuff I don't find necessary:

[snip]


It might be caused by the linker script; I'll try and see if I 
can modify it to get rid of those things.


You can see the latest incarnation of my linker script here: 
https://github.com/JinShil/stm32f42_discovery_demo/blob/master/linker/linker.ld


Mine is quite huge, so I'll try out yours as a starting point. ;)


Re: Creating a microcontroller startup file

2015-04-08 Thread Jens Bauer via Digitalmars-d-learn

On Wednesday, 8 April 2015 at 11:17:12 UTC, Mike wrote:

On Tuesday, 7 April 2015 at 20:33:26 UTC, Jens Bauer wrote:

enum weak = gcc.attribute.attribute(weak);
enum isrDefault = gcc.attribute.attribute(alias, 
defaultHandler);


extern @weak @isrDefault void NMI_Handler();
extern @weak @isrDefault void HardFault_Handler();


This is indeed helpful. I've now reduced each of the 
approximately 100 lines declaring exception vectors to something 
like these:


@weak @ar void Reset_Handler();
@weak @ae void NMI_Handler();

-It would be neat, if @attribute(weak) and 
@attribute(alias,function) could be combined into one, but I 
haven't found a way to do that - I've done that in C earlier, 
though:
void __attribute__((weak, alias(defaultExceptionHandler))) 
NMI_Handler(void);


I use this idiom briefly in my code here: 
https://github.com/JinShil/stm32f42_discovery_demo/blob/master/source/start.d


Yes. I actually came across it and didn't notice it. But now that 
you've explained it, it absolutely makes sense. :)


-I actually added @attribute(naked) to my defaultResetHandler 
yesterday, as I wanted to get rid of the prologue; so I 
completely agree; the startup code should have this attribute.

I've now changed that to use the enum, to be more consistent. ;)


Re: Creating a microcontroller startup file

2015-04-08 Thread Jens Bauer via Digitalmars-d-learn

On Wednesday, 8 April 2015 at 15:53:37 UTC, Jens Bauer wrote:

[snip] I find it strange that calling an empty function outside
the source file will cause that huge difference.
-But of course, there's a logic explanation somewhere. ;)

It might be caused by the linker script; I'll try and see if I 
can modify it to get rid of those things.


Nope, that wasn't it. However, I found out that when I call an 
external function, some unwinding code is forced upon me; it's 
used by libgcc. I can't seem to get rid of it. I've removed the 
-lgcc from my linker flags (along with *all* other libraries, and 
it's still forced upon me.


I tried to remove as much of the druntime, as I could, but it did 
not help a tad.


Re: Creating a microcontroller startup file

2015-04-08 Thread Mike via Digitalmars-d-learn

On Wednesday, 8 April 2015 at 16:10:53 UTC, Jens Bauer wrote:

On Wednesday, 8 April 2015 at 11:17:12 UTC, Mike wrote:

On Tuesday, 7 April 2015 at 20:33:26 UTC, Jens Bauer wrote:




-I actually added @attribute(naked) to my defaultResetHandler 
yesterday, as I wanted to get rid of the prologue; so I 
completely agree; the startup code should have this attribute.

I've now changed that to use the enum, to be more consistent. ;)


I actually added that out of necessity, not optimization.  Id I 
use the STM32, and reset the MCU, the CCRAM is disabled by 
default.  Since my stack is in CCRAM, I need to first enable it 
before any functions can be called.


Mike


Re: Creating a microcontroller startup file

2015-04-08 Thread Jens Bauer via Digitalmars-d-learn

On Wednesday, 8 April 2015 at 23:23:53 UTC, Mike wrote:
I actually added that out of necessity, not optimization.  Id I 
use the STM32, and reset the MCU, the CCRAM is disabled by 
default.  Since my stack is in CCRAM, I need to first enable it 
before any functions can be called.


According to ST-Microelectronics, CCMRAM is enabled by default 
(by hardware).


I am using CCMRAM without enabling it, so it must be correct what 
their User's Manual states.


Re: Creating a microcontroller startup file

2015-04-08 Thread Mike via Digitalmars-d-learn

On Wednesday, 8 April 2015 at 15:44:00 UTC, Jens Bauer wrote:

On Wednesday, 8 April 2015 at 11:17:12 UTC, Mike wrote:
I did something along these lines (modified to match your 
example) and it worked fine for me:


alias VectorFunc = void function();

@attribute(weak) @attribute(alias, defaultHandler)
extern void Reset_Handler();


Strange; I can't get it to build without extern(C).
Also, if I remove extern(C) from for instance 
HardFault_Handler, then a HardFault_Handler written in C is not 
found by the linker.


If HardFault_Handler is written in C then you will definitely 
need to decorate with extern(C).


If your handlers are written in D, and neither the implementation 
nor the declaration are decorated with extern(C) then it should 
work.


Mike


Re: Creating a microcontroller startup file

2015-04-08 Thread Jens Bauer via Digitalmars-d-learn

On Wednesday, 8 April 2015 at 23:28:45 UTC, Mike wrote:

If I use the STM32 system bootloader, and reset the MCU,
the CCRAM is disabled by default.


I see. That is absolutely incorrect behaviour of the bootloader.
A bootloader should only change the things that are absolutely 
necessary to change.


I'll have a look at the other details in your replies tomorrow, 
as I'm getting very sleepy; so writing code is not a good idea in 
my present state. ;)


Re: Creating a microcontroller startup file

2015-04-08 Thread Mike via Digitalmars-d-learn

On Wednesday, 8 April 2015 at 17:45:01 UTC, Jens Bauer wrote:

On Wednesday, 8 April 2015 at 15:53:37 UTC, Jens Bauer wrote:

[snip] I find it strange that calling an empty function outside
the source file will cause that huge difference.
-But of course, there's a logic explanation somewhere. ;)

It might be caused by the linker script; I'll try and see if I 
can modify it to get rid of those things.


Nope, that wasn't it. However, I found out that when I call an 
external function, some unwinding code is forced upon me; it's 
used by libgcc. I can't seem to get rid of it. I've removed the 
-lgcc from my linker flags (along with *all* other libraries, 
and it's still forced upon me.


I tried to remove as much of the druntime, as I could, but it 
did not help a tad.


I can think of two places in the runtime where extra code can be 
added to your binary: runtime initialization and thread-local 
storage.  There may be others depending on what features are 
implemented in the runtime.


You can find the runtime initialization code for GDC's runtime 
here:  
https://github.com/D-Programming-GDC/GDC/blob/master/libphobos/libdruntime/rt/dmain2.d#L152


That eventually will call some things that malloc, and more. That 
all happens before you get to main.  Are you compiling with 
-fno-emit-moduleinfo?  That may help reduce some of that runtime 
initialization.


As I recall, thread-local storage also employs malloc as memory 
is needed for each thread-local variable when a new thread is 
created.  If your project is single-threaded, it still works the 
same way when the initial thread is created.  If you have any 
thread-local state try removing them or changing them to 
__gshared, and see if that helps.


My runtime is quite minimal, which has both benefits and 
consequences.  You can find it here: 
https://github.com/JinShil/stm32f42_discovery_demo/tree/master/source/runtime


This will give you a C-like programming experience.  You can use 
classes, but won't be able to allocate them on the GC heap.  
Instead, you can employ some of the patterns here:  
http://wiki.dlang.org/Memory_Management


You may also wnat to compile with -nodefaultlibs -nostdlib 
-nostartfiles.  That removes the cruntime and libgcc.  But if you 
do that, you may have to compensate by adding additional startup 
code In D.  You can see how I've done that here:  
https://github.com/JinShil/stm32f42_discovery_demo/blob/master/source/start.d#L102


As I understand it, minlibd is a more full-featured runtime, and 
that too has its benefits and consequences.


Mike


Re: Creating a microcontroller startup file

2015-04-08 Thread Mike via Digitalmars-d-learn

On Thursday, 9 April 2015 at 00:37:32 UTC, Jens Bauer wrote:

On Wednesday, 8 April 2015 at 23:23:53 UTC, Mike wrote:
I actually added that out of necessity, not optimization.  Id 
I use the STM32, and reset the MCU, the CCRAM is disabled by 
default.  Since my stack is in CCRAM, I need to first enable 
it before any functions can be called.


According to ST-Microelectronics, CCMRAM is enabled by default 
(by hardware).


I am using CCMRAM without enabling it, so it must be correct 
what their User's Manual states.


Indeed, that's true.  This problem I'm referring to only occurs 
when when resetting from the system boot loader.  Since I want my 
stack to work under both conditions, I need to add that code.


See the discussion here for more information:
https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy.st.com%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fLeave%20DFU%20while%20boot0%20is%20high%20%28STM32F4%29FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5Bcurrentviews=1158

Mike


Re: Creating a microcontroller startup file

2015-04-08 Thread Mike via Digitalmars-d-learn

On Wednesday, 8 April 2015 at 23:23:53 UTC, Mike wrote:

On Wednesday, 8 April 2015 at 16:10:53 UTC, Jens Bauer wrote:

On Wednesday, 8 April 2015 at 11:17:12 UTC, Mike wrote:

On Tuesday, 7 April 2015 at 20:33:26 UTC, Jens Bauer wrote:




-I actually added @attribute(naked) to my 
defaultResetHandler yesterday, as I wanted to get rid of the 
prologue; so I completely agree; the startup code should have 
this attribute.
I've now changed that to use the enum, to be more consistent. 
;)


I actually added that out of necessity, not optimization.  Id I 
use the STM32, and reset the MCU, the CCRAM is disabled by 
default.  Since my stack is in CCRAM, I need to first enable it 
before any functions can be called.




Sorry, I need to be more careful when typing on a tablet.  That 
should read:


I actually added that out of necessity, not optimization.  If I 
use the STM32 system bootloader, and reset the MCU, the CCRAM is 
disabled by default.  Since my stack is in CCRAM, I need to first 
enable it before any functions can be called.


Mike



Re: Creating a microcontroller startup file

2015-04-07 Thread Jens Bauer via Digitalmars-d-learn

On Tuesday, 7 April 2015 at 20:33:26 UTC, Jens Bauer wrote:
Question number 1: How can a C subroutine be made optional, so 
it's called only if it linked ?


Question 1 might be answered by the following thread:
http://forum.dlang.org/thread/mg1bad$30uk$1...@digitalmars.com
-So no need to answer question 1. ;)


Re: Creating a microcontroller startup file

2015-04-07 Thread Rikki Cattermole via Digitalmars-d-learn

On 8/04/2015 8:38 a.m., Jens Bauer wrote:

On Tuesday, 7 April 2015 at 20:33:26 UTC, Jens Bauer wrote:

Question number 1: How can a C subroutine be made optional, so it's
called only if it linked ?


Question 1 might be answered by the following thread:
http://forum.dlang.org/thread/mg1bad$30uk$1...@digitalmars.com
-So no need to answer question 1. ;)


I was going to say wrap it into a function pointer global declaration 
and set it in a module constructor.