cancel
Showing results for 
Search instead for 
Did you mean: 

SmartCard UART HAL Library problem/work-around

childresss
Associate II
Posted on February 04, 2015 at 20:17

1. SmartCard USART mode, getting an interrupt for, receiver overrun error (ORE) while transmitting. ORE interrupt before TC interrupt.   Causes truncated transmission.

Using  

HAL_SMARTCARD_Transmit_IT(

)

The SmartCard UART library code in file stm32f4xx_hal_smartcard.c, line 644 is

    /* Enable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */

   __HAL_SMARTCARD_ENABLE_IT(hsc, SMARTCARD_IT_ERR);

The above enables irrelevant error interrupts in transmit of half duplex mode. The only valid RX interrupt in this case is parity error, where per ISO7816, the receiving device can pull TX/RX low after a stop bit to signal last-byte-in-error. But receiver overrun makes no sense as in half duplex, we are not receiving, and there are (correctly) no RXNE interrupts.

If I change the line of code above to disable rather than enable, the incorrect overrun error interrupts cease.

Q: What is the solution? Could this be a UART errata item?

Development Hardware: STM32F407 on Discovery board, USART2 in SmartCard mode as established by CubeMX, for ISO SmartCard: 9 bits including 1 even parity.

Q: Will move to STM32F415 for product. Does this have exactly the same USART for SmartCard (HDX) mode?

Tools: CubeMX feeding to IAR, ST-Link debugging. Using HAL code unmodifed, latest.

------------------

2. The transmit complete (TC) interrupt occurs two bytes too early in smartcard mode. Example: One call to

HAL_SMARTCARD_Transmit_IT

()

for 20 bytes will interrupt with TC status after 20 bytes have been sent to the UART but bytes 19 and  20 have not yet been transmitted. I believe that #19 is in the serial shift register and #20 is in the TDR. I see no status bit to say that the last stop bit of the 20th byte has been sent. Therefore, the software does not know when the half-duplex line can be turned-around to RX mode. Other than a brute force time delay from TC for 12 baud clock times (start bit, 9 data bits including parity, 1.5 stop bits per char per ISO7816).

How is this normally handled? Or is this a USART2  problem in the STM32F407 on the Discovery boards? (My eventual target is an STM32F415).

(The guard timer is inter-character times, not post-TC time, so it's not applicable).

Thanks in advance

steve
11 REPLIES 11
Posted on February 04, 2015 at 20:56

Hi Steve,

> receiver overrun makes no sense as in half duplex, we are not receiving, and there are (correctly) no RXNE interrupts.

The interrupt enabled by CR3.EIE won't fire unless CR3.DMAR is set - see EIE description and also Figure 320 in RM0090 Rev.8. And, you would not set DMAR unless you want receive using DMA. Ergo, once setting EIE, you *are* bound to receive, aren't you.

I am not going to attempt to penetrate the ''logic'' of  Cube.

> Q: What is the solution?

Get rid of Cube. Own your software.

> Will move to STM32F415 for product. Does this have exactly the same USART for SmartCard (HDX) mode?

Every indications are that the only difference between STM32F405/STM32F407/STM32F415/STM32F417 are the CRYPT/HASH/ETH modules, so the answer is yes.

> 2. The transmit complete (TC) interrupt occurs two bytes too early in smartcard mode.

Are you sure it *is* a TC interrupt? Can't it be a TXE interrupt, or a DMA TC interrupt?

Jan

childresss
Associate II
Posted on February 04, 2015 at 23:43

Thanks for the response!

I know Cube is a crutch, but it really speeds coming up to speed on a new ARM vendor's system. With Cube, it took a half day to get a running '415 dev board and linker file and IAR chain w/ST-Link running.

 I remember that it took days/weeks to get the board, IAR and J-Link all working on my first ARM, an NXP ARM7.

The other reason for Cube as of now is that I have multiple projects going and each project starts on one STM32F4 and moves later to another. And Cube helps quickly get the pin mapping set for a complex design with lots of external devices. Then that pin map has to drive the PC board design. All this before writing any code.

If there's a better way to do this process, I'd like to learn it.

===

Back to the topic.. of why I get the UART receiver overrun errors. Using HAL Library ''_IT'', interrupt I/O. No use of DMA. So I don't know why the ORE error interrupts occur when in smartcard mode on USART2. Nor why the HAL library code as I noted in the OP enables irrelevant receiver interrupts. Perhaps just because that line of code was copied from the non-HDX UART driver.

An yes, the TC interrupt is before the last 2 bytes get sent. I have code that sets a GPIO bit connected to a 'scope. Set the bit before calling for 20 bytes to be sent. Clear the bit when I get the TX complete callback. Scope shows the TC interrupt/callback are after byte 20 is sent to the UART but before byte 19 and 20 have been transmitted. The Ref. Manual for the 4xx chip is fuzzy on what TC means. The smartcard HAL driver code, after  outputting all 20 bytes via individual TE interrupts, sends the last byte, disables TE and enables TC. The TC interrupt occurs and that GPIO bit on the 'scope changes, but the scope also shows two more bytes go out after the TC interrupt; those are the last 2 of 20.

Posted on February 05, 2015 at 00:09

> I know Cube is a crutch, but it really speeds coming up to speed on a new ARM vendor's system.

You might expect to lose the gained time when it comes to the details. Wait, it just came to them.... 😉

> The other reason for Cube as of now is that I have multiple projects going and each project starts on one STM32F4 and moves later to another.

> And Cube helps quickly get the pin mapping set for a complex design with lots of external devices.

>Then that pin map has to drive the PC board design. All this before writing any code.

This is a feature of CubeMX, the program. It has nothing to do with Cube, the library.

===

> Back to the topic..

> of why I get the UART receiver overrun errors.

Post the content of all UART registers at the moment when that ISR is entered.

> An yes, the TC interrupt is before the last 2 bytes get sent.

Post the content of all UART registers at the moment when that ISR is entered.

Jan

childresss
Associate II
Posted on February 05, 2015 at 00:29

0690X00000602zyQAA.jpg

Logic Analyzer screen grab.

Top: Half-duplex/smartCard UART TX/RX serial.

Next down: GPIO bit my code sets before calling transmit_IT, cleared in TXcomplete call-back.

Bottom: Analog signal corresponding to the UART TXRX data line.

Means: TC interrupt occurs when last 2 bytes loaded into UART but before the serial shift register and the TDR (last 2 bytes) have actually flowed on the serial line, and the 20th stop bit has finished.

you mean at the TC interrupt?

Posted on February 05, 2015 at 00:32

You have problem with two interrupts, so... at the entry of both.

JW

childresss
Associate II
Posted on February 05, 2015 at 01:05

At breakpoint in the TxCompleteCallback. USART2 registers

0x40004400: f8 01 00 00 00 00 00 00 90 0d 00 00 0c 35 00 00

0x40004410: 00 38 00 00 20 00 00 00 0a 00 00 00 00 00 00 00

now, to dig about and decode this.

Posted on February 05, 2015 at 14:20

I meant, at the ISR entry, not after Cube had modified most of the registers. Also, IAR is expensive enough to have facilities to serve the content of peripheral registers on a silver plate.

Look, there may be silicon issues, but as long as you stick to Cube, it's hard to distinguish from Cube's errors, or usage errors. I am not going to dig to Cube, so I am out.

Btw., a new errata, rev.6 is out there. At least two issues relate to smartcard, although none will IMO cause abovementioned symptoms; but you might be interested in reading them before proceeding.

JW

Posted on February 05, 2015 at 21:56

So I did not listen to myself and dug into Cube and IMO I found a bug. I am not going to test the fix, though; it's up to you.

In [STM32Cube_FW_F4_V1.4.0]\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_smartcard.c in HAL_SMARTCARD_IRQHandler() (which is apparently the ISR in question), first, USARTx_SR is read into tmp1, then, in an ugly copypasted spaghetti of code, for the various interrupt sources, the interrupt enable flag is read into tmp2 using __HAL_SMARTCARD_GET_IT_SOURCE() (yes, the name is deceiving, it does not get the ''interrupt occured'' *flag*, but the interrupt *enable flag*). Then, for all other sources, tmp1 is masked for the expected flag and compared to zero called RESET in the ''libraries'', while tmp2 is directly compared to zero. But, for TC, both tmp1 (without masking) and tmp2 is compared to zero. Thus, as soon as TC is enabled, the first flag which goes high (TXE, for example) causes SMARTCARD_EndTransmit_IT() to be called, which in turn calls HAL_SMARTCARD_TxCpltCallback(), which is the callback you are probably overriding with your code.

(I looked into the UART and IRDA handlers, they do things differently - they read and mask the _SR bits as well as the enable bits explicitly before each check for the individual sources. Uglier.)

So the fix is, add the proper masking of tmp1 for checking of TC by the end of HAL_SMARTCARD_IRQHandler()

Enjoy.

JW

childresss
Associate II
Posted on February 06, 2015 at 01:44

You are correct!!

I looked at that code for a long time and didn't see that coding mistake they made.

The 'scope shows the timing is correct now, after I put in your recommendation:

// was  if((tmp1 != RESET) && (tmp2 != RESET))

  if (((tmp1 & SMARTCARD_FLAG_TC) != RESET) && (tmp2 != RESET)) 

Yes, lots of the code is weird looking to me. Has that Bangalore look and all that goes with such.

I wish the interrupt handlers all had __weak attributes so I could write my own override.  Not at all how I'd structure things.

BUT, the pin mapping has changed so much, beyond my control because there are 3 different cooks in the code kitchen and each cook works for a different company. Very political. For example, I had a pin map based on the 100 pin '415 chip so we could use FSMC for parallel NAND flash. Political decree came out, must use 64 pin chip because another cook went to board etch before coordinating - so he rules.  Then in the 64 pin mapping, the other cooks silently set precedent and now I don't have the ports I need so I hack and kludge. There are but 5 or so unused pins now, no spare UARTs, etc.

This is why I have to use CubeMX because big changes to pin mapping are too frequent and the cooks don't agree on who ''owns'' the I/O code initialization, and I fear, one cook hasn't admitted that they don't use ST's HAL. A mess.

Well, such is life in this global world of virtual companies and projects.

=======================

I have two other bugs I've found and fixed. I wrote to the ST FAE a few days ago. No response yet.

Is there a mechanism to request ST to change/correct the HAL code?