2015-02-04 11:17 AM
1. SmartCard USART mode, getting an interrupt for, receiver overrun error (ORE) while transmitting. ORE interrupt before TC interrupt. Causes truncated transmission.
UsingHAL_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 toHAL_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 steve2015-02-04 11:56 AM
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? Jan2015-02-04 02:43 PM
2015-02-04 03:09 PM
> 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. Jan2015-02-04 03:29 PM
2015-02-04 03:32 PM
You have problem with two interrupts, so... at the entry of both.
JW2015-02-04 04:05 PM
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.2015-02-05 05:20 AM
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. JW2015-02-05 12:56 PM
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. JW2015-02-05 04:44 PM
// 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?