Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by pabigot

  1. Remember you're working with a 16-bit microcontroller: the maximum value you can assign to TA0CCR0 is 65535, which is about 65ms at 1MHz clock. Your 1045000 decimal is 0xFF208 hex which truncates to 0xF208 16-bit which is 61960 ticks or 59ms. You need to use a slower (or divided) clock source if you want alarms at longer periods. VLOCLK at about 8-12 kHz would work as you could delay up to about 5 seconds but with poor accuracy; preferably use a 32 kiHz crystal feeding ACLK.
  2. You'll need the datasheets. It's tied to a dedicated pin WAKEn described as: An external input that brings the processor out of Hibernate mode when asserted.
  3. At some point (possibly now) the following might be useful to you: /* Ensure CC2500 CSn is held high to avoid issues with use of I2C. */ #define BSP430_PLATFORM_STANDARD_INITIALIZE_EPILOGUE do { \ P3DIR |= BIT0; \ P3OUT |= BIT0; \ } while (0) I use this in platform initialization on the RF2500T when I don't intend to use the on-board CC2500. Without it, I2C does not behave as desired.
  4. Reading TxR is the right answer to the first approximation. There are complexities, though. When the clock driving a timer is asynchronous to MCLK, a read of TxR may return garbage. If the clock source is much slower than MCLK, you can avoid this by reading in a loop until you see the same value twice (the "majority vote" technique). If the clock source is faster, you need to dedicate a capture/compare register and toggle CCIS0 in TxCCTL to synchronously capture the counter value. You can see code that implements these different read techniques in and around this part of BSP430'
  5. Turns out that, although CMSIS structure code I provide executed the same effective operations as TivaWare's function in the same order, it was wrong: section 10.3 of the TM4C123GH6PM data sheet specifies the configuration process, and has the GPIODIR register set first, not last. No idea why it works in the "wrong" order for TivaWare or with the delay, but if the GPIOF->DIR assignment is moved first the delay is not necessary.
  6. I'm a little confused by this description. AFAICT PRIMASK is exactly the Cortex-M version of MSP430's GIEn. The CPS instruction does nothing but enable or disable either PRIMASK or FAULTMASK. TivaWare's IntMasterEnable() is a function that invokes "cpsie i", meaning it clears PRIMASK (as opposed to "cpsie f" which clears FAULTMASK, "cpsid i" which sets PRIMASK, etc.). This is exactly what __enable_irq() in <core_cmFunc.h> does except that __enable_irq() is inline and provides a memory barrier that's probably implicit in the IntMasterEnable() function call. __get_PRIMASK() is the sta
  7. BTW: I'm also working in this area and will be posting a related discussion once I've got everything fully understood, but a lot of what you've written is very true and complements the approach I'm taking. FWIW, default for stdin/stdout/stderr is line-buffered; you can use setvbuf() to disable it with newlib, but if you're using newlib-nano it doesn't work. You can follow that battle here. Update 20140411: The issues with newlib nano turn out to be an idiocy in the linker scripts provided by CMSIS for GCC. Significant space savings can be obtained by using -specs=nano.specs when link
  8. I saw a hint of that in your post which snuck in while I was writing. I'd still look at the linker script to make sure that the material that the compiler is putting into specific sections (so it can be found) actually make it into the final image. Also be aware that the standard gcc-arm infrastructure (if you're using the GNU for ARM Embedded on launchpad.net) is coupled with newlib: the startup routine just zeros bss, and it's _mainCRTStartup in newlib that copies over data, runs constructors, etc., before handing off control to main(). May be that Energia's missing something that's normally
  9. Hmn? OK, knowing nothing about Energia especially on Stellaris, a thought: the TI linker scripts from TivaWare strip out a lot of stuff, including all the sections and init code that's normally what invokes static constructors. It's part of the reason I ditched them and went with the startup infrastructure provided by ARM and gcc-arm, which seems more likely to work for C++ or even C modules that put functions in the .ctors and .dtors sections. That's my best guess without actually looking into it; hope it has some relevance. (Re @@spirilis comment that you can't guarantee the s
  10. In some cases it might depend on context; in my situation there were subsequent uses of h in the code, and changing the expression did swap a couple instructions around but did not change whether the volatile object was read after it was written, or the code size and instructions used. I can reproduce your results showing size variation in an isolated example with the flags you provided, but after adding -Os the difference reduces to whether an instruction appears before or after a compiler-generated but unreferenced label. The instruction sequence is the same for both alternatives with -
  11. Obscurity of the sort I used in the last post irritates me, so let me correct it by providing the details of the teaching I meant to convey: The basic understanding of volatile-qualified objects in C is that the qualifier forces the compiler to execute exactly the operations specified in the source: the optimizer cannot add, remove, or change the order of reads and writes. This is true. What's also true is that, subject to certain limitations imposed by the presence of sequence points, the C standard states that the definition of access to a volatile object is implementation-defined (6
  12. But this is not true. AFSEL is a single register that is not accessed using bitbanding: the TivaWare code that implements the equivalent to the CMSIS operation is: HWREG(ui32Port + GPIO_O_AFSEL) = ((ui32PinIO & 2) ? (HWREG(ui32Port + GPIO_O_AFSEL) | ui8Pins) : (HWREG(ui32Port + GPIO_O_AFSEL) & ~(ui8Pins))); Which is just as much an RMW operation as the CMSIS version. Bit-banding is relevant for operations on a GPIO DATA register
  13. So I've played with the github CMSIS stuff enough to know it can be made to work, though there are bugs in it (the GPIOA_Type structure is wrong for the DATA field, which should be an array of 256 words at the start of the struct, rather than a single word after 255 words of padding). Also a lot of defines for bit fields within the registers are missing. Here's a taste of some examples translating code from the ek-tm4c123gxl uart_echo demonstration from driverlib to CMSIS: // Get and clear the interrrupt status, then loop while the RX // FIFO has data #if CMSIS - 0 UART0->ICR =
  14. TI's APIs aren't efficient in size or speed; e.g. UARTIntClear(UART0_BASE, value) is a function call, even if you use the ROM implementation. Other solutions aren't quite so bad; the equivalent in EFM32-land is: USART0->ICR = value; which is a direct write through a pointer to the struct that lays out the registers belonging to the peripheral instance. TI doesn't even provide a struct declaration for their peripheral registers; they have macros that expand to each individual register (as you showed), and they make you include the specific device header for that even though every devi
  15. Dealing with memory mapped registers, and ensuring the consistency of shared values in the face of interrupts, often requires use of the volatile qualifier in C. Given the following code: typedef struct sFIFO { volatile uint16_t head; volatile uint16_t tail; const uint16_t length; volatile uint8_t buffer[1]; } sFIFO; #define FIFO_ADJUST_OFFSET_NI(fp_,v_) ((v_) % (fp_)->length) static __inline__ int fifo_push_head_ni (sFIFO * fp, uint8_t v) { uint16_t h = fp->head; /* ... */ #if PICK_ONE h = fp->head = FIFO_ADJUST_OFFSET_NI(fp, 1 + h); #else fp->head = h = FIFO_
  16. No, it'd be treated just like any other global variable. Ordinary globals won't be copied into RAM, though they might be cached in registers for some duration that depends on how much the compiler knows about what the program does. (I suppose technically some compiler might use a block of RAM as "extra registers" rather like an off-processor cache, but for that to be worth doing it'd probably have to be a non-uniform memory architecture.) From the perspective of C (specifically mspgcc, but other compilers should use the same policy with different linker section names), const globals are
  17. "const volatile" is an odd combination, but as you found it's what's necessary there. (Or neither const nor volatile, which would probably work too.) FWIW, read-only special-function registers like P1IN are marked const volatile.
  18. Can't speak to any variations from the chip you need to support, but BSP430 has code to interact with the BQ27510. It's pretty trivial; converting the 16-bit elements from big-endian to little-endian is the worst part.
  19. I hadn't been aware of the j modifier before, so thanks for that. In practice, though, rather than casting everything to intmax_t (which would be a huge overhead and wouldn't work with msp430-libc which doesn't support it) the proper solution, if you tolerate ugly printf statements, is to use <inttypes.h> and something like: printf("%" PRIu32 "\n", u32_value); This is the portable way to use printf formatting with the exact-width types.
  20. Yes, it only bites me with printf (and because I insist on using -Werror -Wall). The point is that it is not really necessary to use the bit-sized typedefs in this situation, but ARM's done it anyway: it's encoded into CMSIS. Probably there's some reason GCC prefers long over int for 32-bit, which is really where things go off the rails; they could've used int. It's just irritating; using PRIu32 everywhere makes the code even more ugly.
  21. I should clarify: the CMSIS Peripheral Driver Interface which includes the USB interface in was added in CMSIS 4.0, which was only released a month ago. There's no implementation of it from TI or (AFAICT) anybody else; it's just the specification for an API which, if you implement to it, means you'd be able to re-use code that depends on it on any other Cortex-M device that also implements it. (Maybe; I'm a long way from looking at USB support on these things.)
  22. Tying this back to a sub-discussion at 43oh: CMSIS defines an API for USB host and peripheral devices. Implement that for TM4C, then bridge from that to LUFA (if necessary), and you'd have something that could work across the entire Cortex-M ecosystem.
  23. Or have bad drivers (or poorly designed/named ones), make your customers angry, and hope that they've got too much invested in the proprietary approach that they won't take the time to switch. (Because if they do, they won't be coming back.) I do not believe that a quality API that enhances common core functionality is best created by greenfield development. It's a continuing frustration to me that people insist on creating new solutions rather than adopting existing ones (or adapting themselves to accept existing ones). Of course, when I do exactly that I believe I have good reasons
  24. I admit I'm trying to grasp CMSIS myself, in part because vendors are not supporting it in its full glory so I can't find working examples. My top-level understanding is CMSIS is a standard API specifying how names are spelled and what the corresponding function/macro/variable means. The implementation is expected to provided by the silicon vendor, generally using templates supplied by ARM. There are several layers and blocks in the architecture. Vendors appear to delegate to CMSIS_DSP (a source library), but EFM32 adds only CMSIS-CORE, and TI doesn't even do that. I have yet to fin
  25. AFAIK every processor in the Cortex-M series is 32-bit. This means that every C/C++ compiler should use a 32-bit type as the basic int type. I'm unaware of any compiler that doesn't do this, so my beliefs have yet to be contradicted. The compilers I've seen also choose to make long a 32-bit type. I have no problem with this (if they provide some type so uint64_t works). What I have a problem with is vendors like TI that choose to use "long" instead of "int" as the fundamental type in their APIs. ** Then, when they quietly stop doing that (as they have with TivaWare), ch
  • Create New...