wek wrote:
It's still inconvenient to manually extract the changes. Better put effort in more reasonable stuff than this...
SprinterSB wrote:But you apparently managed, haven't you?Other patches like this one are not in a valid diff format
Quote:
No. It's because the patch is invalid. Goto the bugzilla page, highlight the text and you see that there are empty lines. That is invalid.
SprinterSB wrote:That's because patch is ignorant of the DOS/UNIX line ending differences.and patch terminates with an error.
Quote:
patch is not dump, it is strict. Better reject an invalid patch than making wrong guesses.
but I was not aware of said patch's dumbness
Quote:
"'asm' operand has impossible constraints" is definitely a user error. The compiler is not supposed to hack around user code, no matter if it comes from you or from some "official" header files.
SprinterSB wrote:Quote:Something is wrong with your inline assembler. It's not a compiler bug.with -mstrict-X, several functions won't compile, an example output:
error: 'asm' operand has impossible constraints
Quote:
gives me this error:
eep = (__extension__({ uint32_t __addr32 = (uint32_t)((uint32_t)(0x30000UL + pp + __builtin_offsetof (TCfgRot, eeRot))); uint16_t __result; __asm__ ( "out %2, %C1" "\n\t" "movw r30, %1" "\n\t" "elpm %A0, Z+" "\n\t" "elpm %B0, Z" "\n\t" : "=r" (__result) : "r" (__addr32), "I" ((((uint16_t) &((*(volatile uint8_t *)((0X3B) + 0x20)))) - 0x20)) : "r30", "r31" ); __result; }));
eep.c:1:21: error: braced-group within expression allowed only inside a function
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
Topavrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopHello guys, I'm new to avr programming. I tried building avr-gcc with gcc 4.7.0 and binutils 2.22 and avrlibc 1.8 (latest releases), but I seem to be missing some microcontrollers from the available devices list. Mainly the atxmega128a3u, which I'm currently using.
What are the recommended versions for stable builds, which also include the latest microcontrollers? I don't want to be on the cutting edge, just to be stable (don't really care for size optimizations just yet)
- Log in or register to post comments
Top- Log in or register to post comments
Top- Log in or register to post comments
Topavrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopAs Atmel's 4.5.1 toolchain does support that device seek out their patch set and find out what the patch that adds 128a3u actually affects. Then make similar mods. to the files in the toolchain source you are using. IOW backport the patch to 4.7.x
- Log in or register to post comments
Top@admin: Could this sub-thread be broken out?
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopThey are violating GPL again? ;-)
(they have made several issues of 4.5.1 but I don't think they've posed the patch set for the latest one yet).
[I'll split this out later - I have to take the cats for a walk now]
- Log in or register to post comments
TopMaybe, but it's not worth the hassle right now. In a new code I'll consider that.
In some of the inline asm pieces the direct use of address in inline asm was necessitated by running to the limit of constraints (yes they are lengthy). IIRC they are all ISRs so they might be replaced by "regular" assembler, but I'd expect that that approach would require to use the "used" attribute for -flto too.
JW
- Log in or register to post comments
TopWhat I don't agree with is "to get significantly better code absolute control is inevitable". "Getting significantly better code" is a completely different thing than "need 100% control over result". Don't confuse them with each other.
Just imagine your example from above: How many additional assembler pieces, sprincled all over the code, would you need to reduce code size by 1%? And how big would the effort be?
Setting/unsetting a compiler switch is a trivial action. What would the "stick to asm if you like to..." approach mean with respect to resources needed and maintainability of the project? It's much less paint so see if, for example, -fno-move-loop-invariants can do the same boost. And it's 100% non-intrusive to the sources.
Don't get me wrong: I also use assembler in my brojects where I want best performance and where it's clear that compiler will never be as smart as brain. But that's no "how better code? --> use asm" reflex.
Some years ago, a friend pointed me to Baumann's Lichtzeitpegel clock sculpture in the Rheinturm in Düsseldorf. I decided to handicraft such a clock, but had absolutely no idea how. My Pa just mumbled "SPS" and with "SPS" I started searching until I came across a model railroader's site that used a "Microcontroller" thing. Even managed to find that site again.
The "µC thing" appeared more reasonable than the "SPS thing" and I bought some of these AT89C2051, a breadboard, a propretieary assembler and programmer and started with the clock. During the project I learned assembler programming, how to decode DCF77 time signals, drive > 40 LEDs per SPI + 74*595, program interrupts and debounce switches, implement a menu, output morse signals to find my way through the menu during setup, drive external 24C02 EEPROM and shake the "alarm", a handicraft wind chime made of aluminium tubes.
And during information minig I came across pages with Nixie tube clocks, and I decided a Nixie clock was the next project.
But the assembler was just an annoyance and the built-in editor was scrap and could not be replaced. And the license stuff was just an annoyance, too. And programming in assembler was no real fun after all, partly because it was assembler, and partly because the assembler's language features were really poor and restricted.
I found almost pin-compatible AVR AT90S2313. And I found avr-gcc readily available with WinAVR, installed it, wrote some C programs, learned how the tools work and interact and what programmer there were -- all before I even bought a single piece of AVR related hardware. The software part looked really good and was kind of deliverance compared to the former assembler IDE.
The next step was the hardware: I started with the 1€ setup: A RS232 breakout, a transistor, some Z-diodes, resistors and a AT90S2313 on a breadboard and connected all that sauerkraut circuit with my computer.
From that point on development was easier and I wasted much less wime with the tools. On the other side, I learned obout the tools and how to apply them in the best way. Knowing about what's under the surface will always enable you to get superior results and work faster and with much more ease.
The WinAVR I used was 20060421 which is avr-gcc 3.4. That compiler produced really good results, but still showed many optimization shortcomings. Thus, I tried newer versions of avr-gcc but observed from version to version that the code size went up according to the genenral rule of thumb: avr-gcc 4.x produced code size increase and thus also speed degradation of 5%-10% compared to good old 3.4.
What then drew my attention to the compiler internals was a thread that reported problems with a wrong code. I knew that source code very well as I wrote it and it float around in the net; but the error was not in my piece of code. Instead, my sorce snippet revealed a "wrong code" compiler bug. I got curious and started digging in the compiler and found the root cause of the defect.
It took me some time to figure out how all the patch and open source projects and process are organized, but finally my first patch was accepted and integrated to fix the aforementioned PR42240. That was roughly one year ago.
To keep on contributing has several reasons:
First, It's a pity to see how such a great project got worse and worse over time, accumulated more and more bugs and flaws that are not fixed.
Second, maybe it's giving something back to a great project, instead of a "expect all for nothing" attitude or a "constantly complain and nag but let others do the job" attitude.
Third, is "hack the project? or hack the compiler?". Hacking around inferior code in the source is never a good thing: It obfuscates the source. It is unstable under migration (new toolchain). It's unstable under porting (other hardware). It's costly to find the places and work out how the hack will be. It has the potential to introduce bugs. It avoids optimization if an updated toolversion actually has the flaw fixed -- you won't even notice it with the hack. And it's simply the wrong place: Fix the root cause, not the symptom! I saw code snippets that praise their use of inline assembler, where the same optimization can be achieved with straight forward C and a compiler change that is smaller than the inline assembler hack!
Fourth, disbelief of the kind "it cannot be that hard to teach the bloody compiler what's trivial and obvious to any assembler programmer". On the surface you just see trivial and obvious goal, like "this instruction is suportluous" or "this sequence could be smarter like so".
Sixth, interest in how a real-world compiler and one of the most important free software works. Solving Sudoku is boring after you solved the 3rd puzzle: They are all the same. With problems in GCC this is different.
Seventh, curiosity. For example "how many of brain's smartness can be packed into a software?". An example is the __builtin_avr_insert_bits buit-in which is rather an exercise in finding a smart solution to a problem than an important or even requested extention.
Eighth, aesthetical reasons. That are changes like code cleanup, coding rules and layout, documentation and readability of source, avoid redundancies, find smart and neat solutions instead of clumsy ones, etc.
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopThis is what I think:
Yes, it's a good thing to have a canonical place to learn about things. One place is the tool's/component's documentation.
If there is more elaborate explanation with worked out examples, description of how things interact and all these things, that's certainly a good thing.
I don't think dropping anything at one place is a good thing. A good tutorial should be selective and pick instructive example and work them out.
"The more the better" does not hold IMO.
Flooding such a site will all kinds with information is not helpful at all to the beginner. For a noob there is so much new stuff that he must be overwhelmed by it: New editor environment, new hardware and all the oddities of a new language like C. And we all know C has many oddities and features that are non-intuitive. Getting the hardware settings right like baud rate, like fuse settings, like JTAG, like interrupts, like finding SFR and bit names, like finding right header. Connecting all that stuff and controlling the programmer. Learn what tools are there and how they interact. Understand what's going on under the surface and besides all the obfuscation introduced by tools. (If, for example, you don't see that an error message is from the linker or even are aware that there is something like a linker, it's much harder to understand the error message and the solution). Understanding build and make process. And many, many more.
There are so many things that are new that a noob will drown in all that information.
And I think the link/information I posted above is simply too unimportant to be dropped at such a place and distract noobs, confuse them, put focus on things that are completely irrelevant at that time.
"Urgent! I am late with my project but there is an error. Pls. give details description as soon as possible!"
then I don't even waste a single second on it. Spending the whole life for it is the other opposite...
If people don't even care for what they are actually doing, don't care for what tools that they actually use, don't care for what documentation is included. How am I supposed "link" would help them?
avr-gcc documentation links to avr-libc. WinAVR documentation comes with avr-libc documentation. Even in PDF. Even with elaborate examples. Even with detailes description of how tools interact. Even with detailes description what subpackages are included and where they are hosted.
As I wrote, a wiki-based system is much less effort than a patch-based one.
Still can't believe and don't understand why people prefer to write "[TUT] as thread" and produce tapeworm threads with up to several hundreds of posts. And just beneath there is a wiki perfectly suitable for such information, with much better web-typographic, with categories for articles, with graphics, with chapters and sections, with table of contents, with history, with authors that can be talked to, with discussion page. How old is wiki paradigm and technique now?
But completely bypassed, ignored, deserted, for whatever reason.
@admit. Maybe the "tweak options" can be broken out?
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopYou don't need to worry about beginners - evidence here suggests they don't read the documentation anyway. But experts know where to look and they would like all the documentation in one place.
Already this page has been growing recently:
http://www.nongnu.org/avr-libc/u...
Just adding a few more pages to articles of use does not mean that the reader is going to feel "swamped" by over-information.
Well personally I do like to try and help beginners get started because I was one once and know what it's like. The great thing about GCC is that there is such a great manual (even an online copy) so that the majority of questions ("how do I use EEPROM?", "how do I store data in flash?", "why are my ISR/main variables not updated?") can be answered by it.
Oh and the Atmel Wiki failed because it is was hosted on a server powered by steam and rubber bands (anyway that was about "AVR" in general, not avr-gcc in particular).
- Log in or register to post comments
TopIt's solely related to friendlyness and netiquette and against the "you help me a.s.a.p. because me to lazy to RTFM" attitude.
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopYes but 99% of the time these people are "needy" because it wasn't obvious to them where to look for the manual that would answer all their questions.
It does seem a failure of everything that installs avr-gcc in either a Windows or Linux environment that it does not make it much clearer where the installed copy of the manual (which I take to be the AVR-LibC HTML or PDF files) have been installed on the user's hard drive.
To me trying to use something as complex as a optimizing/linking compiler without at least a brief look at some over-view and a quick summary of the most often used command line options is doomed to failure (I'm always reminded of Gert Frobe flying a plane for the first time in "Those Magnificent Men In Their Flying Machines" - but at least he was reading the manual as he went along - the first landing being the most "interesting" bit - it's only when the seagull steals the manual that he really becomes unstuck).
All installation programs should as a very minimum say "if you don't do anything else at least take 5 minutes to familiarize yourself where "this" is located as you ARE going to need to refer to it at some point".
- Log in or register to post comments
TopYou sure, Cliff? So you just reserve a tiny 1% to reasons like
- Oh man, i can do that within 2 days, and there's a month left for the assignment
- My girl friend has just asked to go to the cinema
- I just didn't make it yet to that fancy new disco in town
- Manuals??? What's the teacher for then???
- Thinking of scheduling my project? Naaah, there's that superfreak that throws complete solutions even for the most demanding and lazy guy.
Your confidence in the average student seems to be quite high. I know, we were all novices one day, but some of us had a student life some 20 years ago as well, right?
Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."
- Log in or register to post comments
TopCinema? Disco? LOL!
- Log in or register to post comments
TopMore findings.
1. More "unused" variables were dropped, but went unnoticed initially. This time, it was a block of data allocated to a fixed position in FLASH through a "manually" assigned section, and never used in C program. It is used as an identification for other utilities.
Johann, could you please help me locating the switch for the linker to print the "dropped" variables?
2. This was fatal: I have "reserved" registers such as (note that I am already paranoid to add the "used" attribute everywhere):
yet the compiler uses them throughout. As I use these in ISRs, this had various "funny" consequences (the code was mostly working though).
It appears that -ffixed-2 et co. helped on this.
If the "allocation through asm("rX") is officially non-functional now, you should perhaps submit a patch for the relevant section in avr-libc's documentation http://www.nongnu.org/avr-libc/u...
Jan
PS. I've just noticed, that with -ffixed-X in place and with no other changes, the program's size *decreased* further - from 141863 bytes reported previously, to 138827 bytes... Shall I feel disturbed? :-?
- Log in or register to post comments
TopI am no ld compendium, sorry ;-)
Be more specific and show an example, presumably you betray the compiler. Are you saying you have
and avr-gcc allocates R2 in some_vect?
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopJan
- Log in or register to post comments
TopIf the register (one of R2..R7) is global and reserved there, it must not be used. If it's not global, the compiler may use it, of course.
Registers from R8 on might be required by the ABI. You can reserve them, but there might be clashes with the ABI. There is a warning like PR45099, fixed in 4.7.0.
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopI spent quite some time trying to reproduce the problem, but I can't reproduce it on my home computer... The sources I have here are somewhat older, but the routine where I have seen the r2..r5 registers be used is unchanged... I don't understand.
Tomorrow at work I will get back to the problem (if time permits) and will report.
JW
- Log in or register to post comments
TopDon't forget to remove the -ffixed- ;-)
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopI have spent many hours trying to produce a minimal example, to no avail. Only if I compile the whole project the problem appears (registers r2-r5 are used in some functions originating in C, even if they were "forbidden" defining "register unsigned char r2 asm ("r2");" as global variable).
Findings:
- this is clearly a LTO problem in linker (during linking): the "forbidden" registers are NOT present in the assembler output from compiler, only in the linked result in .elf
- in functions where the "forbidden" registers appear in the .elf, they are properly pushed/popped in prologue/epilogue (except for main(), which appears to have stripped prologue/epilogue, but that was expected)
- I made sure that the "forbidding definitions" are present in every C source - some of the files with functions small and simple enough not to use the "low" registers ever did not have them before - no change
- could not reproduce the problem when trying to compile and link one of the smaller functions which in the big project exhibited the problem separately from the project, even if the assembler output from compiler is exactly the same (except it has one more unused label) in both cases - in the "minimal" experiment the linker maintains a small stack frame, whereas in the big project it replaces it with the "forbidden" registers
- it is enough to use -ffixed- during linking to remove the problem
- it is not sufficient to use -ffixed- during compilation (and not use it during linking) - in that case problem persists
I now can't spend more time on this. I am willing to cooperate in experiments if anybody has ideas what to try to do next.
JW
- Log in or register to post comments
TopI saw this post from a few days ago. Has anybody tried his instructions on building?
http://maniacbug.wordpress.com/2...
- Log in or register to post comments
TopI'm having a problem compiling for an Xmega32A4U. I'm trying to use what seems to be the latest version you linked. I'm using it from within AVR Studio 5.1, setting it as the toolchain to use for one of my projects. The error is below, that it doesn't recognize the 32A4U. iox32a4u.h is also missing from the include directory, so I guess it just isn't supported by this version of avr-gcc. It seems odd that it isn't. Do you know why?
- Log in or register to post comments
TopYou must give a valid argument to -mmcu=
Otherwise you will get an error.
For a list of valid arguments read the note or the compiler output with --help=target
You can compile code for the architecture by setting -mmcu=avrxmega2 for example. But you will need startup code and header support, too.
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopI wasn't asking why it isn't working, I was asking why that device isn't supported in the expected way. I realize it's fairly new, but my impression was that devices were often supported before they were even released. I'm more wondering about the process that gets MCUs fully supported (you seem to have some insider knowledge) than how to get it working (my current setup is working fine for me).
- Log in or register to post comments
TopMoreover, headers for SFR descriptions, device-specific prototypes like EEprom support routines and vector table definitions are needed.
Compiler and binutils support could be avoided alltogether. The device support is only about header, startup code and libc as mentioned above. The compiler driver just calls the linker with appropriate startup code.o and sets -Tdata and built-in define for the device.
Instead of compiling/assembling with -mmcu=device you just as well can use -mmcu=core -D__AVR_Device__ and add -nostartfiles -Tdata=... -m core to the linker call.
The formal process to add support for whatever feature to GCC or binutils is to provide a patch, and let it approve my respective maintainer. Moreover, you must put your GCC and binutils changes under GPL.
http://gcc.gnu.org/contribute.html
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopThat's interesting, thank you for describing the process. I kind of understood that the compiler didn't need extremely device specific information -- like specific register addresses, etc. -- that are in the header file, but I didn't realize that AVR-LibC did so much at the low level. I just assumed that it provided common C functions like printf and some stuff like delay. I should have known better, because I use interrupt.h quite a bit, but I never thought about how it fits into the rest of the toolchain.
Thanks again!
- Log in or register to post comments
TopCompile for AT90S8515:
Compile for AT90S8535:
even though both devices are in architecture avr2. This because of some unnamed silicon erratum.
For devices supported by avr-gcc, see ./gcc/config/avr/avr-mcus.def.
For respective binutils list, see ./gas/config/tc-avr.c.
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopMinor observation:
This particular erratum is officially acknowledged in Atmel's published AT90S8515 errata sheets:
http://www.atmel.com/Images/DOC1... (rev B silicon)
http://www.atmel.com/Images/DOC2... (rev C silicon)
- Log in or register to post comments
TopNow you can go and search what the second device is that's affected by this silicon bug...
Is there an official errata list, i.e. a map bug -> device instead of the device -> bug map?
Otherwise, you'd have to read several hundreds of data sheets to find out what devices are affected; not really applicable if you need to find out all affected devices or all core errata that need to be worked around by the tools...
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopYou're right, Atmel's current method of publishing errata is really only useful for end-users of particular devices - it's pretty horrible for people who are trying to maintain tools which apply to many different devices.
- Log in or register to post comments
TopJohann,
in your build, http://sourceware.org/PR13410 appears to be fixed, even if the bug report says fixed for binutils 2.23 while your build contains 2.22.
Can you please confirm?
Thanks,
Jan
- Log in or register to post comments
TopBinutilas are not as eloquent as gcc that says 4.6.1 or 4.6.1 DATE (experimental) or 4.6.1 DATE (prerelease).
In GCC speek it would be 2.23 (experimental) I guess?
As you might know, binutils uses CVS as VCS where versioning is really confusing, at least to me...
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopOkay, I see. Honestly, I did not go back to the post where you gave the link, sorry.
I take it as "yes", then... :-)
Thanks,
Jan
PS. This was one of the two linker bugs I came aware throughout the years here on avrfreaks. The other is related to gs() (thus 'M256x, maybe the bigger XMegas too) and *no* -relax; a quick check reveals that that one still persists.
PS2.Submitted the latter to binutils bug tracker
- Log in or register to post comments
TopThanks for the problem number (PR14058)
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopFYI, GCC 4.7.1 release is scheduled for end of next week:
http://gcc.gnu.org/ml/gcc/2012-0...
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopNice! Cannot wait for an offical release with latest binutils and avr-libc!
GCC guys are impressive!
- Log in or register to post comments
Topavrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopI uploaded a new snapshot "avr-gcc-4.7.1-rc1-mingw32.zip" to the same directory as the other snapshots.
- Binutils fixes some wrong code issues with --gc-sections and --relax
- Binutils supports XCH, LAS, LC, LAS instructions
- Binutils supports data expression modifiers like .byte lo8 (symbol)
- avr-gcc comes with a working -mint8.
- For a more complete list problems fixed in 4.7.1, see Bugs Fixed in 4.7.1
The zip file is bigger (45MB inflating to 110MB) because it includes documentation (info, man, html, pdf).For notes on how to "(un)install" the toolchain, see the notes with the previous snapshots.
Versions:
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopIt works fine here, LTO is working too for the first time for me, gained an extra 50 bytes :)
You are the man 8)
- Log in or register to post comments
TopThanks SprinterSB, I would like to build that on Linux (Fedora 16 I686). Should I use just the SVN versions or are there more patches that I need to apply?
AFAIK, newer XMEGA devices are still missing (to be more specific, I look for xmega32a4u). Please correct me if I'm wrong.
- Log in or register to post comments
TopIf you want to add support for a device to the tools, it's a one-lineer:
Unfortunately, there is PR53595. I hacked around that one by combining the compiler from the march snapshot with binutils from the recent snapshot. Without that hack code size increases by 2% for PR53595 alone.
It's kind of mice-milking business...
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopThanks for the build, Johann.
Findings:
- you did not include the patch I posted at http://sourceware.org/bugzilla/s... , did you find any problem with that?
- with -flto, the problem with the linker using "reserved" registers I reported above persists
- with -mstrict-X, several functions won't compile, an example output:
All lines reported above contain pgm_read_byte_far(SOME_CONSTANT_OFFSET + some_16_bit_variable). The functions are lengthy (which is IMO expected for the kind of error above), which is why I can't provide a minimal example at the moment, but am willing to discuss/cooperate if you are interested.
- without -flto the application I used above for the tests compiles and appears to run correctly
Jan
- Log in or register to post comments
TopIn easy way to get a patch is
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopIMHO that's one of the points of the plaintext and almost-human-readable format of diffs. I guess diff/patch back then started with people posted smaller changes simply by quoting the changed lines, manually adding "-" and "+" to them as appropriate; and diff/patch only "machinized" the process to allow for larger changes and automated processing.
However, I found it illustrative to post the patch as part of the explaining text. I could have done both; but I was not aware of said patch's dumbness (okay we can call it *nix-centrism, if you want :-) ).
As I reported in https://www.avrfreaks.net/index.p... , I could not produce a minimal example. Trust me that I tried hard. For obvious reasons I am unable to post the whole project, but am willing to cooperate in experimentation, although IMHO it is not worth spending more time on it, as it is a minority problem and workaround is known - I would just suggest to mention it in documentation (should any happen).
You should start having more faith in that I know what am saying, Johann... ;-)
This is not *my* inline assembler - as I said above, all occurences involve lines with pgm_read_byte_far(). You will find it in. One example of preprocessed output of a line throwing this error:
And I did not say it is a compiler *bug*, but it certainly is a compiler-produced, uhm, feature :-) It apparently can't resolve the register pressure in extreme cases. Again, I don't think this is worth to spend more time on this, and would simply "solve" this "problem" by mentioning it in documentation.
Jan
- Log in or register to post comments
Top