digitalmars.D.learn - Creating a microcontroller startup file
- Jens Bauer (84/84) Apr 07 2015 I'm currently working on a startup file for Cortex-M.
- Jens Bauer (4/6) Apr 07 2015 Question 1 might be answered by the following thread:
- Rikki Cattermole (3/9) Apr 07 2015 I was going to say wrap it into a function pointer global declaration
- Johannes Pfau (5/12) Apr 08 2015 I actually saw these errors when I first tested your examples, but I
- Jens Bauer (4/7) Apr 08 2015 Don't feel bad about that. I think I found out by looking at
- Mike (56/62) Apr 08 2015 I did something along these lines (modified to match your
- Mike (10/25) Apr 08 2015 Sorry, but that code should be:
- Jens Bauer (13/23) Apr 08 2015 Something tells me that now is when I have to start doing some
- Mike (37/55) Apr 09 2015 I don't know if that's a constraint of the language or a
- Jens Bauer (35/48) Apr 10 2015 I don't really like typecasting myself, but I know a function
- Jens Bauer (4/9) Apr 08 2015 Strange; I can't get it to build without extern(C).
- Mike (7/19) Apr 08 2015 If HardFault_Handler is written in C then you will definitely
- Jens Bauer (16/30) Apr 08 2015 I had -fdata-sections for the compiler and --gc-sections for the
- Jens Bauer (8/13) Apr 08 2015 Nope, that wasn't it. However, I found out that when I call an
- Mike (33/47) Apr 08 2015 I can think of two places in the runtime where extra code can be
- Jens Bauer (11/13) Apr 10 2015 I forgot about those. Yes, when excluded those and added a
- Jens Bauer (18/26) Apr 08 2015 This is indeed helpful. I've now reduced each of the
- Mike (6/12) Apr 08 2015 I actually added that out of necessity, not optimization. Id I
- Mike (8/22) Apr 08 2015 Sorry, I need to be more careful when typing on a tablet. That
- Jens Bauer (7/9) Apr 08 2015 I see. That is absolutely incorrect behaviour of the bootloader.
- Jens Bauer (5/9) Apr 08 2015 According to ST-Microelectronics, CCMRAM is enabled by default
- Mike (7/16) Apr 08 2015 Indeed, that's true. This problem I'm referring to only occurs
- Artur Skawina via Digitalmars-d-learn (3/18) Apr 09 2015 http://forum.dlang.org/post/mailman.2672.1403379235.2907.digitalmars-d@p...
- Jens Bauer (18/24) Apr 10 2015 Thank you, Artur.
I'm currently working on a startup file for Cortex-M. Thanks to Johannes, I'm now able to implement almost everything I need. While the most important part of the code code works, there are still a few things, that I would like added/changed. Here's a cut-down version of a start.d: ---8<-----8<-----8<----- /* file: startup.d */ import gcc.attribute; import core.stdc.config; //alias extern(C) const void function() VectorFunc; // currently, this won't work for me alias extern(C) const void *VectorFunc; // so I'm using a void* instead. extern(C) extern __gshared c_ulong[0] _stack; const SIGNATURE_VALUE = 0x5a5a5a5a; attribute("weak") attribute("alias", "defaultResetHandler") extern(C) void Reset_Handler(); attribute("weak") attribute("alias", "defaultExceptionHandler") extern(C) void NMI_Handler(); attribute("section",".isr_vector.ro") VectorFunc[] g_pfnVectors = [ cast(VectorFunc)_stack, // Initial Stack Pointer &Reset_Handler, // Reset Vector &NMI_Handler, // Non Maskable Interrupt Vector cast(VectorFunc)SIGNATURE_VALUE, ]; extern(C) void main(); attribute("weak") extern(C) void LowLevelInit(); attribute("weak") extern(C) void SystemInit(); extern(C) void defaultResetHandler() { // if(&LowLevelInit) LowLevelInit; // if(&SystemInit) SystemInit; /* (snipped code to copy the DATA section to RAM and clear the BSS section) */ // main(); while(true){} } extern(C) void defaultExceptionHandler() { while(true){} } --->8----->8----->8----- The most important thing here is that I have not been successful in making the two subroutines LowLevelInit() and SystemInit() optional. That is: If they are not linked to startup.o, then they should simply be NULL pointers. I can do this in C, by supplying the 'weak' attribute, but so far, my attempts to do this in D have not been successful. If I enable the two lines calling those subroutines, I get link errors... startup.d:(.text+0x2): undefined reference to `LowLevelInit' startup.d:(.text+0x6): undefined reference to `SystemInit' Question number 1: How can a C subroutine be made optional, so it's called only if it linked ? You may have noticed that the VectorFunc is not a real function, but a void*. The code will work fine this way, but I'd prefer it to be more correct (if possible). Question number 2: Is it possible to change the VectorFunc to be a real function pointer, rather than a void* ? I've placed an empty main function in a file called main.d, which is linked to startup.o. If I enable calling main(); then suddenly the executable file grows from TEXT=20 bytes, DATA=16 bytes, BSS=280 bytes to TEXT=10184 bytes, DATA=2132 bytes and BSS=12824 bytes. The disassembly shows that suddenly malloc & friends are added to the executable, even though they're not used at all. I've tried renaming the function I call to something different; but that did not change anything. The things that seem to trigger that the binary file grows, is that if I call the function. I've also tried just having a pointer to the function, and nothing extra is included. Question number 3: How can I call an external function and keep the binary file size down ? I've found out that the 'alias' keyword comes in quite handy, in order to reduce the size of the source code. In my test source, you'll find that the attribute keyword is used twice in front of each function declaration. This looks quite bulky, and I'm sure it can be much improved upon. ;) Question number 4: How can I reduce the function declaration of the Reset_Handler and NMI_Handler shown above ?
Apr 07 2015
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. ;)
Apr 07 2015
On 8/04/2015 8:38 a.m., Jens Bauer wrote:On Tuesday, 7 April 2015 at 20:33:26 UTC, Jens Bauer wrote:I was going to say wrap it into a function pointer global declaration and set it in a module constructor.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. ;)
Apr 07 2015
Am Tue, 07 Apr 2015 20:38:52 +0000 schrieb "Jens Bauer" <doctor who.no>:On Tuesday, 7 April 2015 at 20:33:26 UTC, Jens Bauer 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 ;-)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. ;)
Apr 08 2015
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.
Apr 08 2015
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.ldQuestion 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
Apr 08 2015
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 ];
Apr 08 2015
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 ?
Apr 08 2015
On Wednesday, 8 April 2015 at 15:25:20 UTC, Jens Bauer wrote: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 know the C folks do this stuff all the time, but I think it's kinda janky. I know of two potential alternatives: 1) Do it in the linker script (my current method): MEMORY { CCRAM (rxw) : ORIGIN = 0x10000000, LENGTH = 64k } /* Falling stack starts at the end of the CCM */ _stackStart = ORIGIN(CCRAM) + LENGTH(CCRAM); SECTIONS { .text : { LONG(_stackStart); KEEP(YourISRVectorTable); } } 2) Use a union (See pp. 10 here: http://www.state-machine.com/arm/QDK_ARM-Cortex_STM32-GNU.pdf) C Code to be adapted to D: typedef void (*ExceptionHandler)(void); typedef union { ExceptionHandler handler; void *pointer; } VectorTableEntry; __attribute__ ((section(".isr_vector"))) VectorTableEntry const g_pfnVectors[] = { { .pointer = &__c_stack_top__ }, { .handler = &Reset_Handler }, { .handler = &NMI_Handler }, ... ect ... }; MikeQuestion 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 ?
Apr 09 2015
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: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 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.Can you successfully cast(ISR)&_stack ?Question number 2: Is it possible to change the VectorFunc to be a real function pointer, rather than a void* ?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. ;)
Apr 10 2015
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.
Apr 08 2015
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: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. MikeI 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.
Apr 08 2015
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 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.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?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.ldMine is quite huge, so I'll try out yours as a starting point. ;)
Apr 08 2015
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.
Apr 08 2015
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: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[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.
Apr 08 2015
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. ;)
Apr 10 2015
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.dYes. 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. ;)
Apr 08 2015
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
Apr 08 2015
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: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. MikeOn 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.
Apr 08 2015
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. ;)
Apr 08 2015
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.
Apr 08 2015
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: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%29&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B¤tviews=1158 MikeI 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.
Apr 08 2015
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:http://forum.dlang.org/post/mailman.2672.1403379235.2907.digitalmars-d puremagic.com arturOn 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
Apr 09 2015
On Thursday, 9 April 2015 at 10:47:42 UTC, Artur Skawina wrote: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();http://forum.dlang.org/post/mailman.2672.1403379235.2907.digitalmars-d puremagic.comOn 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
Apr 10 2015