Jump to content


  • Content Count

  • Joined

  • Last visited

Reputation Activity

  1. Like
    jayaura reacted to spirilis in SMCLK cant drive 2 peripherals?   
    No, the x2xx user's guide tells you. TACCR0 Interrupt The TACCR0 CCIFG flag has the highest Timer_A interrupt priority and has a dedicated interrupt vector as shown in Figure 12-15. The TACCR0 CCIFG flag is automatically reset when the TACCR0 interrupt request is serviced. TACTL |= TAIE is a separate interrupt from the TACCTL0 |= CCIE interrupt, per the documentation.  You only have an ISR defined for TIMER0_A0_VECTOR, which is the interrupt vector for TACCR0.
    From msp430g2553.h near the end:
    #define TIMER0_A1_VECTOR (0x0010) /* 0xFFF0 Timer0)A CC1, TA0 */ #define TIMER0_A0_VECTOR (0x0012) /* 0xFFF2 Timer0_A CC0 */ TIMER0_A1_VECTOR is what fires when the timer resets back to 0 when TAIE is set in TACTL.  With no ISR defined there, I'm presuming the CPU branches to the default ISR which is reset (haven't confirmed that but I think that's it).
    If you want to prove this, try defining a simple TIMER0_A1_VECTOR interrupt function that blinks an LED or something and re-enable the TAIE in TACTL.  Actually this function doesn't have to do anything really... it can be blank, just so that it exists and ties up the TIMER0_A1_VECTOR interrupt vector slot so it doesn't get assigned to the default vector handler.
  2. Like
    jayaura reacted to spirilis in SMCLK cant drive 2 peripherals?   
    Oh, right... TACCTL0 |= CCIE already enables an interrupt for that CCR, and then TACTL's TAIE enables a different interrupt (for when the timer resets) I think.  I'm guessing the "default interrupt if the user hasn't defined one" is something that's screwing you up (like resetting the chip).
  3. Like
    jayaura reacted to pabigot in Analyzing blinky's disassembly   
    Nothing short of editing the linker script or providing an alternative definition will affect __watchdog_support. It belongs there. Do not mess with it. 
    To use the built-in watchdog, simply don't add

    WDTCTL = WDTPW + WDTHOLD; anywhere. That turns the watchdog off. Instead, make sure you invoke __watchdog_clear() every 32ms. 
    Use __set_watchdog_clear_value() to assign a new value (WDTPW + something) that configures the interval you want; even if you do, still invoke __watchdog_clear() at the required frequency. Consult the family user's guide for details on how to determine alternative configuration values.
    No; that manual is completely out of date and does not mention these functions. Look at intrinsics.h that was installed with the compiler, and experiment. 
    Probably nobody but me ever used those functions.
  4. Like
    jayaura reacted to Rickta59 in Analyzing blinky's disassembly   
    When using 'C', the compiler always gives you enough rope to hang yourself. When I was writing the msp430 fabooh framework, I also wanted to get rid of this extra bloat. When I compile this:
    the output is this:

    msp430g2231in14_release/blink.elf: file format elf32-msp430 Disassembly of section .text: 0000f800 <__watchdog_support>: f800: b2 40 80 5a mov #23168, &0x0120 ;#0x5a80 f804: 20 01 0000f806 <__init_stack>: f806: 31 40 80 02 mov #640, r1 ;#0x0280 0000f80a <__do_clear_bss>: BCSCTL1 = CALBC1_8MHZ; DCOCTL = CALDCO_8MHZ; #endif } else if (MCLK_FREQ == 1000000) { BCSCTL1 = CALBC1_1MHZ; f80a: d2 42 ff 10 mov.b &0x10ff,&0x0057 f80e: 57 00 DCOCTL = CALDCO_1MHZ; f810: d2 42 fe 10 mov.b &0x10fe,&0x0056 f814: 56 00 clear(pins_mask); pren |= pins_mask; } static ALWAYS_INLINE void setmode_output(const uint8_t pins_mask) { pdir |= pins_mask; f816: d2 d3 22 00 bis.b #1, &0x0022 ;r3 As==01 static ALWAYS_INLINE void clear(const uint8_t pins_mask) { pout &= ~pins_mask; } static ALWAYS_INLINE void toggle(const uint8_t pins_mask) { pout ^= pins_mask; f81a: d2 e3 21 00 xor.b #1, &0x0021 ;r3 As==01 void loop(void) { while (1) { RED_LED::toggle(); delay(msec_delay); f81e: 2e 43 mov #2, r14 ;r3 As==10 f820: 3f 40 82 45 mov #17794, r15 ;#0x4582 f824: 1f 83 dec r15 f826: fe 23 jnz $-2 ;abs 0xf824 f828: 1e 83 dec r14 f82a: fc 23 jnz $-6 ;abs 0xf824 f82c: 03 43 nop f82e: f5 3f jmp $-20 ;abs 0xf81a 0000f830 <__stop_progExec__>: f830: 32 d0 f0 00 bis #240, r2 ;#0x00f0 f834: fd 3f jmp $-4 ;abs 0xf830 0000f836 <__ctors_end>: f836: 30 40 3a f8 br #0xf83a 0000f83a <_unexpected_>: f83a: 00 13 reti Disassembly of section .vectors: 0000ffe0 <__ivtbl_16>: ffe0: 36 f8 36 f8 36 f8 36 f8 36 f8 36 f8 36 f8 36 f8 fff0: 36 f8 36 f8 36 f8 36 f8 36 f8 36 f8 36 f8 00 f8 I compiled the code above like this:
    $ make Compiling file: blink.cpp msp430-g++ -c -mmcu=msp430g2231 -Os -Wall -Wextra -DFIXMATH_NO_CACHE -DFIXMATH_NO_64BIT -DFIXMATH_NO_ROUNDING -fwrapv -fmessage-length=0 -ffunction-sections -fdata-sections -std=gnu++98 -g -ggdb3 -fno-rtti -fno-exceptions -fverbose-asm -DFABOOH -DF_CPU=1000000 -MD -MP -MF msp430g2231in14_release/blink.d -I../../../ -I../../../board/msp430g2231in14 -I../../../include/msp430/core -I../../../include/3rdparty blink.cpp -o msp430g2231in14_release/blink.o Linking target: msp430g2231in14_release/blink.elf msp430-gcc -mmcu=msp430g2231 -DFIXMATH_NO_CACHE -DFIXMATH_NO_64BIT -DFIXMATH_NO_ROUNDING -fwrapv -fmessage-length=0 -ffunction-sections -fdata-sections -mmcu=msp430g2231 -mdisable-watchdog -Wl,--gc-sections,-Map=msp430g2231in14_release/blink.map,-umain -L../../../board/msp430g2231in14 msp430g2231in14_release/blink.o -o msp430g2231in14_release/blink.elf If you look at the main.h header file, you can see how I replaced the system functions with my own versions that do nothing: 
    Another thing to reducing the size is to use the -mdisable-watchdog flag. That gets rid of all extra WDT code.
    Of course when all this fails to work, you can at least claim your code is small
  5. Like
    jayaura reacted to wasson65 in Analyzing blinky's disassembly   
    In a nutshell:
    Programming in C:  Now why did that stupid compiler do that in a wasteful and ultra-careful way?
    Programming in Assembly: Now why didn't that stupid programmer spend 4 extra cycles to make that routine generally safer?
    Once upon a time, there were people who coded PC applications in assembly because it made for faster programs.  Then the machines got faster, compliers got a little better, and assembly really wasn't worth it any more on PC's.
    Because libraries have to work (generally) on multiple architectures, and programs (generally) have to co-exist in memory and systems (generally) are multi-tasking, and interrupt routines (generally) must leave the environment exactly as they found them, there are things that the compliers are going to do, just to be 'good citizens'.  A good part of this 'good citizenship' can be dropped if you have intimate knowledge about the environment that the code is going to have to run in, which we (generally) have.
    And when the amount of application logic is large compared to the amount of hardware specific logic, these tradeoffs make a lot of sense.
    On our little '430s the hardware specific logic is probably 80% of our entire codebase, so the generalizations can begin to consume a non-trivial amount of space and cycles, which, as you know, we never have quite enough of....
    Viva la Assemblia!  - lol
  6. Like
    jayaura reacted to pabigot in Analyzing blinky's disassembly   
    BTW: The value in __watchdog_support() is not supposed to be WDTHOLD. If you choose to turn off the watchdog in main() (as your program does), that's fine, but the toolchain should not make that policy decision for you. Instead it preserves the power-up setting, and uses the value it saved on startup to ensure the watchdog does not fire during the startup code.
  7. Like
    jayaura reacted to pabigot in Analyzing blinky's disassembly   
    All your questions relate to mspgcc's runtime support infrastructure and are independent of the program you've compiled.
    Because the value that needs to get written to the watchdog timer to reset it varies depending on MCU, and the expression computed by __watchdog_support reads the current setting then changes it to be a valid reset that preserves that setting. (Specifically, in some MCU families the bits that produce the power-up default timeout interval are different because of clock differences, so having a constant won't work across all platforms. I didn't want yet another chip-specific object file, so I found a general solution.)
    It's copied into RAM so that subsequent uses of the intrinsic __watchdog_clear() know what value to write. mspgcc also supports intrinsics __set_watchdog_clear_value() and __get_watchdog_clear_value(). It is the only toolchain that does this, so since it's not supported anymore people will have to create a new solution to the problem.
    Because your example doesn't use the built-in watchdog support, but the runtime system doesn't know that so it leaves it present.
    The value copied to r15 is defined at link time, and is not zero when you have global variables that must be initialized before main() gets invoked.
  • Create New...