Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
gonadic io
Feb 16, 2011

>>=

hobbesmaster posted:

if you have c++11 look at std::atomic and let the compiler deal with it

edit: wait, you're on a m0, you don't have strexb. disregard

also rust :q:

Adbot
ADBOT LOVES YOU

Sapozhnik
Jan 2, 2005

Nap Ghost
Probably the only universally safe way to do this on ARM is using the bitband regions (google it).

ARM's atomic ops are of the load reserved/store conditional variety. This protects you against interrupt pre-emption between the load and the store but it does not protect you against the register itself changing under your feet. Well-designed micros don't do that, they always have separate command and status registers, but you should check the data sheet just to be sure.

Whether LLVM bitcode has a way of faithfully expressing ARM atomic ops I don't know.

hobbesmaster
Jan 28, 2008

^^ not on m0s, right?

std::sync::atomic then but I would inspect the assembly output if you have interrupts because you don't have the exclusive instructions

hobbesmaster fucked around with this message at 20:46 on Jan 23, 2017

Bloody
Mar 3, 2013

JawnV6 posted:

yeah, whatever you're reading has other bits set that you don't want to perturb. so you need a read (to figure out what's already set), modify the one bit of interest, then a write with your new value

disabling interrupts is one way to make sure you won't be preempted. you could also solve it with a lock specific to the register or resource, even if you were interrupted the other thread couldn't get the lock, so your RMW operation would appear atomic

or just target a different processor with bit set/bit clear instructions for atomic bit modification!

Sapozhnik
Jan 2, 2005

Nap Ghost
@microcontroller_dril
Do I have the best-designed peripheral layout register imaginable? No. But, do I at least have robust atomic load and store ops to make the best of a bad situation? Also no.

JawnV6
Jul 4, 2004

So hot ...

Bloody posted:

or just target a different processor with bit set/bit clear instructions for atomic bit modification!

i phrased it that way because i thought Rust had some under-the-hood thing that would generate a mutex/lock for you :shobon:

but yeah MSP430 bis/bic supremacy

Storysmith
Dec 31, 2006

Harik posted:

I need to either magic up an analog pedal in the space constraints of the current "go button" fake pedal, or just implement soft-start speed ramping on my micro.

look at how guitar foot pedals are done, you can either go geared potentiometer or led blocking wedge into the middle of a homemade vactrol in that size easily

you'll need to rig a return spring obvs and a kill switch on the dash

Raluek
Nov 3, 2006

WUT.

Storysmith posted:

look at how guitar foot pedals are done, you can either go geared potentiometer or led blocking wedge into the middle of a homemade vactrol in that size easily

you'll need to rig a return spring obvs and a kill switch on the dash

is just going to a junkyard and spending $7.59 for a dbw pedal out of the question? although i dunno if the jy would try to call it a pedal + sensor, in which case it'd be like, over $20 and gently caress that

gonadic io
Feb 16, 2011

>>=

samd21g manual posted:

Before entering the STANDBY sleep mode the user must make sure that a significant amount of clocks
and peripherals are disabled, so that the voltage regulator is not overloaded. This is because during
STANDBY sleep mode the internal voltage regulator will be in low power mode.

i love this sentence, it's my favourite one so far.

now i feel like a hardware programmer. nothing is absolute, there are no hard limits

hobbesmaster
Jan 28, 2008

enjoy your new life of going through 1000 page reference manuals to find the one number you need

Spatial
Nov 15, 2007

also, the number is wrong :(

Sweevo
Nov 8, 2007

i sometimes throw cables away

i mean straight into the bin without spending 10+ years in the box of might-come-in-handy-someday first

im a fucking monster

also the peripheral doesn't work, and the solution in the errata is "don't use it"

Bloody
Mar 3, 2013

and its the on every rev of the chip

Bloody
Mar 3, 2013

exhaustive list of microcontrollers whose DMAs work as advertised:

Sapozhnik
Jan 2, 2005

Nap Ghost
idk the EFM32's DMA worked pretty well i.m.e.

and I did some fairly aggressive poo poo with it, driving multiple I2C buses as well as a SPI bus

now, i was but a baby embdev at the time, and didn't realize that driving a slow i2c bus with the dma controller instead of an interrupt-driven fsm was massive overkill

but it worked

Phobeste
Apr 9, 2006

never, like, count out Touchdown Tom, man

gonadic io posted:

I'm switching my code to properly use volatile read and writes, which correspond directly to the llvm instructions: http://llvm.org/docs/LangRef.html#volatile-memory-accesses

But now I have an &= in my code. Do I just have to do a read and then a write? I suppose it's not a multithreaded env so that's not a worry, but I should make sure that interrupts are disabled for it?

depending on the register (more common for registers the designers think will be frequently twiddled) you may have strobe interfaces, where you have a SET register you can write to and it'll set any bit that was a 1 in the write to the set. so you don't have to read it

gonadic io
Feb 16, 2011

>>=
i think i'm doing something dumb here.

i'm trying to enable the RTC, by setting the mode, prescaler, and enable bits as instructed.

the enable bit is synced, so according to:

samd21g manual posted:

When executing an operation that requires synchronization, the Synchronization Busy bit in the Status
register (STATUS.SYNCBUSY) will be set immediately, and cleared when synchronization is complete.
The Synchronization Ready interrupt can be used to signal when synchronization is complete. This can
be accessed via the Synchronization Ready Interrupt Flag in the Interrupt Flag Status and Clear register
(INTFLAG.SYNCRDY). If an operation that requires synchronization is executed while
STATUS.SYNCBUSY is one, the bus will be stalled. All operations will complete successfully, but the
CPU will be stalled and interrupts will be pending as long as the bus is stalled.
The following bits are synchronized when written:
• Software Reset bit in the Control register (CTRL.SWRST)
• Enable bit in the Control register (CTRL.ENABLE)

i'm writing to CTRL.ENABLE and then waiting on the STATUS.SYNCBUSY bit.

code:
let rtc = RTC as *mut RTC_Mode_0;
        unsafe {
            (*rtc).control[1].set(PRESCALER);
            (*rtc).control[0].set(MODE | ENABLE);
            while (*rtc).status.get() != 0 {} // FIXME: hangs
        }
If I comment out the status check, or set it to "== 0" then the code runs as expected and i get my blinking LED.
but if i attempt to wait for the syncbusy, then it waits indefinitely.

i've checked, and clock/power to the RTC is enabled on reset. the enable bit IS set when i write to it (and is zero before). i've checked that the syncbusy bit is zero before the operation, and as far as i can tell you don't need to do anything to enable the sync functionality.

i tried setting all of my interrupts to just immediately return too, but no difference there. the syncbusy bit just...isn't set...

e: hmm, let me fiddle around with the global clock a bit

gonadic io fucked around with this message at 13:27 on Jan 26, 2017

Jerry Bindle
May 16, 2003

From the description, I think the syncbusy bit is clearing itself automatically after you enable the RTC, you don't need to poll on it.

e: In other words, the syncbusy may go high for a few cycles immediately after the RTC is enabled but then it goes low again before your `while (*rtc).status.get() != 0 {}` executes.

Jerry Bindle fucked around with this message at 15:13 on Jan 26, 2017

Sapozhnik
Jan 2, 2005

Nap Ghost
You're not waiting for the SYNCBUSY bit in the STATUS register to be clear, you are waiting for the entire STATUS register to be zero.

gonadic io
Feb 16, 2011

>>=
Update: I got openocd working and managed to crash gdb a bunch

gonadic io
Feb 16, 2011

>>=

Sapozhnik posted:

You're not waiting for the SYNCBUSY bit in the STATUS register to be clear, you are waiting for the entire STATUS register to be zero.

I did an & 1 << 7 too, sync busy is the only bit on that register.

gonadic io
Feb 16, 2011

>>=

Barnyard Protein posted:

From the description, I think the syncbusy bit is clearing itself automatically after you enable the RTC, you don't need to poll on it.

e: In other words, the syncbusy may go high for a few cycles immediately after the RTC is enabled but then it goes low again before your `while (*rtc).status.get() != 0 {}` executes.

If that was low, then the loop would never iterate.

Jerry Bindle
May 16, 2003

gonadic io posted:

If that was low, then the loop would never iterate.

oh i see, i think i got confused because you said it never gets set... if you have access to a field engineer, it might make your life easier to ask them. the most frustrating thing to me is not being able to tell if firmware is wrong, or if i've found a silicon bug. its really difficult to confirm a silicon bug diagnosis unless you've got someone at the sausage factory willing to tell you. good luck!

Sapozhnik
Jan 2, 2005

Nap Ghost
post the disasm

gonadic io
Feb 16, 2011

>>=

Sapozhnik posted:

post the disasm

will do.

i'm fairly sure this is something i'm doing wrong, i guess i'll go back to C until i get it working

Spatial
Nov 15, 2007

is "rtc" marked as volatile? if not the compiler will likely transform the loop to one memory access followed by an [effectively] infinite loop.

gonadic io
Feb 16, 2011

>>=

Spatial posted:

is "rtc" marked as volatile? if not the compiler will likely transform the loop to one memory access followed by an [effectively] infinite loop.

yep it is. i even put asm!(""); in the loop but no change.

JawnV6
Jul 4, 2004

So hot ...

Sapozhnik posted:

post the disasm

this is the next step when C messes up too

JawnV6
Jul 4, 2004

So hot ...
double post, but I took a look at the repo

you're setting up a struct with all the variable names, then instantiating it at the right base address? im assuming the [#c] bit is saying "lay this out like a dumb C POD struct, don't reorder, don't collapse". it might generate the right asm, but I'd be reluctant to give that much choice to the compiler. i'd want to know at the site I'm writing to a device exactly how wide that access will be, seems like you might specify writing to a byte-sized chunk and ending up with a 4-byte unaligned access somewhere

i wouldn't change the names at all. you have a couple deltas, more friendly names, replacing vowels, etc. idk, maybe it's just my terrible practices but if a name doesn't come up with a grep -iRl i'd probably assume it doesn't exist

gonadic io
Feb 16, 2011

>>=

JawnV6 posted:

double post, but I took a look at the repo

you're setting up a struct with all the variable names, then instantiating it at the right base address? im assuming the [#c] bit is saying "lay this out like a dumb C POD struct, don't reorder, don't collapse". it might generate the right asm, but I'd be reluctant to give that much choice to the compiler. i'd want to know at the site I'm writing to a device exactly how wide that access will be, seems like you might specify writing to a byte-sized chunk and ending up with a 4-byte unaligned access somewhere

i wouldn't change the names at all. you have a couple deltas, more friendly names, replacing vowels, etc. idk, maybe it's just my terrible practices but if a name doesn't come up with a grep -iRl i'd probably assume it doesn't exist

that's what im doing yeah.
i have mostly been adapting the original files, so samd21g18a.h containing:
#define PORT ((Port *)0x41004400UL) /**< \brief (PORT) APB Base Address */
becomes samd21g18a.rs with:
pub const PORT: *mut PIO = 0x41004400 as *mut PIO; // (PORT) APB Base Address

and then
code:
/** \brief PortGroup hardware registers */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef struct {
  __IO PORT_DIR_Type             DIR;         /**< \brief Offset: 0x00 (R/W 32) Data Direction */
  __IO PORT_DIRCLR_Type          DIRCLR;      /**< \brief Offset: 0x04 (R/W 32) Data Direction Clear */
  __IO PORT_DIRSET_Type          DIRSET;      /**< \brief Offset: 0x08 (R/W 32) Data Direction Set */
  __IO PORT_DIRTGL_Type          DIRTGL;      /**< \brief Offset: 0x0C (R/W 32) Data Direction Toggle */
  __IO PORT_OUT_Type             OUT;         /**< \brief Offset: 0x10 (R/W 32) Data Output Value */
  __IO PORT_OUTCLR_Type          OUTCLR;      /**< \brief Offset: 0x14 (R/W 32) Data Output Value Clear */
  __IO PORT_OUTSET_Type          OUTSET;      /**< \brief Offset: 0x18 (R/W 32) Data Output Value Set */
  __IO PORT_OUTTGL_Type          OUTTGL;      /**< \brief Offset: 0x1C (R/W 32) Data Output Value Toggle */
  __I  PORT_IN_Type              IN;          /**< \brief Offset: 0x20 (R/  32) Data Input Value */
  __IO PORT_CTRL_Type            CTRL;        /**< \brief Offset: 0x24 (R/W 32) Control */
  __O  PORT_WRCONFIG_Type        WRCONFIG;    /**< \brief Offset: 0x28 ( /W 32) Write Configuration */
       RoReg8                    Reserved1[0x4];
  __IO PORT_PMUX_Type            PMUX[16];    /**< \brief Offset: 0x30 (R/W  8) Peripheral Multiplexing n */
  __IO PORT_PINCFG_Type          PINCFG[32];  /**< \brief Offset: 0x40 (R/W  8) Pin Configuration n */
       RoReg8                    Reserved2[0x20];
} PortGroup;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
becomes
code:
pub struct PIO {
    pub dir: VolatileCell<u32>,
    pub dir_clear: VolatileCell<u32>,
    pub dir_set: VolatileCell<u32>,
    pub dir_toggle: VolatileCell<u32>,
    pub out: VolatileCell<u32>,
    pub out_clear: VolatileCell<u32>,
    pub out_set: VolatileCell<u32>,
    pub out_toggle: VolatileCell<u32>,
    pub in_: VolatileCell<u32>,
    pub control: VolatileCell<u32>,
    pub wr_config: VolatileCell<u32>,
    pub _reserved: VolatileCell<u32>,
    pub p_mux: VolatileCell<[u8; 16]>,
    pub pin_cfg: VolatileCell<[u8; 32]>,
}
where VolatileCell just enforces volatile reads and writes.

then later i'll wrap this in methods that make more sense from the outside and obey the occasional read-only/write-only register.

gonadic io fucked around with this message at 08:00 on Jan 27, 2017

JawnV6
Jul 4, 2004

So hot ...
that preserves the granularity, but in rtc.rs there's byte widths?
code:
#[repr(C)]
pub struct RTC_Mode_0 {
    pub control: [u8; 2],
    pub read_req: [u8; 2],
    pub ev_control: [u8; 2],
    pub inten_clear: u8,
    pub inten_set: u8,
    pub int_flag: u8,
    _reserved1: u8,
    pub status: u8,

gonadic io
Feb 16, 2011

>>=

JawnV6 posted:

that preserves the granularity, but in rtc.rs there's byte widths?
code:
#[repr(C)]
pub struct RTC_Mode_0 {
    pub control: [u8; 2],
    pub read_req: [u8; 2],
    pub ev_control: [u8; 2],
    pub inten_clear: u8,
    pub inten_set: u8,
    pub int_flag: u8,
    _reserved1: u8,
    pub status: u8,

are you talking about the arrays or the reserved field? that's the definition right out of the manual, but instead of a single u16 field they're bitflags so i split them up.

gonadic io
Feb 16, 2011

>>=
hmm, i think i may have broken my arduino by flashing the wrong thing. i was trying to upload using openocd and flashed the wrong section of memory.

anyway after reburning the bootloader using the ide (Amtel EDBG) i have blink.rs working again but can't load the globals anymore. i got the debugger working and it's going into the hard fault interrupt handler so i guess im making trying the stuff in http://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html

is this a thing that's possible to have hosed it up? the offending code is identical to what was working before*

i checked the addresses of the linker variables:
code:
$ arm-none-eabi-nm target/arduino-zero/debug/zero
20000020 D __data_end__
20000000 D __data_start__
000026ac R __etext
* essentially just
code:
  unsigned int *src, *dst;

  src = &__etext;
  dst = &__data_start__;
  while (dst < &__data_end__)
    *dst++ = *src++;

yippee cahier
Mar 28, 2005

if you want to go down the debugging path, make yourself handlers for the other faults that result in a HardFault if unhandled then read out the status registers associated with whichever one you're triggering. on a CM4, sometimes you get the the address of an offending instruction directly.

EDIT: if you have a real debugger attached, don't worry about the assembly. you can just set a breakpoint in the hook and inspect the registers and stack.

yippee cahier fucked around with this message at 18:14 on Feb 3, 2017

Spatial
Nov 15, 2007

the M0 doesn't have the other fault handlers or the cause-of-error registers, only hardfault. that thing is cut down to the bone

e: however, you can make a decent crashdump because of the way the exception stacking works. the program counter and link register [among others] are placed on the stack automatically before entering the hardfault handler. see here for the layout.

Spatial fucked around with this message at 19:15 on Feb 3, 2017

gonadic io
Feb 16, 2011

>>=
i hope you're happy thread:

gonadic io
Feb 16, 2011

>>=
also i think i've been fundamentally misunderstanding a bunch of stuff.

how does the bootloader code interact with the binary code? does it matter if they contain the same symbols or sections? or does it just handle flashing, and the reset button etc and they don't actually share any env?

Bloody
Mar 3, 2013

they most likely do not share anything

also clean breadboards will always make me extremely happy

JawnV6
Jul 4, 2004

So hot ...
nice, clean wiring

i sorta prefer to color code things, at the very least vcc/ground should be red/black




gonadic io posted:

also i think i've been fundamentally misunderstanding a bunch of stuff.
same

Adbot
ADBOT LOVES YOU

gonadic io
Feb 16, 2011

>>=

JawnV6 posted:

nice, clean wiring

i sorta prefer to color code things, at the very least vcc/ground should be red/black

same

i only got one set of wires colour coded by length. and i ain't got a snipper/stripper. hence you can see me bending the red ones at the top to the right length

  • Locked thread