![]() |
Forum Index : Microcontroller and PC projects : Harmony - debunking the myths
Author | Message | ||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10201 |
The issue of Harmony has been raised on a number of threads so here is my take. First, talking about "Harmony" in the singular is too simplistic. There are a number of layers that may of may not be relevant to a particular application. At the bottom is the peripheral library which is almost identical to plib so in plib you go: data=ReadSPI1(); in Harmony you go: data = PLIB_SPI_BufferRead(SPI_ID_1); Note how the SPI channel isn't hardcoded into the call in Harmony so it is easier to re-allocate in the software. Next is the driver layer. In plib these calls are mixed in with the more primitive calls; in Harmony they are in separately loadable modules. so in plib you go: NVMErasePage(address) in Harmony you go: DRV_FLASH0_ErasePage(address) The top layer in Harmony is the application layer - this doesn't exist in plib and it is here that Harmony can seem overly complex but really isn't. If we look at setting up a Harmony project from scratch this can better explained. We use the Harmony wizard in MPLabX to create the basic project. A graphical wizard helps set up the chip configuration and we can then chose any specific drivers we are going to use. In the case of the Micromite EXTREME I only included the USB driver to support the console port. Then we click "make code" in the wizard and Harmony creates the empty project. The thing that is now likely to confuse with Harmony is that it is designed to support a real time operating system (RTOS). These typically work on the basis that a main system timer schedules everything based on a complex state machine and the top level of Harmony is very much designed to support this. The main program created is very simple int main ( void ) { /* Initialize all MPLAB Harmony modules, including application(s). */ SYS_Initialize ( NULL ); while ( true ) { /* Maintain state machines of all polled MPLAB Harmony modules. */ SYS_Tasks ( ); } } In addition Harmony, only if required or requested, sets up a routine timer interrupt which it uses to manage drivers. In the case of USB this runs every 1msec and does things like looking for connection/disconnection and deals with enumeration etc. So how does this relate to a project like the Micromite EXTREME? The Micromite code has always had a 1msec timer interrupt that Geoff uses for things like the RTC and all sorts of timers and timeouts so this MM routine was just added into the interrupt routine after the USB servicing. Harmony provides an easy hook for user code like this void __ISR(_TIMER_1_VECTOR, ipl1AUTO) IntHandlerDrvTmrInstance0(void) { DRV_TMR_Tasks(sysObj.drvTmr0); T1Interrupt(); //normal MM timer interrupt code } The SYS_Tasks call above is replaced by the main MM code which also runs in a tight loop Then, all the old plib code in the MM was replaced, in the first case to get things running by some register bashing, and now by the Harmony plib calls. So what is the overhead? Well pretty much nothing - the MX470 code handles USB in an interrupt taking place every 500msec. Harmony does it every 1000msec. It does nothing else in the interrupt except call the original MM code. The main loop works in exactly the same way as before. Harmony set up the chip automatically in its SYS_Initialize call for maximum performance, not trivial with a chip as complex as the MZ. So far I haven't encountered any bugs in the library routines used. The big downside, like much modern software, is the learning curve needed to get started (try programming "Hello World" in c#.net). Harmony does come with lots of example programs but getting them running on something other than a Microchip development board can be a challenge to start with as they use knowledge about the board (BSP library == board specific parameters?) in order to flash LEDs and read switches , do serial I/O etc. that rely on the specific wiring of the board. So in summary: is it perfect? - of course not is it usable? - yes absolutely does it incur massive overhead? no: a few extra instructions in the timer interrupt, nothing in the main program loop does it make some things simpler? Yes: USB CDC took less than an hour to get working Is it overly complex? Yes in concept, not inherently in execution Is it future proof? Well certainly more than plib which Microchip don't support on any of the newer chips, but who knows going forward |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
Interesting. I should get started with it. I hope most of Harmony works a lot better then 5-6 months ago. btw Hello world in C# is easy. :) [code] public class HelloWorld { public static void Main() { System.Console.WriteLine("Hello, World!"); } } [/code] Microblocks. Build with logic. |
||||
Geoffg![]() Guru ![]() Joined: 06/06/2011 Location: AustraliaPosts: 3282 |
Interesting, USB in two hours - I spent two weeks on it (a couple of years ago) and still did not get it working properly. I was experimenting with an early release of Harmony and there was no way of telling how many characters had been received via USB. You got a flag to say that a CDC frame had arrived but you had to assume that it contained just one character. If a number of characters arrived in the same frame you lost all the rest. The Harmony generated code was so complex that there was no way to add this critical feature. I assume that it has changed since then but this was typical of Harmony at that time (V1.0) so I just gave up on it. It wasn't helped by the MZ EF chip which had a huge number of hardware bugs. You are right about it being designed to work with an RTOS. Even setting up something simple like a timer was a nightmare because Harmony assumes that multiple real time processes will want to simultaneously access the timer. I hope that they fixed that also because you need more than a single 1mS timer. Geoff Geoff Graham - http://geoffg.net |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10201 |
case USB_DEVICE_CDC_EVENT_READ_COMPLETE: /* This means that the host has sent some data*/ appDataObject->isReadComplete = true; appDataObject->readLength = ((USB_DEVICE_CDC_EVENT_DATA_READ_COMPLETE*)pData)->length; break; |
||||
Geoffg![]() Guru ![]() Joined: 06/06/2011 Location: AustraliaPosts: 3282 |
How did you go configuring timers? Geoff Graham - http://geoffg.net |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10201 |
Harmony set up the main 1msec timer as part of initialisation (needed for USB). All other timers are easy to set up free running with the plib calls. I haven't set up another timer with an interrupt successfully but I think this is me not understanding the NVIC, priorities and shadow sets properly (or at all ![]() |
||||
isochronic Guru ![]() Joined: 21/01/2012 Location: AustraliaPosts: 689 |
Good comments matherp. I have used the beta version 2.01b to some small extent, and found it ok. The learning curve was/is a bit daunting but that is more from the complexity of what harmony is addressing rather than harmony itself. The documentation works a lot better using the help system rather than reading the pdf. The writers point out, to have a system updating a screen, Gui interface, and usb etc in real time as well as user software, requires an approach with more complexity than a single activity and blocking i/o delays. The configurator (2.01b) is good now. Eg it was very easy to set up the clock (oscillator), uart and I/O port serial comm, I used uart2 and pins 57 /58 (100 pin MZ EF) and was up and running quickly. Note for 2.01b you have get it (the configurator plugin) and install it separately. It is brilliant to be able to add a peripheral and have the system integrate it. For example a board may have some unique components that need initialization, and so it may be that a board will require/supply initialization routines. So the documentation has some emphasis on "bsp"s, (Board + Software Packages ?), but it is not necessary to use one. Likewise components will also have specific configurations, that are stored. It is a good idea to use a new configuration name for each new project. There is an associated largish BSP document describing commercially available hardware, boards etc which is also worth looking through. Some products refer to the older processors eg some entries include EC as well as EF series but the EC's are probably being phased out. Digilent put some example projects on wikidot which are useful, even though originally arduino, google "wi-fire" and "wikidot" . I think as chips become more complex, the software which can be ported rapidly to new chips will be the software that stays viable, so it is more and more necessary to use a system like this. |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |