I ran into some issues configuring my stm32f429-DISCO board for a UART transmission on UART5.
I used the example project provided by st. To be exact, the UART/UART_TwoBoards_ComDMA in version 1.7.0.
In this example the USART1 is used to circle one data package around.
When the DISCO-board is programmed with the original code, I can see the USART1 output message on my oscilloscope.
On the other hand, when I try the same thing with the UART5, because the pins for USART1 will be blocked in my final configuration it won't work.
I narrowed the problem down to the initialization process.
HAL_UART_MspInit(huart);
This function is not setting the TC and RXNE bit in UART1->SR, and therefore the UART5 is not configured.
I know for UART1 you need to enable the clock, because it can be a synchronous transmission.
__HAL_RCC_USART1_CLK_ENABLE();
I can't seem to find a similar function for UART5. Has somebody an idea or a hint for me?
In case a bigger problem is underlying this issue, here are the changed settings for the UART5 configuration of the example.
/* Definition for USARTx clock resources */
#define USARTx UART5
//#define USARTx_CLK_ENABLE() __HAL_RCC_USART1_CLK_ENABLE();
#define DMAx_CLK_ENABLE() __HAL_RCC_DMA1_CLK_ENABLE()
#define USARTx_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()
#define USARTx_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
//#define USARTx_FORCE_RESET() __HAL_RCC_USART1_FORCE_RESET()
//#define USARTx_RELEASE_RESET() __HAL_RCC_USART1_RELEASE_RESET()
/* Definition for USARTx Pins */
#define USARTx_TX_PIN GPIO_PIN_12
#define USARTx_TX_GPIO_PORT GPIOC
#define USARTx_TX_AF GPIO_AF8_UART5
#define USARTx_RX_PIN GPIO_PIN_2
#define USARTx_RX_GPIO_PORT GPIOD
#define USARTx_RX_AF GPIO_AF8_UART5
/* Definition for USARTx's DMA */
#define USARTx_TX_DMA_CHANNEL DMA_CHANNEL_4
#define USARTx_TX_DMA_STREAM DMA1_Stream7
#define USARTx_RX_DMA_CHANNEL DMA_CHANNEL_4
#define USARTx_RX_DMA_STREAM DMA1_Stream0
/* Definition for USARTx's NVIC */
#define USARTx_DMA_TX_IRQn DMA1_Stream7_IRQn
#define USARTx_DMA_RX_IRQn DMA1_Stream0_IRQn
#define USARTx_DMA_TX_IRQHandler DMA1_Stream7_IRQHandler
#define USARTx_DMA_RX_IRQHandler DMA1_Stream0_IRQHandler
#define USARTx_IRQn UART5_IRQn
#define USARTx_IRQHandler UART5_IRQHandler
I'm happy for any suggestion and help that guides me in the right direction.
Thank you for your time,
eimer
UART5 has no S, so the function to enable the clock is called
__HAL_RCC_UART5_CLK_ENABLE();, like e.g. there: Receiving data from 2 UARTs, STM32F4-Discovery, HAL drivers
Related
I use a STM32 connected with SPI to a MCP23S17 16 bit I/O port expander.
I want to make all 16 I/0 pins as output and just making them all LOW or HIGH.
I used an oscilloscope to check is SPI transmit the signals right, and it does.
The only thing is that on the I/O pins I get around 0.4V. Not 5V.
Sometimes I get a value of 1.4V but it goes away, weird thing...
Can somebody check my code and tell me where is my mistake? I am pretty sure I did the code wrong somewhere.
MCP23S17.h:
#ifndef INC_MCP23S17_H_
#define INC_MCP23S17_H_
#include "stm32f1xx_hal_conf.h"
extern SPI_HandleTypeDef hspi2;
void MCP23S17_SPI_Write(uint8_t reg_addr, uint8_t data);
uint8_t MCP23S17_SPI_Read(uint8_t data);
#define CS_HIGH() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
#define CS_LOW() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
#define MCP23S17_AAA ((uint8_t)0x0E)
#define MCP23S17_ADDRESS ((uint8_t)0x40)
#define MCP23S17_W ((uint8_t)0x00)
#define MCP23S17_R ((uint8_t)0x01)
#define MCP23S17_IODIRA ((uint8_t)0x00)
#define MCP23S17_IPOLA ((uint8_t)0x02)
#define MCP23S17_GPINTENA ((uint8_t)0x04)
#define MCP23S17_DEFVALA ((uint8_t)0x06)
#define MCP23S17_INTCONA ((uint8_t)0x08)
#define MCP23S17_IOCONA ((uint8_t)0x0A)
#define MCP23S17_GPPUA ((uint8_t)0x0C)
#define MCP23S17_INTFA ((uint8_t)0x0E)
#define MCP23S17_INTCAPA ((uint8_t)0x10)
#define MCP23S17_GPIOA ((uint8_t)0x12)
#define MCP23S17_OLATA ((uint8_t)0x14)
#define MCP23S17_IODIRB ((uint8_t)0x01)
#define MCP23S17_IPOLB ((uint8_t)0x03)
#define MCP23S17_GPINTENB ((uint8_t)0x05)
#define MCP23S17_DEFVALB ((uint8_t)0x07)
#define MCP23S17_INTCONB ((uint8_t)0x09)
//#define MCP23S17_IOCONB ((uint8_t)0x0B)
#define MCP23S17_GPPUB ((uint8_t)0x0D)
#define MCP23S17_INTFB ((uint8_t)0x0F)
#define MCP23S17_INTCAPB ((uint8_t)0x11)
#define MCP23S17_GPIOB ((uint8_t)0x13)
#define MCP23S17_OLATB ((uint8_t)0x15)
//#define MCP23S17_INT_ERR ((uint8_t)255)
//#define BANK ((uint8_t)0x80) //bit 7 of IOCON
//#define MIRROR ((uint8_t)0x40) //bit 6 of IOCON
//#define SEQOP ((uint8_t)0x20) //bit 5 of IOCON
//#define DISSLW ((uint8_t)0x10) //bit 4 of IOCON
//#define HAEN ((uint8_t)0x08) //bit 3 of IOCON
//#define ODR ((uint8_t)0x04) //bit 2 of IOCON
//#define INTPOL ((uint8_t)0x02) //bit 1 of IOCON
//#define unused ((uint8_t)0x00) //bit 0 of IOCON
//-----------------------
#define MCP23S17_MODERA_W(x) MCP23S17_SPI_Write(MCP23S17_IODIRA, ((uint8_t)x))
#define MCP23S17_MODERA_R() MCP23S17_SPI_Read(MCP23S17_IODIRA)
#define MCP23S17_IPOLA_W(x) MCP23S17_SPI_Write(MCP23S17_IPOLA, ((uint8_t)x))
#define MCP23S17_ODRA_W(x) MCP23S17_SPI_Write(MCP23S17_OLATA, ((uint8_t)x))
#define MCP23S17_ODRA_R() MCP23S17_SPI_Read(MCP23S17_OLATA)
#define MCP23S17_IDRA_R() MCP23S17_SPI_Read(MCP23S17_GPIOA) // Reflect the value of the port A
#define MCP23S17_PUDA_W(x) MCP23S17_SPI_Write(MCP23S17_GPPUA, ((uint8_t)x))
#define MCP23S17_PUDA_R() MCP23S17_SPI_Read(MCP23S17_GPPUA)
#define MCP23S17_SETUP_W(x) MCP23S17_SPI_Write(MCP23S17_IOCONA, ((uint8_t)x))
#define MCP23S17_SETUP_R() MCP23S17_SPI_Read(MCP23S17_IOCONA))
#define MCP23S17_MODERB_W(x) MCP23S17_SPI_Write(MCP23S17_IODIRB, ((uint8_t)x))
#define MCP23S17_MODERB_R() MCP23S17_SPI_Read(MCP23S17_IODIRB)
#define MCP23S17_IPOLB_W(x) MCP23S17_SPI_Write(MCP23S17_IPOLB, ((uint8_t)x))
#define MCP23S17_ODRB_W(x) MCP23S17_SPI_Write(MCP23S17_OLATB, ((uint8_t)x))
#define MCP23S17_ODRB_R() MCP23S17_SPI_Read(MCP23S17_OLATB)
#define MCP23S17_IDRB_R() MCP23S17_SPI_Read(MCP23S17_GPIOB) // Reflect the value of the port B
#define MCP23S17_PUDB_W(x) MCP23S17_SPI_Write(MCP23S17_GPPUB, ((uint8_t)x))
#define MCP23S17_PUDB_R() MCP23S17_SPI_Read(MCP23S17_GPPUB)
//-----------------------
void GPIO_Write_Pins(uint16_t);
void GPIO_Expander_Init();
void MCP23S17_SPI_Write(uint8_t reg_addr, uint8_t data);
#endif /* INC_MCP23S17_H_ */
MCP23S17.c
#include "main.h"
#include "MCP23S17.h"
void MCP23S17_SPI_Write(uint8_t reg_addr, uint8_t data)
{
uint8_t pBuff[3];
pBuff[0] = MCP23S17_ADDRESS|MCP23S17_AAA|MCP23S17_W; //optocode that contain 0100 + 111 + 0 (read command)
pBuff[1] = reg_addr; // register address
pBuff[2] = data; // the value that is modified on the register, check datasheet
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
HAL_SPI_Transmit_IT(&hspi2, pBuff, 3); //transmit on the spi2 the optocode, register adress and the value for the register
for(uint32_t i = 0; i < 85; i++) //delay
{}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
}
void GPIO_Expander_Init()
{
MCP23S17_SETUP_W(0x00);
MCP23S17_MODERA_W(0x00);
MCP23S17_MODERB_W(0x00);
MCP23S17_PUDA_W(0x00);
MCP23S17_PUDB_W(0x00);
//MCP23S17_IPOLA_W(0x00);
//MCP23S17_IPOLB_W(0x00);
}
void GPIO_Write_Pins(uint16_t dataspi)
{
//16 to 8 and 8
uint8_t data_half[2];
data_half[0]=*((uint8_t*)&(dataspi)+1); //split the first half of the data
data_half[1]=*((uint8_t*)&(dataspi)+0); //split the second half of the data
MCP23S17_ODRA_W(data_half[0]); //first half
MCP23S17_ODRB_W(data_half[1]); //second half
}
and in main.c
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
GPIO_Expander_Init();
GPIO_Write_Pins(0xFFFF);
while(1)
{
}
The only thing is that on the I/O pins I get around 0.4V
This is likely because GPIOs are not initialized.
You also have a different problem to deal with.
for(uint32_t i = 0; i < 85; i++) //delay
{}
This loop is very likely to be optimize away by the compiler. This is because, it doesn't do anything.
There are more sophisticated ways of generating delays in a microcontroller. The best possible solution would be to use a timer module.
So coming back with the solution, the code was good, 2 first gpio expanders that I tried were purely burned. For a much shorter working code just comment here asking for it. Thank everyone for advices cause I took them in consideration in the final form of code.
My machine has CRTSCTS #defined inside a #ifdef __USE_MISC which stops it being available to C programs which I compile.
/usr/include/x86_64-linux-gnu/bits/termios.h:
...
#define B4000000 0010017
#define __MAX_BAUD B4000000
#ifdef __USE_MISC
# define CIBAUD 002003600000 /* input baud rate (not used) */
# define CMSPAR 010000000000 /* mark or space (stick) parity */
# define CRTSCTS 020000000000 /* flow control */
#endif
/* c_lflag bits */
#define ISIG 0000001
#define ICANON 0000002
...
How do I get access to CRTSCTS without just hacking the value 020000000000 into my program?
I already #include <termios.h> and many other headers.
I am also using:
#define __USE_POSIX199309
#define _POSIX_C_SOURCE 199309L
#include <time.h> /* nanosleep needs lines above */
The __USE_MISC macro is an internal definition that, though I suppose you could define this yourself, it's better to find the proper feature-test macro that enables it.
On my CentOS 7 system, /usr/include/features.h has a whole range of these kinds of macros, and it appears that __USE_MISC is enabled by _BSD_SOURCE or _SVID_SOURCE; it's not clear which one is compatible with other things you're going to need.
... // features.h
#if defined _BSD_SOURCE || defined _SVID_SOURCE
# define __USE_MISC 1
#endif
Try #define _BSD_SOURCE at the top of your program - before all the includes - and see how it goes.
Ref: http://man7.org/linux/man-pages/man7/feature_test_macros.7.html
I'm on GCC112, which is a little-endian Power8 machine running Linux. Power8 has in-core crypto providing AES, SHA and a few other useful features. I'm trying to determine the availability of the features at runtime using getauxval. The use case is distros building for a "minimum" capable machine, and we need to swap-in a faster function at runtime.
The dump of hwcaps.h is shown below, but it lacks specific bits for Power8, AES, SHA and others. However, I believe Power8 is ISA 2.07, and ISA 2.07 has the bit PPC_FEATURE2_ARCH_2_07.
The thing I am not clear on is, is Power8 in-core crypto optional like ARM's crypto under ARMv8. I can't find a document that clearly states the requirement, and I don't have a membership to OpenPower to access ISA documents. (Another possibility is, it is stated but I missed it in the docs).
Is it possible to use getauxval to query the runtime environment for the features? If not, then how do we determine feature availability at runtime? Is CPU probing the only alternative available?
Maybe more generally, how do we determine Power6, Power7 and Power8 runtime environments?
auxv.h is mostly empty. The header file includes hwcaps.h.
$ cat /usr/include/bits/hwcap.h
...
/* The bit numbers must match those in the kernel's asm/cputable.h. */
/* Feature definitions in AT_HWCAP. */
#define PPC_FEATURE_32 0x80000000 /* 32-bit mode. */
#define PPC_FEATURE_64 0x40000000 /* 64-bit mode. */
#define PPC_FEATURE_601_INSTR 0x20000000 /* 601 chip, Old POWER ISA. */
#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 /* SIMD/Vector Unit. */
#define PPC_FEATURE_HAS_FPU 0x08000000 /* Floating Point Unit. */
#define PPC_FEATURE_HAS_MMU 0x04000000 /* Memory Management Unit. */
#define PPC_FEATURE_HAS_4xxMAC 0x02000000 /* 4xx Multiply Accumulator. */
#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 /* Unified I/D cache. */
#define PPC_FEATURE_HAS_SPE 0x00800000 /* Signal Processing ext. */
#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 /* SPE Float. */
#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 /* SPE Double. */
#define PPC_FEATURE_NO_TB 0x00100000 /* 601/403gx have no timebase */
#define PPC_FEATURE_POWER4 0x00080000 /* POWER4 ISA 2.00 */
#define PPC_FEATURE_POWER5 0x00040000 /* POWER5 ISA 2.02 */
#define PPC_FEATURE_POWER5_PLUS 0x00020000 /* POWER5+ ISA 2.03 */
#define PPC_FEATURE_CELL_BE 0x00010000 /* CELL Broadband Engine */
#define PPC_FEATURE_BOOKE 0x00008000 /* ISA Category Embedded */
#define PPC_FEATURE_SMT 0x00004000 /* Simultaneous
Multi-Threading */
#define PPC_FEATURE_ICACHE_SNOOP 0x00002000
#define PPC_FEATURE_ARCH_2_05 0x00001000 /* ISA 2.05 */
#define PPC_FEATURE_PA6T 0x00000800 /* PA Semi 6T Core */
#define PPC_FEATURE_HAS_DFP 0x00000400 /* Decimal FP Unit */
#define PPC_FEATURE_POWER6_EXT 0x00000200 /* P6 + mffgpr/mftgpr */
#define PPC_FEATURE_ARCH_2_06 0x00000100 /* ISA 2.06 */
#define PPC_FEATURE_HAS_VSX 0x00000080 /* P7 Vector Extension. */
#define PPC_FEATURE_PSERIES_PERFMON_COMPAT 0x00000040
#define PPC_FEATURE_TRUE_LE 0x00000002
#define PPC_FEATURE_PPC_LE 0x00000001
/* Feature definitions in AT_HWCAP2. */
#define PPC_FEATURE2_ARCH_2_07 0x80000000 /* ISA 2.07 */
#define PPC_FEATURE2_HAS_HTM 0x40000000 /* Hardware Transactional
Memory */
#define PPC_FEATURE2_HAS_DSCR 0x20000000 /* Data Stream Control
Register */
#define PPC_FEATURE2_HAS_EBB 0x10000000 /* Event Base Branching */
#define PPC_FEATURE2_HAS_ISEL 0x08000000 /* Integer Select */
#define PPC_FEATURE2_HAS_TAR 0x04000000 /* Target Address Register */
I'd say that getauxval() would be the best way to do this; the HWCAP & HWCAP2 values are exactly for determining hardware features. Missing from your list is the PPC_FEATURE2_VEC_CRYPTO, which indicates the presence of the vector crypto instructions, which sounds like the one you need.
As a side note: you probably don't want to detect processor implementations, but processor features. Specifically, check for the individual feature, rather than trying to check for a process that provides that feature. (eg., detect VEC_CRYPTO directly, rather than trying to check for POWER8, and assume that that implies crypto functionality).
As a bit of detail, Linux's cputable entries specify the HWCAP/HWCAP2 values. Using POWER8 as an example:
#define COMMON_USER2_POWER8 (PPC_FEATURE2_ARCH_2_07 | \
PPC_FEATURE2_HTM_COMP | \
PPC_FEATURE2_HTM_NOSC_COMP | \
PPC_FEATURE2_DSCR | \
PPC_FEATURE2_ISEL | PPC_FEATURE2_TAR | \
PPC_FEATURE2_VEC_CRYPTO)
That's from arch/powerpc/include/asm/cputable.h in the kernel (which also provides the actual hwcap bits that can be set in the aux vector).
Finally, I'm fairly sure you don't need to be an OpenPOWER foundation member to download the ISA (latest is 3.0B) - you just need an account on the website.
I want to be able to define a tuple which represents the arguments needed by other macros.
I think the best way to show what I want is to show an example:
#include <avr/io.h>
#define LED_PORT PORTB
#define LED_DDR DDRB
#define LED_PIN PB7
#define LED LED_PORT, LED_DDR, LED_PIN
#define OUTPUT(port, ddr, pin) ddr |= 1 << pin
void main(void) {
OUTPUT(LED);
}
I want OUTPUT(LED) to be then expanded into:
LED_DDR |= 1 << LED_PIN
The problem that I get is to do with the order of expansion, and results in the following error:
macro "OUTPUT" requires 3 arguments, but only 1 given
This is for use with an AVR project with custom built hardware where I have defined LED and other components with a respective LED_PORT LED_DDR and LED_PIN.
I then want to define more macros that can take this LED and use the appropriate arguments to map to the most succinct way possible.
Is this possible with the standard C-preprocessor?
You can add a level of indirection to the macro to achieve this:
#define OUTPUT_I(port, ddr, pin) ddr |= 1 << pin
#define OUTPUT(spec) OUTPUT_I(spec)
During rescanning, spec is expanded before OUTPUT_I, so the OUTPUT_I macro sees three parameters.
I want to be able to define a tuple which represents the arguments needed by other macros.
I think the best way to show what I want is to show an example:
#include <avr/io.h>
#define LED_PORT PORTB
#define LED_DDR DDRB
#define LED_PIN PB7
#define LED LED_PORT, LED_DDR, LED_PIN
#define OUTPUT(port, ddr, pin) ddr |= 1 << pin
void main(void) {
OUTPUT(LED);
}
I want OUTPUT(LED) to be then expanded into:
LED_DDR |= 1 << LED_PIN
The problem that I get is to do with the order of expansion, and results in the following error:
macro "OUTPUT" requires 3 arguments, but only 1 given
This is for use with an AVR project with custom built hardware where I have defined LED and other components with a respective LED_PORT LED_DDR and LED_PIN.
I then want to define more macros that can take this LED and use the appropriate arguments to map to the most succinct way possible.
Is this possible with the standard C-preprocessor?
You can add a level of indirection to the macro to achieve this:
#define OUTPUT_I(port, ddr, pin) ddr |= 1 << pin
#define OUTPUT(spec) OUTPUT_I(spec)
During rescanning, spec is expanded before OUTPUT_I, so the OUTPUT_I macro sees three parameters.