Add support for the MSP430FR5969 platform#1581
Open
nvt wants to merge 12 commits into
Open
Conversation
The eUSCI on FR5xxx parts uses a different register layout than the older USCI: word-mode CTLW0/CTLW1/BRW/MCTLW and per-module IE/IFG/IV. This adds a UART-mode implementation with SWRST handling on word writes, UCOS16 oversampling baud-rate calculation, and a combined per-module interrupt vector that auto-clears IV on read. IE/IFG writes re-evaluate the CPU interrupt line so newly enabled flags fire and cleared flags actually deflag.
The FR5969 uses the Clock System (CS) module, distinct from the FLL-based UCS on F5xxx parts. CS selects the DCO directly via DCOFSEL/DCORSEL lookup tables (per SLAS704G Table 5-15) with no FLL locking. The module implements SELM/SELS/SELA source selection and DIVM/DIVS/DIVA dividers with separate MCLK and SMCLK so DIVM != DIVS works, plus CSCTL0 password protection with lenient re-lock on non-A5 writes (matching driverlib's CSCTL0_H = 0 idiom; no PUC, per real silicon). POR reset values follow SLAU367P §3.3: 8 MHz DCO with /8 dividers giving 1 MHz MCLK after reset.
First FRAM-based MSP430 in MSPSim. No radio is wired up; targets non-networked applications and intermittent-computing research. - FRAM emulation: FRAMController + FRAMSegment, hasFRAM branch in MSP430Core (Flash + FlashSegment vs FRAMController + FRAMSegment), and IOPort SEL0/SEL1/SELC for the FR5xxx port-mapping syntax. - MSP430FR5969Config: 64 KB main FRAM at 0x4400, 768 B info FRAM, 2 KB SRAM, eUSCI_A0/A1 + eUSCI_B0, CRC16, MPY32, 5 IO ports (P1/P2 with edge interrupts), 64-vector IVT, 20-bit MSP430X. - FR5969Node: eUSCI_A0 backchannel, Button on P4.5 (S1, active-low), port listeners. - Cooja: Msp430FR5969Mote/MoteType/LED, MspDefaultSerial falls back to "USCI A0" when the legacy "USART 1" lookup fails.
- Drop the redundant DEBUG-gated TCTL write log from Timer.java; the same call is already traced via the surrounding peripheral logging. - Split the MoteInterfaceHandler constructor call onto its own line so a thrown exception points at the constructor, not the surrounding add().
The Watchdog class hardcoded both fields of the F1xxx/F2xxx/F4xxx WDTCTL:
WDTISx as a 2-bit field at bits 0..1 with delays {32768, 8192, 512, 64},
and WDTSSEL as a single-bit field at bit 2 selecting SMCLK or ACLK.
F5xxx/FR5xxx WDT_A widens both: WDTISx is 3 bits (0..7) with intervals
from 2^31 down to 2^6 cycles, and WDTSSEL is 2 bits at bits 5..6 selecting
SMCLK / ACLK / VLOCLK / X_CLK.
With the old code, WDTIS__8192K (=0x02, meaning 2^23 ~= 1 s at 8 MHz on
FR5969) was interpreted as 512 cycles, so the watchdog reset the node
every ~64 us after watchdog_start() and prevented any etimer- or
CTimer-driven Contiki-NG code from running on MSP430FR5969. Likewise,
firmware that selected ACLK with WDTSSEL__ACLK (0x20) was silently read
as SMCLK because 0x20 & 0x04 == 0, and VLOCLK could not be modelled at
all.
Move the delay table, WDTISx mask, and WDTSSEL decoding onto
MSP430Config so each chip config supplies the right layout. Override
all three in MSP430FR5969Config with the FR5xxx values. The legacy
single-arg Watchdog constructor is kept for callers that don't go
through MSP430Config. Replace the boolean sourceACLK with a
SMCLK/ACLK/VLOCLK enum so scheduleTimer() can pick the right time
base; VLOCLK is treated as ~10 kHz (the documented nominal for the
FR5xxx CS module). Unknown WDTSSEL values (e.g. X_CLK) fall back to
the SMCLK cycle-counter path so behaviour stays defined.
Java class names must begin with an upper-case letter, and the project's
established style for MSP430 classes is "MSP430..." rather than
"Msp430...". Rename:
eUSCI_A -> EUsciA (PascalCase; keeps the eUSCI and A
distinction from TI's nomenclature)
Msp430FR5969Mote -> MSP430FR5969Mote
Msp430FR5969MoteType -> MSP430FR5969MoteType
Msp430FR5969LED -> MSP430FR5969LED
Comments and log strings that name TI's hardware peripheral (e.g.
"eUSCI_A0") are left unchanged since they reference the datasheet
identifier, not a Java symbol.
Two related fixes that let active-low buttons (and any other chip that drives a port pin) work correctly across a CPU reset: * Button.<init> now sets the IOPort pin to the released level. Previously the chip relied on the IOPort's default LOW initial state, which matched a polarity=true (active-high) button but left a polarity=false (active-low, e.g. MSP-EXP430FR5969 S1 on P4.5) indistinguishable from a pressed button. The first press read pinState=LOW and produced no LO->LO transition, so no falling-edge interrupt was raised. * IOPort.reset() no longer wipes pinState[] / IN. On real silicon a POR resets internal registers (DIR, IE, IES, IFG, ...) but does not reset externally driven pin levels - if a button is held down, the pin is still low after reset. The previous implementation cleared pinState to LOW, which combined with the Button issue above meant the released pin state set in the Button constructor was lost as soon as the CPU was reset before the firmware ran. Reset now leaves pinState untouched (initialising only null entries to LOW on first reset) and rebuilds IN from it.
P3 and P4 on the FR5969 have port-interrupt logic just like P1/P2 - the PBIES/PBIE/PBIFG registers are at 0x238/0x23A/0x23C and PnIV at 0x22E/0x23E. The previous config declared P3/P4 with only IN/OUT/DIR/REN/SEL*/SELC, so firmware writes from gpio_hal_arch_pin_cfg_set() and friends (called by button_hal_init for S1 on P4.5) hit voidIO and produced VOID_IO_WRITE/VOID_IO_READ warnings. The ports were also created with interrupt=0, so even if the registers existed IOPort.setPinState() would not have raised an interrupt on a pin transition. Add IES/IE/IFG/IV_L/IV_H to the P3 and P4 port specs and use the actual port-interrupt vectors (P3=41, P4=40, both PORTx_VECTOR / 2) when constructing the IOPort instances.
Per SLAU367P §3.3.7 (table 3-10), CSCTL6 holds the *REQEN bits (ACLKREQEN / MCLKREQEN / SMCLKREQEN / MODCLKREQEN) and its reset value is 0007h - the first three REQEN bits are enabled out of POR. The emulator was resetting CSCTL6 to 0000h instead, which would cause any firmware that reads CSCTL6 to observe an incorrect "no clock requests asserted" state. Also fix two comments that called CSCTL6 the "Fault flags" register and grouped LFXTOFFG / HFXTOFFG (which actually live in CSCTL5) underneath a "// CSCTL6: Fault flags" header. Separately, the SEL_HFXTCLK case in getSourceFrequency() returned LFXTCLK_FREQ (32 kHz) as a "default to LFXT if HFXT not configured" fallback. The MSP-EXP430FR5969 LaunchPad has no HFXT crystal and the emulator does not model the oscillator, so any firmware that routes MCLK/SMCLK/ACLK to HFXTCLK is asking for a clock the simulator cannot deliver - and silently giving them 32 kHz hides the misconfiguration. Return 0 Hz instead and log a one-shot warning. Downstream timing (Timer divides, UART baud rates) will break loudly, surfacing the issue at first use instead of pretending the firmware ran correctly.
The FR5969 uses FRCTL_A, but FRAMController was modelled mostly on the older FRCTL (ch.7). Bring the controller in line with FRCTL_A: * Honour FRCTL0.WPROT. Add FRAMController.attemptWrite(), called from FRAMSegment.write(), so writes are blocked when WPROT=1 and the Write Protection Detection flag WPIFG (GCCTL1 bit 4) is raised on the violation, per §8.2.3.1. Before this change FRAMSegment.write() always landed; firmware (or a runaway write) could overwrite FRAM with WPROT engaged, contrary to the spec. * FRCTL0: widen NWAITS from the FRCTL 3-bit field (mask 0x70) to the FRCTL_A 4-bit field (mask 0xF0). Declare AUTO (bit 3) for completeness; the emulator still does not act on it. * GCCTL0: bit 4 is WPIE and bit 3 is ACCTEIE in FRCTL_A. Add both; drop the FRCTL-only FRLPMPWR constant (bit 1 is reserved in FRCTL_A). * GCCTL1: bit positions in FRCTL_A are WPIFG (4), ACCTEIFG (3), UBDIFG (2), CBDIFG (1). The old code put UBDIFG at bit 0 (FRCTL layout) - latent bug because nothing in the emulator sets UBDIFG today. Move UBDIFG to bit 2 and add ACCTEIFG. * Per §8.6.3 all four IFG bits clear on write-0 (write-1 has no effect). The old code did W1C for CBDIFG/UBDIFG; switch to W0C across the board. Verified with a probe: writing 1 to WPIFG is a no-op, writing 0 clears it. The Memory.set()/get() debug path deliberately bypasses WPROT so the ELF loader and Cooja debugger can still poke FRAM after WPROT has been engaged.
The port-config strings declared PxSELC at offset 0x16/0x17 from each port-group base, which is the layout in SLAU367P §12's generic Px register table but not the one the FR5969 device actually implements. Per the msp430fr5969 device header, PASELC sits at 0x210, PBSELC at 0x230, and PJSELC at 0x330 - i.e. offset 0x10/0x11 from each group's base. Silent today because IOPort.writePort() has no case for SELC, so writes landed on a stored-but-unused slot regardless of the address. Fixing the offset keeps the config aligned with the device map and removes a trap for any future SELC handling in IOPort. Also add a SELC entry for PJ (PJSELC=0x330) which was missing entirely.
The field is the absolute address of WDTCTL, not the WDT_A module base - the two only coincide on F1xxx/F2xxx parts where the module is just the WDTCTL register. On F5xxx/FR5xxx WDTCTL sits at module-base + 0xC, so configs like MSP430FR5969Config rightly set watchdogOffset=0x15C even though BASEADDRESS_WDT_A__ is 0x150 in the device header. Add a doc comment so the next reader does not file the same "naming inconsistency" report.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR introduces a new MSP430 platform: the MSP430FR5969 LaunchPad. This platform lacks a radio, but comes with 64 kB of FRAM, which makes it suitable for some intermittent computing scenarios.
There is also a corresponding port of the platform to Contiki-NG in contiki-ng/contiki-ng#3143.