- Posts: 4402
General development guidelines
- PhracturedBlue
- Topic Author
- Offline
8009918: e1a0c001 mov ip, r1
...
80099c8: e1a0100c mov r1, ip
80099cc: e4d1c001 ldrb ip, [r1], #1
80099d0: e2522001 subs r2, r2, #1
80099d4: e4c3c001 strb ip, [r3], #1
80099d8: 1afffffb bne 80099cc <memcpy+0xc0>
Did you try running in the debugger? I found that using gdb with the STLink and loading my elf file works reasonably well, even if it is a little fragile.
Please Log in or Create an account to join the conversation.
- PhracturedBlue
- Topic Author
- Offline
- Posts: 4402
Please Log in or Create an account to join the conversation.
- rcH4x0r
- Offline
- Posts: 33
-A memset to fill the buffer with 'A' hangs too.
-A simple for loop to copy the 7 bytes from flash to the buffer works (as does printf).
Looks like there is an issue with the libs/toolchain
Please Log in or Create an account to join the conversation.
- PhracturedBlue
- Topic Author
- Offline
- Posts: 4402
8006a78: f002 ef48 blx 800990c <memcpy>
(That isn't actually a blx, as the first nibble is 'f' which marks it as a 'BL' instruction (which makes more sense, so I guess objdump is confused see below)
However, the 1st nibble in the second byte is 'e' which is not valid for 'BL' in thumb or thumb2 as far as I can tell (it should be 11x1)
So the compiler seems to be generating bad code which is probably what confused objdump. This is the only occurrence of this I see in the firmware, so maybe something about newlib?
Please Log in or Create an account to join the conversation.
- PhracturedBlue
- Topic Author
- Offline
- Posts: 4402
in Makefile change:
$(TARGET).elf: $(LINKFILE) $(OBJS)
$(CC) -o $@ $(OBJS) $(LFLAGS)
$(TARGET).elf: $(LINKFILE) $(OBJS)
$(CC) -o $@ $(OBJS) $(LFLAGS) $(CFLAGS)
I did this, and the compiled code now looks like this:
8006a78: f002 ff48 bl 800990c <memcpy>
Please Log in or Create an account to join the conversation.
- rcH4x0r
- Offline
- Posts: 33
Please Log in or Create an account to join the conversation.
- PhracturedBlue
- Topic Author
- Offline
- Posts: 4402
Please Log in or Create an account to join the conversation.
- rcH4x0r
- Offline
- Posts: 33
Edit: Yes, that fixed it, onwards!
Please Log in or Create an account to join the conversation.
- wuselfuzz
- Offline
- Posts: 83
About using C++:
I tried an object oriented C++ approach for my quadcopter stuff once which resulted in a PWM interface with a Sam7xPWM implementation accessible as a singleton.
The resulting user code was about this simple:
int main() {
PWM& pwm=Sam7xPWM::getInstance();
pwm[0]=1000;
pwm[1]=500;
}
All the neccessary hardware setup (configuring GPIOs, creating a microsecond timer, setting up all four sam7x hardware pwm channels) worked automagically in the singleton's static constructor.
Even cout worked through the USART.
However, the drawbacks were:
- IMO, it's nicer to have a hardware_init()-function called at the start of main() that sets everything up in a specific order. Instead of read-modify-write operations for e.g. the data direction registers of a port belonging to a peripheral, this allows you to set up the registers once and be done with that.
- Using cout just once added many kilobytes of additional code. Much more bloat than just using printf.
- You need a more complex linker script and startup code to properly call static constructors.
About global (or rather file scope) variable use:
I'd rather use an object-oriented C (NOT C++) approach at many places and avoid global variables. As an example, there's the global struct Model Model and there's the function
u8 MIXER_MapChannel(u8 channel).
In an OO approach, Model would be the object, mode would be a property and MapChannel would be a method. "object oriented C" would then be like
u8 MODEL_MapChannel(struct Model *m, u8 channel) {
switch(m->mode) {
...
}
...
}
Why all the hassle? Think about flight mode switches, dual rates, and the likes.
Please Log in or Create an account to join the conversation.
- PhracturedBlue
- Topic Author
- Offline
- Posts: 4402
If you notice, I am not very consistent about this. In some cases I pass the object, and in others I directly access global variables. From a uC perspective I am used to programming on more limited platforms than the STM32, and there can be significant overhead to passing more than a couple parameters in a function call. That probably isn't particularly relevant to the stm32 though. In any case, I'm open to any improvements to cleaning up the code.wuselfuzz wrote:
About global (or rather file scope) variable use:
I'd rather use an object-oriented C (NOT C++) approach at many places and avoid global variables. As an example, there's the global struct Model Model and there's the function
u8 MIXER_MapChannel(u8 channel).
In an OO approach, Model would be the object, mode would be a property and MapChannel would be a method. "object oriented C" would then be like
u8 MODEL_MapChannel(struct Model *m, u8 channel) { switch(m->mode) { ... } ... }
I'm not sure exactly what you are referring to here though:
The mapping is only relevant for the 4 sticks (as all other input are labeled, there is no confusion about what they do). I'm not sure this is the best example to show your point.Why all the hassle? Think about flight mode switches, dual rates, and the likes.
It may make more sense for Model to be private to mixer.c and to use accessors to get at it (you'll see some of that in the code as well), but I don't think doing so will have a significant impact on the MapChannels function.
Please Log in or Create an account to join the conversation.
- PhracturedBlue
- Topic Author
- Offline
- Posts: 4402
Please Log in or Create an account to join the conversation.
- FDR
- Offline
That could benefit from inheritance too...
Please Log in or Create an account to join the conversation.
- Home
- Forum
- Development
- Development
- General development guidelines