#avr | Logs for 2015-06-29

Back
[05:51:19] <Lambda_Aurigae> aandrew, I don't have steam and no clue what the heck tis-100 is.
[06:33:01] <twnqx> a game on my wishlist :P
[08:55:57] <aandrew> it's teaching me just how much assembly I've lost :-(
[09:12:00] <twnqx> lol
[09:12:07] <twnqx> how can you lose assembly
[09:24:11] <FL4SHK> Not using it for a while I guess
[09:25:08] * twnqx is not convinced
[09:25:47] <twnqx> yum, turtle sauce
[09:26:16] <FL4SHK> Really? Have you ever gone for a while without using a particular assembly language?
[09:26:27] <twnqx> "a particular" - ok
[09:26:39] <FL4SHK> Any assembly language
[09:26:47] <twnqx> but since we're speaking about tis-100, the game, it would refer to assembly as a generic version
[09:26:48] <FL4SHK> I've used more than one
[09:26:50] <twnqx> same
[12:29:25] <DusXMT> Hi. I'm writing a set of interrupt-driven UART routines (I know there's probably tons of implementations out there, but I want to write my own, as a part of the learning experience). I have an interrupt collecting the received bytes into a circular buffer, but I'm worried about race conditions. In particular, if the function that retrieves a character from the buffer gets interrupted by the store interrupt, th
[12:29:31] <DusXMT> ere's a possibility of data loss. If I make it atomic with ATOMIC_BLOCK, however, the interrupts end up being disabled, and some data from the UART may be lost... I'm thinking of using a temporary buffer in case the retrieval function gets interrupted, but can anyone perhaps think of a more elegant solution?
[12:30:49] <DusXMT> Also, a quick question, if I make other interrupts interruptable, do they get re-entered from start (like on the x86), or does it continue where it left off?
[12:31:13] <DusXMT> (I'm using the GNU toolchain with avr-libc, my chip's an ATmega8)
[12:32:32] <LeoNerd> I usually solve that by not really doing *anything* from interrupt handlers
[12:32:53] <LeoNerd> All my nontrivial AVR programs run basically a little scheduler, which just runs down an array of "task" structures, which are basically function pointers
[12:33:18] <LeoNerd> On an interrupt, say the UART one, I'd just mark that the UART receiver task is ready to run again, and return. Then the main loop wakes up, runs that safe in the knowledge that nothing else is running
[12:33:38] <LeoNerd> If an interrupt *does* happen while the task is running, it doesn't matter as all it does is sets a runnable flag on the tasks, so that won't mind
[12:35:35] <LeoNerd> This also helps things like having two different peripherals that are both SPI-attached... when either fires an interrupt I just wake up the "You should do SPI now" task which asks both of them what they want
[12:38:36] <DusXMT> LeoNerd: Thanks for the suggestion... but isn't there a problem with marking the task as ready, since what if it doesn't get executed quick enough and the byte in UDR gets replaced?
[12:39:20] <LeoNerd> Well, if that happens then your program actually isn't fast enough to cope with incoming data anyway
[12:39:28] <LeoNerd> *when* that byte gets lost doesn't matter in that case
[12:40:24] <LeoNerd> But it depends on the hardware in question, the shape of the program, etc... E.g. for a UART, what I've done in the past is managed a little fixed-size linebuffer in the UART interrupt, and only woken up handler tasks on receipt of an entire command over the wire
[12:40:42] <LeoNerd> But that was because I could relatively easily determine when "the end" is from the interrupt handler, and I knew that I wouldn't receive another until I responded to the first
[12:42:02] <DusXMT> LeoNerd: I'm just trying to control the uC with a program I've written on the "big computer", it communicates via fixed-size messages (currently 60 bytes, but only the text-transfering messages make use of the entire message), and I want a robust way to send/retrieve data
[12:42:33] <LeoNerd> Well, if you have 60 bytes spare on the MCU then you could do the same; buffer them up and run the task when you have a full message
[12:42:42] <LeoNerd> Or even, if you have 120 bytes spare, you could bankswitch
[12:43:19] <DusXMT> Good point
[12:43:47] <LeoNerd> 120 bytes could be a lot though... depends on the MCU in question and the other requirements.
[12:44:03] <LeoNerd> But if you can't spare that, then regardless of the program layout, you won't be able to handle one incoming command while processing another *anyway*
[12:44:56] * DusXMT was trying to write a generic implementation that he'd be able to use later on, since this is only a test program to get used to serial communication with the MCU
[12:45:23] <LeoNerd> I have quite a lot of generic code I drag around. My entire tasks system, for one thing
[12:45:33] <LeoNerd> Most of the "larger" bits of code turn into other tasks anyway
[12:46:11] <LeoNerd> It's all about building a sufficiently powerful base OS abstraction
[12:47:02] <DusXMT> Well, I think I'll go with the secondary (main buffer busy) buffer then. Definitely thanks for your input though, I'm new to the world of AVR and MCUs, so I've got lots to learn
[13:19:23] <DusXMT> Or an even better solution would be, while interrupts are disabled in the bite retrieval function, manually check whether there's a byte available, the collection of which would be handled by the interrupt. (I haven't thought of it primarly because I've been mostly plotting on paper up until now...)
[13:19:36] <DusXMT> s/bite/byte/
[13:45:17] <blathijs> DusXMT: To answer your original question: If you disable interrupts for each byte access seperately, you should be good (since interrupts won't be disabled for > 1 byte time I expect)
[13:46:21] <blathijs> DusXMT: Also, realize that in a circular buffer, the ISR and main loop won't ever access the same data bytes anyway, since the ISR only writes and the main loop only reads
[13:47:45] <blathijs> DusXMT: The only conflicts could occur with the index bytes, but again each of the indexes is written by one and read by the other. If your buffer is <= 256 bytes long, the indices will be bytes so accesses are always atomic
[13:48:26] <DusXMT> blathijs: The problem is, in my circbuf implementation, I hold a boolean value of whether the buffer is empty, or contains data... I guess I might as well sacrafice that 1 byte in the buffer to determine fullness just by looking at the indexes
[13:50:07] <blathijs> DusXMT: Given that a bool is also stored as a byte, unless you can combine it with others in a flag byte
[13:50:38] <blathijs> DusXMT: But even with that bool - the ISR will write it and the loop will read it, so I don't think there will be a problem there either?
[13:50:58] <blathijs> As long as the ISR first updates the index and then the bool, I think?
[13:51:36] <blathijs> Oh, wait, the main loop has to set the bool to false of course
[13:51:49] <DusXMT> blathijs: also, from my experience with multithreaded programming, no matter how unprobable a race condition's negative outcome is, it's never good to underestimate... The reading function can be triggered at any time during program execution, when the MCU expects a message
[13:52:47] <DusXMT> I think this solution of manually cheching whether there's a byte in that tiny time period where interrupts are disabled is the most elegant solution
[13:52:52] <blathijs> DusXMT: Yeah, agreed, race conditions should be impossible, not just unlikely. I'm just saying they would be impossible (though the bool variable probably requires disabling interrupts when handling the bool, not sure yet)
[13:54:06] <DusXMT> blathijs: This is in the reading function, once it reads a byte: if (((buffer->end + 1) & (BUFFER_SIZE - 1)) == buffer->start) buffer->is_empty = true; If it gets interrupted in-between the condition and the conditioned statement, the received byte was just lost
[13:54:31] <DusXMT> s/reads a byte/gets a byte from the buffer/
[13:55:27] <DusXMT> (`end' and `start' are indexes of the last, and first valid byte in the buffer, respectively)
[13:55:35] <blathijs> DusXMT: Yeah, so I think that the mainloop should indeed disable interrupts while modifying is_empty (and of course include the modifying of end in there))
[17:54:47] <zed___> sup guys
[17:55:14] <zed___> trying to read the flash of an atmega16L using a jtagice mkI. I can read the fuse/lock/eeprom, but when I try to read the flash it times out
[17:55:48] <zed___> if the lock bits were set then shouldn't it return garbage data rather than a timeout?
[17:56:13] <Lambda_Aurigae> nope.
[17:56:22] <Lambda_Aurigae> if lock bits are set it will refuse to read I think.
[17:57:54] <zed___> is "refusal to read" equivalent to timing out?
[17:58:36] <zed___> and what should the hex values be for the lock bits to be set? the datasheet only shows individual bits
[17:59:22] <Lambda_Aurigae> could be.
[17:59:53] <Lambda_Aurigae> can't convert bits to bytes?
[18:00:21] <zed___> >.<
[18:00:52] <Lambda_Aurigae> let me look at the datasheet.
[18:00:55] <Lambda_Aurigae> gotta download it first.
[18:00:56] <zed___> http://www.atmel.com/images/doc2466.pdf
[18:01:11] <Lambda_Aurigae> just downloaded it.
[18:01:35] <zed___> well "00" is quite easy to spot though from bits -> bytes
[18:01:42] <Lambda_Aurigae> 8 bits...bits 7 and 8 are always 1
[18:01:56] <Lambda_Aurigae> well, I guess you can program them.
[18:02:00] <Lambda_Aurigae> what does the lock byte read as?
[18:02:05] <zed___> Lambda_Aurigae: cf
[18:02:46] <zed___> xxd out.bin
[18:02:48] <zed___> 0000000: cf
[18:03:07] <Lambda_Aurigae> 11001111
[18:03:20] <Lambda_Aurigae> the 00 in there is the LB1 and LB2
[18:03:31] <zed___> ;(
[18:03:38] <Lambda_Aurigae> meaning further programming and verification of flash and eeprom is disabled in parallel, spi/jtag serial programming mode.
[18:04:03] <zed___> Lambda_Aurigae: but I can read eeprom wihthout issues
[18:04:07] <Lambda_Aurigae> however, the bootloader CAN write to it.
[18:04:20] <Lambda_Aurigae> just going by the datasheet.
[18:04:24] <Lambda_Aurigae> page 259/260
[18:04:30] <Lambda_Aurigae> oh..
[18:04:31] <Lambda_Aurigae> oops.
[18:04:34] <Lambda_Aurigae> I read that wrong.
[18:04:43] <Lambda_Aurigae> the LB1/2 is bits 0/1
[18:04:45] <Lambda_Aurigae> those are 1
[18:04:48] <Lambda_Aurigae> duh!
[18:04:55] <Lambda_Aurigae> meaning no memory lock.
[18:04:56] <zed___> so those are unprogrammed?
[18:05:09] <Lambda_Aurigae> yeah.
[18:05:09] <zed___> interesting, means we've got to dig deeper :D
[18:05:15] <Lambda_Aurigae> only thing programmed is blb12 and blb11
[18:05:26] <zed___> what effect does that have? boot lock its?
[18:05:29] <Lambda_Aurigae> put a regular serial programmer on it.
[18:05:36] <Lambda_Aurigae> datasheet page 260.
[18:05:52] <zed___> only interface I've got to the device is jtag. serial interface would require soldering very tiny test points on the board.
[18:06:30] <Lambda_Aurigae> any way to slow down the jtag?
[18:06:42] <zed___> pretty sure avrdude has a setting for that
[18:06:43] <Lambda_Aurigae> I don't have or use jtag so no clue what can be done with it.
[18:07:15] <zed___> "-B bitclock"
[18:07:17] <zed___> " Specify the bit clock period for the JTAG interface or the ISP clock (JTAG ICE only). The value is a floating-point number in microseconds."
[18:07:27] <zed___> and yeah, i'm using the jtag ice
[18:07:35] <Lambda_Aurigae> ok, so set it to like 32
[18:07:39] <Lambda_Aurigae> or 64.
[18:07:58] <Lambda_Aurigae> I'm guessing the default is 10 if it is like the -B option for ISP.
[18:08:08] <Lambda_Aurigae> err,,,SPI rather
[18:08:26] * Lambda_Aurigae slaps fingers for thinking pic.
[18:09:19] <zed___> still times out on values of 64 and 32
[18:10:50] <Lambda_Aurigae> might have to wait till someone who uses jtag pops up.
[18:11:31] <zed___> alright, thanks though. at least i know those security bits aren't set
[18:11:50] <Lambda_Aurigae> yeah....if I were to actually think I wouldn't have confused us to start with those.
[18:12:05] <Lambda_Aurigae> but, it's been a long day of dealing with idiot copier customers.
[18:13:47] <zed___> ah it's cool
[18:13:50] <zed___> just set their papers on fire
[18:15:07] <Lambda_Aurigae> tempting
[18:15:20] <Lambda_Aurigae> but this job does allow me to afford some luxuries I've grown used to.
[18:15:27] <Lambda_Aurigae> like, sleeping indoors and eating.
[18:17:15] <zed___> sleeping under your desk is a nice luxury
[18:17:17] <zed___> try it sometime
[18:17:31] <zed___> you know you're living the high life when you're curled up in the fetal position under your desk
[18:18:46] <Lambda_Aurigae> sound of computer fan would keep me awake.
[18:20:50] <zed___> but is it louder than the sound of your customers screaming because you're under your desk and not listening to them?
[18:20:55] <zed___> that's all that matters
[18:29:18] <zed___> So, anyone on that knows about jtag?
[18:30:00] <Lambda_Aurigae> unfortunately I'm an onsite tech.
[18:30:09] <Lambda_Aurigae> and I'm the guy they send out when nobody else can fix it.
[18:30:16] <zed___> ...hide under your client's desk?
[18:30:17] <Lambda_Aurigae> so by the time I get there the customer is already pissed.
[18:34:47] <Tom_itx> don't shoot the messenger
[18:41:16] <zed___> Tom_itx: or kick the messenger down a really big watering hole while screaming "this is sparta"
[18:45:52] <Lambda_Aurigae> it is very seldom I leave someplace and the customer is still pissed.
[18:54:10] <zed___> So using avrdude on osx resulted in that error, on windows it worked fine to read flash
[18:54:11] <Lambda_Aurigae> even if I can't fix the problem.
[18:55:57] <Lambda_Aurigae> aahh
[18:56:11] <Lambda_Aurigae> so, sounds like you have an osx issue.
[18:56:19] <zed___> that must means osx is inferioriorior to windows
[18:56:42] <Lambda_Aurigae> naaa.
[18:56:47] <Lambda_Aurigae> just equally crappy.
[18:56:49] <zed___> yaaaa
[18:56:54] <zed___> also yes
[18:59:16] <Lambda_Aurigae> the core of osx is decent...I find the mac interface to be,,,,icky.
[18:59:53] <zed___> i unplugged a serial device that i had an open connection to the other day on mavericks and i kernel panicked
[18:59:59] <zed___> yeah, the core is great
[19:00:34] <Lambda_Aurigae> being unix, it works well...but they did some seriously stupid stuff to it.
[19:01:42] <Lambda_Aurigae> windows on the other hand is just,,,,icky all around.
[19:17:16] <FL4SHK> Windows is pretty icky
[19:17:19] <FL4SHK> icky vicky
[19:17:51] <zed___> so uh yeah, any advice on next steps from here? when using avr-objdump, how do I know which architecture it is? arv5? avr100?
[19:18:16] <zed___> using an architechture of avr-5 seems to produce some neat assembly, but I don't know if it's the right architecture
[19:25:55] <zed___> derp
[19:25:56] <zed___> http://www.nongnu.org/avr-libc/user-manual/using_tools.html
[19:26:36] <Lambda_Aurigae> just use the specific avr definition.
[19:27:01] <zed___> says atmega16l is avr5, so it worked out fine
[19:27:14] <zed___> "avr-objdump -j .sec1 -d -m avr5 out.ihex"
[19:27:35] <Lambda_Aurigae> if you specify the chip then you get things like memory size and such.
[19:28:09] <zed___> where's that option at? only oone I see related to what the target was is -m
[19:28:20] <zed___> "avr-objdump -j .sec1 -d -m atmega16l out.ihex"
[19:28:38] <zed___> "can't use supplied machine atmega16l"
[19:28:48] <Lambda_Aurigae> oh..for avr-objdump then the avr5 works.
[19:28:56] <zed___> :D
[19:28:59] <Lambda_Aurigae> I thought it was for compiling.
[19:29:14] <Lambda_Aurigae> sorry,,,ignore me,,getting more tired.
[19:29:18] <zed___> nah, not quite there yet