0
\$\begingroup\$

I'm developing a custom protocol processing device based on MCU. My protocol is somewhat similar to I2C and uses bit-banging instead of hardware implementation. I've done a prototype based on Atmega328P, mostly due to plenty of help online and cheap development boards. When everything started to work, I discovered that I'm not satisfied with the maximum speed of protocol processing logic. Even though most instructions are processed in 1T on Atmega328P, and it has a reasonably fast ISR latency (only 4T), the main problem is a lot of push/pop instructions are added to preserve/restore registers.

Now, I'm considering some other MCU architecture, which will allow me to run my code faster. I hope modern 8051 core based MCU might be an option.

EMF8 for example can run on 50-75MHz, same as ARM, can run 70% of instructions in 1T. Although, it will take 9T+9T to enter and exit ISR, I hope that it may not need to push/pop so many registers, as it can work with RAM directly, without mandatory use of registers (as in Cortex). For some reason AT89 are not even listed on Microchip web site after take over of Atmel. There others available, but I don't know how they can be compared.

Cortex-M0(+) is another option, but there people on the internet complaining about large ISRs latency, even though according to ARM it should be streamlined and efficient. Although it will allow me to run code 3x times faster on 48MHz, it will most likely to suffer from the same issue as Atmega328P, as it had to push/pop lots of registers. I also don't think that I will benefit from 32 bit architecture, as my code doesn't use any math and mostly based on uint_8t types.

I hope people have experience with new 8051s and can provide their opinion.

=== EDIT to provide more details ===

  • The protocol is synchronous, it uses 2 pins: one for clock, one for data.
  • ISR is on pin change, however with AVR I can't have separate ISRs for clock and data, as both pins on the same port. I have more logic in ISR to identify which pin has changed.
  • On 16MHz clocked atmega I'm having 10kbps (kilobit) with full logic in ISR and 50kbps with bare minimum. I established that 25us after pin toggle in master is sufficient for slave to process the change with bare minimum of logic. 10us is not enough, it starts missing clock.
  • The code is implemented in pure C no ASM. All push/pops are inserted by avr-gcc. I can see in decompile that all registers r18-r31 are preserved/restored.
\$\endgroup\$
  • \$\begingroup\$ The MCS-51 architecture uses a bank-switched register set, where the R0..R7 bank in use is selected from 1 of 4 sets using two PSW bits. The Accumulator still needs to be stacked if your ISR needs it. A fast ISR still needs to vector to the ISR, push the PSW, push the ACC and OR the PSW to select (say) R0..R7 bank 3. But you can maybe skip the push ACC or the register if you're only doing bit banging or rotating memory to do a serial shift register, for instance. Depends what you need to do and how honed you can write it, I did a good many fine-tuned ISRs. \$\endgroup\$ – TonyM Feb 17 '18 at 22:29
  • \$\begingroup\$ by the way, what kind of ISRs are we talking about? Timers firing, or inputs changing? \$\endgroup\$ – Marcus Müller Feb 17 '18 at 22:37
  • 1
    \$\begingroup\$ What speeds are you achieving, that you are not satisfied with? And where do you want to get to? And are you communicating between essentially asynchronously clocked MCUs? \$\endgroup\$ – jonk Feb 17 '18 at 22:48
  • \$\begingroup\$ @MarcusMüller Thank you for your comment. I added more info into the question. \$\endgroup\$ – zmechanic Feb 18 '18 at 11:12
  • 1
    \$\begingroup\$ @zmechanic You completely fail to understand why it is important, if you think this is about UART vs SPI -- though there is a relationship. My question is about pushing towards speed using bit-banging. Unfortunately, you still haven't answered my questions: existing speed, desired speed. So I can't tell you if what I'm thinking matters yet. \$\endgroup\$ – jonk Feb 18 '18 at 20:42
2
\$\begingroup\$

So, I'd actually recommend Cortex-M0 for the reasons that you cite against Atmega:

The Cortex-M0 microarchitecture is pretty smart when it comes to helping developers implement real-time OSes. For example, pushing registers is done for you (of course, limited to the relevant registers, and I'd guess that's where the latency comes from), and the hardware handles two different stack pointers, depending on whether you're in "application" or "handler" mode.
I'd like to refer you to the presentation Mr. Moritz Fischer held at FOSDEM 2018 about Multitasking on Cortex-M.

Bonus (but my guess would be the STM8 has something like that, too): Cortex-M0s typically come with capable DMA engines linked to their peripherals. If you, for example, need to bitbang a pin with a sequence of 128 hi/lo states, you can just let the peripheral do that. No need to interfere yourself, just write the data to the right position, and inform the device or dma controller what to do. The capabilities of course depend on the actual peripherals that the silicon manufacturer (ST, NXP, Atmel, Cypress…) attached to the ARM core.

There's several ready-to-use free RTOSes for Cortex-M. So, that might be a reason to use that – especially if you prefer C over assembler.

I've not tried these, but: The Cypress PSoC 4200 series comes with what they call "programmable universal digital blocks". These things are meant to be "independent" hardware state machines. Pretty much exactly what you need to implement wire protocols.

\$\endgroup\$
  • \$\begingroup\$ Thank you for your reply, Marcus. I'm not having issues with master, which does bit-banging, as I have to insert delays, so that slave can keep up with master. \$\endgroup\$ – zmechanic Feb 18 '18 at 11:16
  • \$\begingroup\$ I don't think that any kind of RTOS is necessary, as what I'm dealing with is a protocol controller, with absolutely deterministic logic. Also, suitable MCU with large ROM/RAM needed to run RTOS will be an overkill and cost over permitted for the BOM. \$\endgroup\$ – zmechanic Feb 18 '18 at 20:42
  • \$\begingroup\$ You have a wrong picture of what an RTOS I have in mind: it's not a fully fledged monster of an OS, but only as much as necessary as to orchestrate tasks and interrupts. Because it doesn't matter resource-wise whether you do that or someone with OS design experience does it. (Rtoses for cortex-m literally take a couple dozen bytes of RAM, typically. You don't care about that, and it's certainly not much more than the minimum amount that you could squeeze out with full knowledge of your application) \$\endgroup\$ – Marcus Müller Feb 18 '18 at 23:08
  • \$\begingroup\$ I used FreeRTOS in the past on PIC32, and it works marvels with asynchronously running tasks. In my case I have only 2 tasks. One is driven by ISR that receives a bit, the other one which processes a byte. Processing code also need to reply to master when it receives 8 bit (I'm running 10-bit-per-byte protocol). I clearly don't see how I would benefit from RTOS in this case, especially because MCU is just a protocol converter, as it calls another MCU via USART when it received useful packet of data. What I need is an MCU with fast response to ISR with minimal prologue/epilogue. \$\endgroup\$ – zmechanic Feb 18 '18 at 23:41
  • \$\begingroup\$ I found today that a minimal for AVR is 5T to enter ISR + 3T for jump to ISR implementation + 5T to exit ISR. This gives me at least 13T, which is really good, AVR backs up and restores 12 registers, which adds another 24T (12+12). Plus some more code to identify was it CLK or DATA toggling, as they sit on the same port. \$\endgroup\$ – zmechanic Feb 18 '18 at 23:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.