Thanks for the input, all.
Neither JTAG nor standart UART worked, unless I enabled reduced device drivers and small C library, i.e. polling. This was with the NIOS /e core.
I have since switched to the /f core, which solved the problem. One day when I have time (or when it comes back to bite) I might hunt down the issue, but for now I'll live with the core change.
This may be a separate issue altogether, but I also experienced strange behaviour when passing character pointers between my own functions with the /e core. This might have had something to do with incorrect variable alignment in memory. Nevertheless this was also fixed with the /f core.
-DB