This is, unfortunately, the problem with using manufacturer libraries. You never *really* know what they're doing, or failing to do, until you go through the code in detail to check it.
I abandoned the use of the HAL quite early on in my STM32 career, and never looked back. Keep the ST header files for their useful definitions of register names and values, but don't use the code at all. Just poke the hardware, it's not that hard - especially since you have to pass all the essential parameters to the HAL anyway.
IMHO the HAL doesn't offer useful abstraction or simplification, just obfuscation.
If you already have working UART2 code, you could possibly try:
- configure the UART using HAL
- immediately afterwards, reconfigure the UART using your own code
- check that it now works OK
- remove settings from your own code until you find the one which allowed the port to work. (There may, of course, be more than one).