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
hobbesmaster
Jan 28, 2008

the arduino zero is a cortex-m0+ (atmel samd21)

this guy has it working with the m3 based arduino: http://hannobraun.de/embedded/2015-04-30-building-with-llvm/

it looks like you'd need to build a llvm tool chain including and bsp for the zero board you have. that's probably biting off way more than you want at the moment

Adbot
ADBOT LOVES YOU

Sapozhnik
Jan 2, 2005

Nap Ghost
what does this command print?

$ arm-none-eabi-ld --verbose

gonadic io
Feb 16, 2011

>>=
the platform was wrong, i've now set it for armv6.

i do also include the vector table. you can see my c code here: https://gist.github.com/djmcgill/4e35c60449a983cb0e838e6bc59a39a0
you're totally right about getting some C working before Rust though.

i looked in the MC manual, and the clock and power for the pio are both enabled by default: http://www.atmel.com/Images/Atmel-42181-SAM-D21_Datasheet.pdf (page 145)

hannobraun is the main guide that im following, since he gets it working in rust too later on in the series.

e: and i certainly feel really over my head, i bought a bunch of relays and solenoid valves and gyros i probably won't be able to touch for a long time if ever :sigh:

e2: or i could always just say gently caress it and code in c in the arduino IDE

gonadic io fucked around with this message at 00:54 on Jan 15, 2017

hobbesmaster
Jan 28, 2008

isn't it c++?

gonadic io
Feb 16, 2011

>>=

hobbesmaster posted:

isn't it c++?

gnu++11 at that

Bloody
Mar 3, 2013

I recommend reading the datasheet and understanding the details of whatever linker bullshit is necessary to get the right bits of code in the right place

spankmeister
Jun 15, 2008






sounds like you have some bit janitoring to do :iamafag:

gonadic io
Feb 16, 2011

>>=

Bloody posted:

I recommendreading the datasheet andunderstanding the details of whatever linker bullshit is necessary to get the rightbits of code in the right place

yeah that's prob it too. at the moment i've just blindly copied a few different linker scripts from the IDE

gonadic io
Feb 16, 2011

>>=
or i could just cheat and write my rust program as a library that the arduino IDE code calls...

yippee cahier
Mar 28, 2005

the D21 will have a default linker script in Atmel's ASF library, somewhere. you'll also find headers that declare a bunch of resources, might help you at the rust level, might not. i don't know about how rust expects to see memory when it starts, but there will be barebones interrupt vector with enough startup code to zero out your BSS and load statically initialized variables from ROM to RAM. check it out.

gonadic io
Feb 16, 2011

>>=

yippee cahier posted:

the D21 will have a default linker script in Atmel's ASF library, somewhere. you'll also find headers that declare a bunch of resources, might help you at the rust level, might not. i don't know about how rust expects to see memory when it starts, but there will be barebones interrupt vector with enough startup code to zero out your BSS and load statically initialized variables from ROM to RAM. check it out.

I will do thanks. I'm currently trying to link against all of arduino's libs (which include the asf ones) to do the device initialisation.

Mostly so that I don't have to copy all of this into rust: https://github.com/arduino/ArduinoCore-samd/blob/master/bootloaders/zero/board_init.c

gonadic io
Feb 16, 2011

>>=
Also I'm doing this in c to start with, but rust is fine with no_std and populating a vector table.

This guy has everything working on a Due: hannobraun.de/embedded/

But the zero seems more complicated being a samd21 instead of d20.

gonadic io
Feb 16, 2011

>>=
I'm struggling to link my c program when the arduino .ino one works. Output of obj dump is:
code:
$ arm-none-eabi-objdump -Cd main.o
main.o:     file format elf32-littlearm
Disassembly of section .text._Z5setupv:
00000000 <setup()>:
   0:	4a03      	ldr	r2, [pc, #12]	; (10 <setup()+0x10>)
   2:	2380      	movs	r3, #128	; 0x80
   4:	029b      	lsls	r3, r3, #10
   6:	6013      	str	r3, [r2, #0]
   8:	4a02      	ldr	r2, [pc, #8]	; (14 <setup()+0x14>)
   a:	6013      	str	r3, [r2, #0]
   c:	4770      	bx	lr
   e:	46c0      	nop			; (mov r8, r8)
  10:	41004408 	.word	0x41004408
  14:	41004418 	.word	0x41004418
Disassembly of section .text._Z4loopv:
00000000 <loop()>:
   0:	4770      	bx	lr

$ arm-none-eabi-objdump -Cd /var/folders/bv/yr_mdf2s2cv76npqrtq40r880000gn/T/arduino_build_499341/sketch/Blink2.ino.cpp.o
/var/folders/bv/yr_mdf2s2cv76npqrtq40r880000gn/T/arduino_build_499341/sketch/Blink2.ino.cpp.o:     file format elf32-littlearm
Disassembly of section .text.setup:
00000000 <setup>:
   0:	4a03      	ldr	r2, [pc, #12]	; (10 <setup+0x10>)
   2:	2380      	movs	r3, #128	; 0x80
   4:	029b      	lsls	r3, r3, #10
   6:	6013      	str	r3, [r2, #0]
   8:	4a02      	ldr	r2, [pc, #8]	; (14 <setup+0x14>)
   a:	6013      	str	r3, [r2, #0]
   c:	4770      	bx	lr
   e:	46c0      	nop			; (mov r8, r8)
  10:	41004408 	.word	0x41004408
  14:	41004418 	.word	0x41004418
Disassembly of section .text.loop:
00000000 <loop>:
   0:	4770      	bx	lr


Linking the ino file works fine, but linking my main.c gives this error:
~/Library/Arduino15/packages/arduino/hardware/samd/1.6.11/cores/arduino/main.cpp:47: undefined reference to `setup'
~/Library/Arduino15/packages/arduino/hardware/samd/1.6.11/cores/arduino/main.cpp:51: undefined reference to `loop'

It looks to me like the distinction is the names 'setup' vs 'setup()'. But the contents of the ino file and the c file are identical so I don't understand why different labels are being generated.

Bloody
Mar 3, 2013

looks like the top one is getting name mangled or something? section .text._z5setupv versus section .text.setup and .text._z4loopv vs .text.loop

gonadic io
Feb 16, 2011

>>=

Bloody posted:

looks like the top one is getting name mangled or something? section .text._z5setupv versus section .text.setup and .text._z4loopv vs .text.loop

That'll be it thanks, easy to fix too.

JawnV6
Jul 4, 2004

So hot ...
that one's kinda gnarly, but are you intending to also replace https://github.com/arduino/ArduinoCore-samd/blob/master/bootloaders/zero/board_startup.c ?

you'll probably want to at least read through that one, it's doing some important things behind the scenes before "main()" and however your rust is compiling it will probably need to define some of the same symbols

Spatial
Nov 15, 2007

i'm not an electrical engineer, someone check me before i wreck me. for low power stuff is estimating battery life as simple as dividing the battery capacity by average current consumption and accounting for some efficiency factor?

let's say my mcu averages 95 uA and i've got a 2500 mAh battery. assume a power efficiency of 85%.

this gives me 2500*1000*60*60 uAs capacity which is consumed at an effective rate of 112uA/s, amounting to 81,211,139 seconds or 940 days. sound about right?

Sapozhnik
Jan 2, 2005

Nap Ghost
Depends on the battery chemistry. As batteries discharge their voltage drops towards zero. Lithium batteries are great because their voltage barely drops at all until they are almost totally discharged, at which point the voltage drops off a cliff. Alkaline battery voltage drops gradually as it discharges. Below a certain voltage your circuit will fail.

(I am also not an EE and I'm kind of an embdev scrub despite it being a large part of my job but that's my understanding)

hobbesmaster
Jan 28, 2008

that voltage is how you determine current capacity. ie, you use an adc to check a voltage reference and calculate what v_bat is based on that. based on the battery chemistry you set some voltage as the "low battery" alarm and then halt if it goes below another threshold. overdischarging rechargeable batteries destroys them

anyways that is indeed how you do ballpark estimates, but make sure you do actually measure the actual current going into the mcu. the spec sheet will report what it uses without any peripherals on and running at some slow frequency

BobHoward
Feb 13, 2012

The only thing white people deserve is a bullet to their empty skull

Spatial posted:

i'm not an electrical engineer, someone check me before i wreck me. for low power stuff is estimating battery life as simple as dividing the battery capacity by average current consumption and accounting for some efficiency factor?

let's say my mcu averages 95 uA and i've got a 2500 mAh battery. assume a power efficiency of 85%.

this gives me 2500*1000*60*60 uAs capacity which is consumed at an effective rate of 112uA/s, amounting to 81,211,139 seconds or 940 days. sound about right?

if it's a rechargeable battery of some kind, at 940 days predicted life self-discharge is a serious issue and will probably be more responsible for actual lifetime than the 95uA load. the only battery chemistry i know of off the top of my head that won't self-discharge quite a bit over a time span like that is lithium primary cells ("primary" is battery jargon for non-rechargeable, secondary cells are rechargeable)

also for batteries at trickle currents you don't really need to think about efficiency all that much. the big source of inefficiency when taking energy out of a battery is its parasitic internal resistance. the power lost as heat in this resistor is P=I^2 * R. if I (current) is super low this loss is going to be negligible and you can basically ignore it, also for most lithium chemistries the resistance value R is super low too

so it was a good idea to toss some kind of fudge factor in your calculation, just not for the reasons you thought. you'll have to investigate what kind of self discharge curve your battery has to do a good estimate

finally just fyi amps are already a rate unit (1A = 1 Coulomb/s, Coulomb is the SI unit of electrical charge). the technically correct way to make the calculation you did is to calculate the charge capacity of the battery as 2500mA * 1h = 9000C and then divide by the current you're going to draw (in amps), which is like multiplying by seconds/Coulombs so the coulombs cancel out and you're left with seconds and yes i know the numbers all come out the same in the end this is just poo poo that bugs EEs

JawnV6
Jul 4, 2004

So hot ...
yeah the best you'll get is FW's taking a swing at the fudge factors because real EE's know better

Spatial
Nov 15, 2007

thanks for the learning guys. :tipshat:

i thought the discharge rate might be an important factor but I didn't think it would be the dominating one. that's interesting. it's almost certain this will be some lithium ion rechargable.

gonadic io
Feb 16, 2011

>>=
hurray i got the bare minimum blink.rs working on my arduino zero!(after doing it in c first)

https://github.com/djmcgill/to-the-moon/blob/master/rust/zero/src/main.rs

the only difference from my code a week ago is realising that the arduino linker scripts reference "isr_vector" not "vectors".

however i spent the whole week learning shitloads so i don't really consider it wasted time tbh.

next up: globals, properly setting up the interrupts, and a little abstraction so i'm not just writing to raw pointers

gonadic io
Feb 16, 2011

>>=
i have a terrible bit-janitor question:

copying the globals to data and zeroing bss is done like:
code:
// headers
extern unsigned int _etext;
extern unsigned int _data;
extern unsigned int _edata;
extern unsigned int _bss;
extern unsigned int _ebss;

// init function
unsigned int *src, *dst;

src = &_etext;
dst = &_data;
while (dst < &_edata) *dst++ = *src++;

dst = &_bss;
while (dst < &_ebss) *dst++ = 0;
my question is: i would expect the extern vars to be the addresses of the various locations. instead they're actual variables located in the exact locations, containing uninit data? does that mean that i have to be really careful about copying them, which would mean that i instead have a stack variable? wtf?

Spatial
Nov 15, 2007

gonadic io posted:

my question is: i would expect the extern vars to be the addresses of the various locations. instead they're actual variables located in the exact locations, containing uninit data? does that mean that i have to be really careful about copying them, which would mean that i instead have a stack variable? wtf?
they probably are effectively the addresses, although you don't have the whole code there so i can't be 100%.

from what i see, i'm guessing those vars are declared with their locations forced to the beginnings and ends of the relevant sections. they aren't real variables at all but merely a way to abstract the locations of the sections, which they overlap. that way the section addresses can be resolved at link time and you don't have to put magic pointers into the c code.

once this completes the real variables are all initialised and you enter main() at which point you can use them safely.

i don't know what you mean by copying them and having a stack variable.

JawnV6
Jul 4, 2004

So hot ...
when the micro boots, only the ROM is valid and RAM is trash. everything your program needs to have set up before main() needs to be set up, so that code copies a blob from the ROM to the place in RAM that code will be looking for it, and zeroes out the section that main() will assume is zero. on a big system this would be handled by the OS, on embedded it's a little shim handler like this

there's one little quote that's confusing:

gonadic io posted:

code:
src = &_etext;
dst = &_data;
my question is: i would expect the extern vars to be the addresses of the various locations. instead they're actual variables located in the exact locations, containing uninit data?
those lines of C take the address of _etext and _data. after they run, 'src' should be pointing to the section of ROM and 'dst' will point to the RAM address that it will end up in

gonadic io
Feb 16, 2011

>>=
if it were a pointer, i could pass them as parameters to functions for example to do the initialisation there.

however since they're variables with magic addresses, i have to directly reference ONLY those variables.

the moment i pass them (by value) to a function or to a local variable, say if i wanted to rename them without editing the linker script, then that special property is lost and they're useless.

just seems like a weird way of doing it to me

Spatial
Nov 15, 2007

something is being misunderstood here but it's hard to tell what.

in C, global variables are guaranteed to be initialised before you enter main(). the code snippet you showed implements that guarantee.

globals with more specific values are placed in the DATA section. having these two contiguous groups allows for efficient initialisation using memcpy() and memset() style operations.

the variables shown in that snippet have their addresses aliased to the BSS and DATA linker sections (in RAM), and the read-only constant section in TEXT which contains their initial values (in ROM or flash). they are not the actual global variables themselves and have no value, their only use is in taking their address.

global variables which need to be zeroed before entering main() are placed in the BSS section.

the purpose of the code snippet is to initialise all global variables in one efficient pass with minimal additional code size, as opposed to individually assigning each one a separate value.

this is just an optimisation though. you don't have to do that. you really can just assign values to all the global variables you've defined, or take their addresses and pass them around to other init functions. you could get rid of that initialiser snippet entirely and assign initial values to all your individual global variables in a function.

the problem with this technique is that it scales extremely poorly. it's error prone, much slower, much bigger, and means you have to know the initial values of all globals in two places in the codebase. this is why the bulk initialisation method is used, it's both faster and easier.

personally i write this stuff in assembly because it avoids confusion and is much more straightforward and explicit. in assembler you have SFB/SFE to get the ranges of individual sections so there's no crazy poo poo with aliasing things that look like variables but aren't, etc.

Spatial fucked around with this message at 17:33 on Jan 21, 2017

gonadic io
Feb 16, 2011

>>=
I understand now what that snippet does, and why it's there (and have recreated it in rust)

The main thing i dont get is why the linker gives you variables that have the address that you want, instead of giving you the pointer values themselves. It seems to me that you'd always just immediately get the address of the data, edata etc. So why make you get their addresses, and not just... Give you the addresses? Why the extra step of indirection?

gonadic io fucked around with this message at 17:39 on Jan 21, 2017

Spatial
Nov 15, 2007

ah, i get you.

the compiler doesn't know what the address will be at compile time. it merely leaves blanks in various places for the linker to fill in and produces a table of where those blanks are. the final memory addresses of sections are decided by the linker which then fills in those blanks. there are lots of different kinds of blanks, for example this is also how the offsets for jump and function call instructions are resolved.

why is it done this way? probably a historical artifact from when they couldn't fit both the compiler and linker into memory at the same time. :newlol:

Sapozhnik
Jan 2, 2005

Nap Ghost
yeah but like

what are birds variables, anyway?

a global variable is a name for a fixed location in memory. a global variable is a name for the start of a fixed location in memory. so if i had a global variable counting the number of bad posts i'd made then it would require at least four bytes to contain the entire value because i'm terrible at posting.

Consider the following mlyp.c file:

code:
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

/* Included from posts.h */
struct post;

const struct post *get_next_post(void);
bool is_post_good(const struct post *post);
/* End included from posts.h */

uint32_t bad_post_counter;

void update_bad_post_counter(void)
{
    const struct post *post;

    while ((post = get_next_post()) != NULL) {
        if (!post_is_good(post)) {
            bad_post_counter++;
        }
    }
}
you compile that .c file, the compiler spits out an mlyp.o file. if you objdump it then once you shovel through the jargon, what does an object file describe? lots of little fragments of memory, and names ("symbols") for them.

export update_bad_post_counter: This is a (let's say for the sake of argument) 27 byte area of memory that should be placed in the .text section and should be filled with the following bytes: CC 7A 4F ... whatever
export bad_post_counter: This is a 4 byte area of memory that should be placed in the .bss section. This is just memory that's reserved, it is expected that the runtime environment will arrange for .bss to be filled with zeros when execution begins.
import get_next_post: This is a symbol that this .o file depends on to do its thing (so, a function defined in some other .o)
import is_post_good: Same

That isn't a freestanding program yet because it needs to call out to get_next_post() and is_post_good(). And also update_bad_post_counter() isn't a valid entry point into the program, for a "hosted" program running on a normal OS that would be main().

Now let's say those functions that it depends on are provided by posts.c, which you also compile to posts.o. And you've got a main.c which contains main and also calls out to mlyp. You pass those to the linker and it combines everything and lays it all out in memory, then emits a single big object file; an executable.

The linker uses a link script to do this, which describes the details of the final big object file, and the conventions it must adhere to in order to be executed by its target environment. Within an operating system there's a bunch of boring crap that must be adhered to. On bare metal, however, you'll have .text dropped into the address space region that the microcontroller's ROM circuits respond to, and .bss and .data dropped into the address space region that the microcontroller's SRAM circuits respond to. You also need to provide for a _start() function, which on old crappy micros must be written in assembler and do a lot of CPU setup crap but on Cortex-M chips the reset circuitry handles all of that for you and _start pretty much just needs to clear SRAM and do nothing else. SRAM cells are feedback loops that capture and amplify their current electrical charge, so when you first power the micro on then the SRAM will capture whatever random electrical noise is floating around and amplify it until the feedback loop is stable, filling SRAM with randomized bits. This is true of all microcontrollers.

So _start() has to loop through all of .bss and set it to zero, then call main(). And the linker script helps to accomplish this. In addition to describing the memory regions in the microcontroller's address space you can also force it to define symbols at certain predefined memory addresses (for instance, the vector table must be located at a predefined area in ROM so that the microcontroller knows where to begin executing and what to execute when interrupts come in), or at certain offsets within a given section. So you can force it to define two symbols called _bss_start and a _bss_end at the locations where they need to be.

Then those locations are visible as variables. Which as we've established are just locations in memory. Instead of storing to them, your _start will put _bss_start's address into a counter, which is then constantly incremented and compared against _bss_end.

Harik
Sep 9, 2001

From the hard streets of Moscow
First dog to touch the stars


Plaster Town Cop

Spatial posted:

why is it done this way? probably a historical artifact from when they couldn't fit both the compiler and linker into memory at the same time. :newlol:

A few reasons - probably the most pressing is that dynamic linking means the compiler cannot know the symbol location when it emits a binary, so you have to have this mechanism (or force everything static, which would be a disaster). At that point, separating linking from compiling makes a lot more sense.



I managed to get a working build on this loving rockchip processor, finally. I was given the wrong device-tree by the vendor, but it was subtly wrong in non-obvious ways. Rockchip won't talk to anyone under a million a month volume, so we had to go through an integrator in china who could talk to them. They did literally nothing but use the correct DTS from the source and it's something I would have been able to fix in an afternoon had I had any way to communicate with the manufacturer. Ugh.

It took 4 months to see a #. I can bring an iMX board up in a day.

Yocto: Still not a fan, but it builds faster than I remember when I tossed it on my haswell + NVMe.

gonadic io posted:

i have a terrible bit-janitor question:

copying the globals to data and zeroing bss is done like:
code:
// headers
src = &_etext;
dst = &_data;
my question is: i would expect the extern vars to be the addresses of the various locations. instead they're actual variables located in the exact locations, containing uninit data? does that mean that i have to be really careful about copying them, which would mean that i instead have a stack variable? wtf?

Look closer: It's taking the address of _data, not the value. Because it's an address, the linker turns it into a value assignment (src = 0x0f00; dst = 0xbeef;)

src and dst are stack (more likely register) variables.

Harik fucked around with this message at 21:19 on Jan 21, 2017

JawnV6
Jul 4, 2004

So hot ...

gonadic io posted:

I understand now what that snippet does, and why it's there (and have recreated it in rust)

The main thing i dont get is why the linker gives you variables that have the address that you want, instead of giving you the pointer values themselves. It seems to me that you'd always just immediately get the address of the data, edata etc. So why make you get their addresses, and not just... Give you the addresses? Why the extra step of indirection?
are you sure they're uninitialized? some of them should overlap with other variables. a lot of these tools are dealing with the blobs in the abstract and don't really have a concept of peeking into the contents. generate a .map file if your toolchain isn't

if the linker had actual variables, it would need to carve out memory for them and the bootstrap code would load it from somewhere anyway

Harik posted:

I managed to get a working build on this loving rockchip processor, finally. I was given the wrong device-tree by the vendor, but it was subtly wrong in non-obvious ways. Rockchip won't talk to anyone under a million a month volume, so we had to go through an integrator in china who could talk to them. They did literally nothing but use the correct DTS from the source and it's something I would have been able to fix in an afternoon had I had any way to communicate with the manufacturer. Ugh.

It took 4 months to see a #. I can bring an iMX board up in a day.
who needs a OS anyway :v:

seriously thats a frustrating kind of work, especially in the arm's length support volumes

Harik
Sep 9, 2001

From the hard streets of Moscow
First dog to touch the stars


Plaster Town Cop

gonadic io posted:

I understand now what that snippet does, and why it's there (and have recreated it in rust)

The main thing i dont get is why the linker gives you variables that have the address that you want, instead of giving you the pointer values themselves. It seems to me that you'd always just immediately get the address of the data, edata etc. So why make you get their addresses, and not just... Give you the addresses? Why the extra step of indirection?

You're not thinking from the CPUs point of view. A variable is just a hard-coded address. &_data compiles to a constant.

Actually reading the value from memory is the extra step.

Just because you had to write an extra character doesn't mean more operations were performed.

Does that make sense?

gonadic io
Feb 16, 2011

>>=

Harik posted:

You're not thinking from the CPUs point of view. A variable is just a hard-coded address. &_data compiles to a constant.

Actually reading the value from memory is the extra step.

Just because you had to write an extra character doesn't mean more operations were performed.

Does that make sense?

that does actually, perfectly. i've been too coddled in langs that don't celebrate UB quite as much as c does.

Harik
Sep 9, 2001

From the hard streets of Moscow
First dog to touch the stars


Plaster Town Cop
Cool.



On my hobby front, I've decided to take the dead powerwheels barbie jeep that my kids have and overdrive it. Offhand, does anyone know if ESCs (Electronic Speed Controls) for brushless motors can drive two motors in parallel? If not I can just run both ESCs off the same PWM (servo 1-wire protocol) and hopefully they'll match pretty well.

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.

It's a fun mesh of hardware and software - the software is probably the easiest part, since it's going to be a tiny state machine (go, reverse, go fast) and a pedal on something like a STM32L dev board. Fun part is translating the random nameless components into real specs I can order. What exactly is the sizing on the drive gear? What is the motor mount style? What kind of battery connector will be able to pull 25-30A sustained? Can I make a fireproof housing for the LIPOs so my kids aren't strapped into a timebomb?

Then, and the most important bit: Some plastic etching primer so I can purge the world of one more "pink" piece of poo poo and give it a nice paintjob that's not embarassing to everyone involved.

Lots of caliper work and googling. At least I was able to take the entire electronics out so I can work on it on my bench.

I'll progress pix once I get some of the hardware parts.

simble
May 11, 2004

sounds great tim the tool man taylor *grunts*

gonadic io
Feb 16, 2011

>>=
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?

JawnV6
Jul 4, 2004

So hot ...

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?

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

Adbot
ADBOT LOVES YOU

hobbesmaster
Jan 28, 2008

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

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

  • Locked thread