2020-06-06 10:58 AM
Using this board from ebay with the STM32H750VB mcu and I have USART1 configured, and it 'functions' but the data I send from the pc is not what the board is getting. I had to download several serial clients until I found one that would read parity as 'space' and that made it work correctly but I have no parity configured on the board, and Im stumped as to why its not getting what I am sending.
If I send the letter 'A' (ascii 65) the board gets decimal 160. The MSB seems to be set sometime when it shouldn't be, and I cannot figure out whats causing it. Ive spent close to 50 hours trying to figure this out. Anyone have any ideas?
I got some basic pinout and description info from a post @Community member made a few months ago, and I thought it was working correctly but then noticed this data problem. I've used cubemx to generate all code, I've hand written it based on reg values from the reference manual, and I have tried several examples from various places on the web.
__GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = GPIO_PIN_9;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Alternate = GPIO_AF7_USART1;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_10;
GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
__USART1_CLK_ENABLE();
//Most of these registers are already at zero when reset. but im getting desperate.
//set word length. 2 bits
USART1->CR1 &= ~(USART_CR1_M0); //00 = 1s,8d,Ns
USART1->CR1 &= ~(USART_CR1_M1); //01 = 1s,9d,Ns
//10 = 1s,7d,Ns
//set stop bits
USART1->CR2 &= ~(USART_CR2_STOP_0 | USART_CR2_STOP_1); //00=1 stop bit
//01=.5 stop bit
//10=2 stop bit
//11=1.5 stop bit
//set parity
USART1->CR1 &= ~(USART_CR1_PCE); //0=parity control disabled
//1=parity control enabled
//set msb/lsb
USART1->CR2 &= ~(USART_CR2_MSBFIRST); //0=0 bit first
//1=7/8 bit first
//set flow hw control
USART1->CR3 &= ~(USART_CR3_RTSE | USART_CR3_CTSE); //0=turn of ready to send and clear to send
//set tx/rx enable
USART1->CR1 |= (USART_CR1_RE | USART_CR1_TE); //enable transmit and receive
//set over sampling
USART1->CR1 &= ~(USART_CR1_OVER8); //0=over sample by 16
//1=over sample by 8
//set interrupts
USART1->CR1 |= (USART_CR1_RXNEIE_RXFNEIE); //enable interrupts
//set FIFO
USART1->CR1 &= ~(USART_CR1_FIFOEN);
uint32_t Baud = 9600;
//set baud rate
//((clkspeed/prescaler) + (baudrate/2))/baudrate
USART1->BRR = ((HAL_RCC_GetPCLK2Freq() / 1) + (Baud / 2U)) / Baud;
USART1->CR1 |= (USART_CR1_UE);
/* Peripheral interrupt init*/
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
2020-06-06 10:59 AM
...
2020-06-06 05:21 PM
The fact that you're getting characters, but not the right ones, suggests the clock is the issue.
Can you verify your clock is correct with a logic analyzer? If not, post your clock initialization. Specifically if you're using HSI, make sure the calibration and trim values are set correctly, as these can throw off the clock by more than the allowed UART tolerance.
2020-06-06 05:36 PM
Clock is configured by CubeMX currently. I replaced all the manual clock configuration I had implemented. Its not garbage data exactly, its as if I cannot get rid of the parity bit no matter what I try. If I set data bits to 7 instead of 8 with the below, it does work, but I have to set the client to 7 data bits as well and I do not understand why. Is there ALWAYS a parity bit no matter what? and can you not drop it off with &0x1FF or 0xFF on the RDR?
//set word length. 2 bits
USART1->CR1 &= ~(USART_CR1_M0);//00 = 1s,8d,Ns
USART1->CR1 |= (USART_CR1_M1); //01 = 1s,9d,Ns
//10 = 1s,7d,Ns
Current RCC:
RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = { 0 };
/** Supply configuration update enable
*/
HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 32;
RCC_OscInitStruct.PLL.PLLN = 129;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
//Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2
| RCC_CLOCKTYPE_D3PCLK1 | RCC_CLOCKTYPE_D1PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV1;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
//Error_Handler();
}
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART1
| RCC_PERIPHCLK_SPI1 | RCC_PERIPHCLK_SDMMC;
PeriphClkInitStruct.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL;
PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
Current ISR:
void USART1_IRQHandler()
{
uint32_t IIR = HOST_USART->ISR; //<--flag clears when we read the ISR
if ((IIR & USART_FLAG_RXNE)!=0) //<-- check to see if this is an RXNE (read data register not empty
{
uint8_t byte = (uint8_t)(HOST_USART->RDR & 0x1FF); //<-- 0xFF doesnt work either
Hardware_Abstraction_Layer::Serial::host_ring_buffer->put(byte);
Hardware_Abstraction_Layer::Serial::send(0, &byte); //<--echo back what we got
}
}
2020-06-06 06:00 PM
> Is there ALWAYS a parity bit no matter what? and can you not drop it off with &0x1FF or 0xFF on the RDR?
You can set no parity by clearing the USART_CR1_PCE bit. Why do you think yours keeps adding a parity bit? Have you actually looked at a scope trace and seen it? Note that "space" parity isn't really common, as it doesn't actually provide a parity check.
> RCC_HSICALIBRATION_DEFAULT
See what this is getting evaluated to and ensure it's right for the chip revision you have. CubeMX got it wrong for a while, not sure the current status.
#if defined(RCC_HSICFGR_HSITRIM_6)
#define RCC_HSICALIBRATION_DEFAULT (0x40U) /* Default HSI calibration trimming value, for STM32H7 rev.V and above */
#else
#define RCC_HSICALIBRATION_DEFAULT (0x20U) /* Default HSI calibration trimming value, for STM32H7 rev.Y */
#endif
2020-06-06 06:04 PM
Space parity isn't even an option on the STM32H7. Unlikely that's what the processor is doing.
2020-06-06 07:34 PM
RCC_HSICALIBRATION_DEFAULT is evaluating to 0x40, and I think the chip is a Y revision. I'll change it and see if there is any effect.
Parity has been configured off for the USART.
No the chip doesnt support space parity, Im just stating that with a client setting of space parity I can get data to the board and it is correct. Data from the board however is then jumbled. I can also set the data bits to 7 instead of 8 in the USART config and the data to and from the board is correct. However I cannot specify 7 data bits to communicate with the board because the same software communicates with other processors at 8 data bits.
Here is a comparison of some of the values:
10100101 <--sent from client
110100101<-- mcu byte read is
10011110 <--sent from client
110011110<-- mcu byte read is
10100101 <--sent from client
110100101<-- mcu byte read is
RDR is 9 bits wide, so I can mask off the far left bit with 0xFF. But when I send a value that is smaller say 0x10 this is what is read from RDR
00010000<--from client
10010000<-- mcu byte read is
Masking it off with 0XFF still picks up the far left byte, and its broken again.
The only thing left I can think of is that something else is connected to USART1 and I dont know what it is.
I'll change the trim value and see what it does.
2020-06-06 07:58 PM
Well I think this has resolved it!
#if defined(RCC_HSICFGR_HSITRIM_6)
#define RCC_HSICALIBRATION_DEFAULT (0x20U) /* Default HSI calibration trimming value, for STM32H7 rev.V and above */
#else
#define RCC_HSICALIBRATION_DEFAULT (0x20U) /* Default HSI calibration trimming value, for STM32H7 rev.Y */
#endif
I changed it from 40 to 20 back and forth a few times. At 40 I get garbage, at 20 it is correct!
So question now, what is the proper way to configure that? If I undefine RCCHSICFGR_HSITRIM_6 its could probably have effects on other things. Should I just leave the value changed in the define?
And I am presuming this value is specific to the Y chip, because Y is higher than V, but there are 2 values and Im assuming its a specific to Y revision value.