Here is the COM port opening part:
portHandle=CreateFileA(portName, GENERIC_READ|GENERIC_WRITE,0, NULL, OPEN_EXISTING, 0, NULL);
if (portHandle == INVALID_HANDLE_VALUE)
{
return -1;
}
COMMCONFIG Win_CommConfig;
COMMTIMEOUTS Win_CommTimeouts;
unsigned long confSize = sizeof(COMMCONFIG);
Win_CommConfig.dwSize = confSize;
GetCommConfig(portHandle, &Win_CommConfig, &confSize);
Win_CommConfig.dcb.Parity = 0;
Win_CommConfig.dcb.fRtsControl = RTS_CONTROL_DISABLE;
Win_CommConfig.dcb.fOutxCtsFlow = FALSE;
Win_CommConfig.dcb.fOutxDsrFlow = FALSE;
Win_CommConfig.dcb.fDtrControl = DTR_CONTROL_DISABLE;
Win_CommConfig.dcb.fDsrSensitivity = FALSE;
Win_CommConfig.dcb.fNull=FALSE;
Win_CommConfig.dcb.fTXContinueOnXoff = FALSE;
Win_CommConfig.dcb.fInX=FALSE;
Win_CommConfig.dcb.fOutX=FALSE;
Win_CommConfig.dcb.fBinary=TRUE;
Win_CommConfig.dcb.DCBlength = sizeof(DCB);
if (baudrate != -1)
{
Win_CommConfig.dcb.BaudRate = baudrate;
}
Win_CommConfig.dcb.ByteSize = 8;
Win_CommTimeouts.ReadIntervalTimeout = 50;
Win_CommTimeouts.ReadTotalTimeoutMultiplier = 0;
Win_CommTimeouts.ReadTotalTimeoutConstant = 110;
Win_CommTimeouts.WriteTotalTimeoutMultiplier = 0;
Win_CommTimeouts.WriteTotalTimeoutConstant = 110;
SetCommConfig(portHandle, &Win_CommConfig, sizeof(COMMCONFIG));
SetCommTimeouts(portHandle,&Win_CommTimeouts);
return 0;
It connects OK, I manage to issue some AT comamnds and read back OK\n> responses, even one of the upper level protocol (OBD2: the command is 0100\r) gets a proper answer. But when I attempt other commands such as scanning of supported pids (e.g 0000\n, 0101\n, 0202\n etc) the whole thing either echoes back whatever I write to it or just times out. Issuing the same sequence of commands from a hyperterminal works properly. These serial ports are virtual simulated ports should it matter - http://com0com.sourceforge.net/.
What am I missing ? Perhaps some reading / setting / resetting of someof the pins ? It has been a while since I last mingled with RS232... Thanks!
EDIT: just tried the scantool at https://www.scantool.net/downloads/diagnostic-software/ and it worked ok too.
e.g 0000\n, 0101\n, 0202\n
This was the issue. It should have been \r at the end, not \n. Hyperterminal worked because the key would insert a \r here on Windows. Probablysome validation of the input was done by the device connected and so it got to work even with the wrong terminator character fed in.
Related
I'm implementing serial communication with a device in a firmware wrote from another person.
The MCU is STM32F411VET and I've data loss in communication.
To try to understand the problem, I wrote a little firmware that manage only usart2 and with it I haven't data loss, infact in this case, the usart2 works very fine at 115200 and don't loss a single byte.
Then, I've compared the code of this test software with code of software I'm working on and they are identical.
So I checked if there is another part of code that can conflict with USART2 and I have not found anything.
I searched instruction that disable interrupts, but there is one not used in my case.
The loop time is less then one milliseconds then I think that this not a problem.
What else could I check?
I finished ideas 😞
The init code of USART2 is:
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_USART2_CLK_ENABLE();
GPIO_InitStruct.Pin = TX_Pin | RX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);{
HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Uart2_Ready = false;
}
The Rx callback is:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
RxBuffer[BufferIndex++] = c;
HAL_UART_Receive_IT(huart, (uint8_t *)&c, 1);
if (BufferIndex == BUFFER_LENGHT)
{
memcpy(&Rx_Packet, RxBuffer, BUFFER_LENGHT);
PacketReady = true;
BufferIndex = 0;
}
}
Many thanks for help.
Solved, I found a function with problems.
This is in my init.c:
server_data_t **data = (server_data_t**)get_env(argv, US_SERVER_DATA);
data[0] = (server_data_t*)calloc(1, sizeof(server_data_t));
kv_t *channels = &data[0]->channels;
kv_t *users = &data[0]->users;
kv_init(channels, "channels.dat", 10*1024, 0, 0, 0);
kv_init(users, "users.dat", 10*1024, 0, 0, 0);
These initializations were only for testing puproses:
channel_t *channel = (channel_t*)calloc(1, sizeof(channel_t));
channel->name = strdup("Test channel");
channel->id = 1;
kv_item channel_item;
channel_item.key = (char*)&channel->id;
channel_item.klen = sizeof(u32);
channel_item.val = (char*)channel;
channel_item.in_use = 0;
kv_add(channels, &channel_item);
channel_t *channel2 = (channel_t*)calloc(1, sizeof(channel_t));
channel2->name = strdup("Test channel2");
channel2->id = 2;
kv_item channel_item2;
channel_item2.key = (char*)&channel2->id;
channel_item2.klen = sizeof(u32);
channel_item2.val = (char*)channel2;
channel_item2.in_use = 0;
kv_add(channels, &channel_item2);
kv_do(channels, NULL, sizeof(u32), test_proc, 0);
The user defined process kv_do process:
static int test_proc(const kv_item *item, const void *ctx)
{
return 1;
}
Starting the server segfaults after the kv_do test process starts an infinite loop when trying to visit all items. It works fine with one item in the list, then it just visits the first item and quits. I can also visit the items one by one with the ID using kv_get.
I found an edge case where it worked with two items if my key was "Test Channel" key length was strlen("Test Channel") and then the next channel key was "Test Channel2" where key-length was as long as the first items key-length. Pretty confusing.
Is the mistake in the code (pointers and such) or how the process is supposed to work with the return value of 1?
I know that gwan sometimes have trouble with KVMs so if it could be that, I'm running Oracle VM VirtualBox v5.0.24 with Ubuntu.
Are the kv.c and persistence.c G-WAN examples working for you?
If any of them crashes, then you are probably using out-of-sync. G-WAN headers (gwan.h) with a recent ./gwan executable.
I am writing an I2C slave routine for PIC18F25K80 and I am stuck on a weird problem.
This is my routine:
void interrupt interruption_handler() {
PIE1bits.SSPIE = 0; // Disable Master Synchronous Serial Port Interrupt
if (PIR1bits.SSPIF != 1) {
//This is not I2C interruption;
PIE1bits.SSPIE = 1; // Enable Master Synchronous Serial Port Interrupt
return;
}
//Treat overflow
if ((SSPCON1bits.SSPOV) || (SSPCON1bits.WCOL)) {
dummy = SSPBUF; // Read the previous value to clear the buffer
SSPCON1bits.SSPOV = 0; // Clear the overflow flag
SSPCON1bits.WCOL = 0; // Clear the collision bit
SSPCON1bits.CKP = 1;
board_state = BOARD_STATE_ERROR;
} else {
if (!SSPSTATbits.D_NOT_A) {
//Slave address
debug(0, ON);
//Read address
address = SSPBUF; //Clear BF
while(BF); //Wait until completion
if (SSPSTATbits.R_NOT_W) {
SSPCON1bits.WCOL = 0;
unsigned char a = 0x01;
SSPBUF = a;//0x01 works //Deliver first byte
asm("nop");
}
} else {
if (SSPSTATbits.BF) {
dummy = SSPBUF; // Clear BF (just in case)
while(BF);
}
if (SSPSTATbits.R_NOT_W) {
//Multi-byte read
debug(1, ON);
SSPCON1bits.WCOL = 0;
SSPBUF = 0x02; //Deliver second byte
asm("nop");
} else {
//WRITE
debug(2, ON);
}
}
transmitted = TRUE;
SSPCON1bits.CKP = 1;
PIR1bits.SSPIF = 0;
PIE1bits.SSPIE = 1; // Enable Master Synchronous Serial Port Interrupt
}
}
It works like a charm if I set constant values on SSPBUF. For example, if you do:
SSPBUF = 0x01;
(...)
SSPBUF = 0x02;
I get the two bytes on the master. I can even see the wave forms of the bytes being transmitted on the oscilloscope. Quite fun!
But when I try to set SSPBUF using a variable like:
unsigned char a = 0x01;
SSPBUF = a;
I get zero on the master.
It is driving me crazy.
Some hypothesis I've discarded:
Watchdog timer is messing up interrupting in the middle of the protocol: It is not. It is disabled and the problem happens in both SSPBUF assignments
I need to wait until BF goes low to continue: I don't. AFAIK, you setup the SSPBUF, clear SSPIF, set CKP and return from interruption to take care of life in 4Mhz while the hardware send data in few Khz. It will interrupt you again when it finishes.
It makes no sense to me. How good it is if you cannot define an arbitrary value using a variable?
Please gurus out there, enlighten this poor programmer.
Thanks in advance.
It has something to do with how the compiler generates the code and some undocumented/unknown PIC restriction around SSPBUF (it is an special register anyway).
I found out that it works when the compiler uses movwf and does not work when the compiler uses movff.
I moved the question to another forum because I realized the audience there is more adequate.
You will find more details here:
https://electronics.stackexchange.com/questions/251763/writing-sspbuf-from-variable-in-i2c-slave-protocol-in-pic18/251771#251771
Try move declaration : "unsigned char a = 0x01;"
to the beginning of the function or try define it as volatile global variable.
take into accunte that SSPBUF is both read and write buffer.check if there are conditions that may cause I2C module to reset this buffer.
I am creating a multi-monitor full screen DXGI/D3D application. I am enumerating through the available outputs and adapters in preparation of creating their swap chains.
When creating my swap chain using DXGI's IDXGIFactory::CreateSwapChain method, I need to provide a swap chain description which includes a buffer description of type DXGI_MODE_DESC that details the width, height, refresh rate, etc. How can I find out what the output is currently set to (or how can I find out what the display mode of the output currently is)? I don't want to change the user's resolution or refresh rate when I go to full screen with this swap chain.
After looking around some more I stumbled upon the EnumDisplaySettings legacy GDI function, which allows me to access the current resolution and refresh rate. Combining this with the IDXGIOutput::FindClosestMatchingMode function I can get pretty close to the current display mode:
void getClosestDisplayModeToCurrent(IDXGIOutput* output, DXGI_MODE_DESC* outCurrentDisplayMode)
{
DXGI_OUTPUT_DESC outputDesc;
output->GetDesc(&outputDesc);
HMONITOR hMonitor = outputDesc.Monitor;
MONITORINFOEX monitorInfo;
monitorInfo.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(hMonitor, &monitorInfo);
DEVMODE devMode;
devMode.dmSize = sizeof(DEVMODE);
devMode.dmDriverExtra = 0;
EnumDisplaySettings(monitorInfo.szDevice, ENUM_CURRENT_SETTINGS, &devMode);
DXGI_MODE_DESC current;
current.Width = devMode.dmPelsWidth;
current.Height = devMode.dmPelsHeight;
bool useDefaultRefreshRate = 1 == devMode.dmDisplayFrequency || 0 == devMode.dmDisplayFrequency;
current.RefreshRate.Numerator = useDefaultRefreshRate ? 0 : devMode.dmDisplayFrequency;
current.RefreshRate.Denominator = useDefaultRefreshRate ? 0 : 1;
current.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
current.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
current.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
output->FindClosestMatchingMode(¤t, outCurrentDisplayMode, NULL);
}
...But I don't think that this is really the correct answer because I'm needing to use legacy functions. Is there any way to do this with DXGI to get the exact current display mode rather than using this method?
I saw solution here:
http://www.rastertek.com/dx11tut03.html
In folow part:
// Now go through all the display modes and find the one that matches the screen width and height.
// When a match is found store the numerator and denominator of the refresh rate for that monitor.
for(i=0; i<numModes; i++)
{
if(displayModeList[i].Width == (unsigned int)screenWidth)
{
if(displayModeList[i].Height == (unsigned int)screenHeight)
{
numerator = displayModeList[i].RefreshRate.Numerator;
denominator = displayModeList[i].RefreshRate.Denominator;
}
}
}
Is my understanding correct, the available resolution is in the displayModeList.
This might be what you are looking for:
// Get display mode list
std::vector<DXGI_MODE_DESC*> modeList = GetDisplayModeList(*outputItor);
for(std::vector<DXGI_MODE_DESC*>::iterator modeItor = modeList.begin(); modeItor != modeList.end(); ++modeItor)
{
// PrintDisplayModeInfo(*modeItor);
}
}
std::vector<DXGI_MODE_DESC*> GetDisplayModeList(IDXGIOutput* output)
{
UINT num = 0;
DXGI_FORMAT format = DXGI_FORMAT_R32G32B32A32_TYPELESS;
UINT flags = DXGI_ENUM_MODES_INTERLACED | DXGI_ENUM_MODES_SCALING;
// Get number of display modes
output->GetDisplayModeList(format, flags, &num, 0);
// Get display mode list
DXGI_MODE_DESC * pDescs = new DXGI_MODE_DESC[num];
output->GetDisplayModeList(format, flags, &num, pDescs);
std::vector<DXGI_MODE_DESC*> displayList;
for(int i = 0; i < num; ++i)
{
displayList.push_back(&pDescs[i]);
}
return displayList;
}
I have some cross platform DNS client code that I use for doing end to end SMTP and on windows I can find the current DNS server ip addresses by looking in the registry. On the Mac I can probably use the SystemConfiguration framework as mentioned in the first answer, however the exact method of doing so is not immediately obvious.
For instance SCDynamicStoreCopyDHCPInfo returns some of the dynamic DHCP related data but not the DNS server addresses.
I know its very late to answer this question but may be helpful for the others.
This Code will help out for this task ..
SCPreferencesRef prefsDNS = SCPreferencesCreate(NULL, CFSTR("DNSSETTING"), NULL);
CFArrayRef services = SCNetworkServiceCopyAll(prefsDNS);
long servicesCount = CFArrayGetCount(services);
for (long i = 0; i < servicesCount; i++) {
const SCNetworkServiceRef service = (const SCNetworkServiceRef)CFArrayGetValueAtIndex(services, i);
CFStringRef interfaceServiceID = SCNetworkServiceGetServiceID(service);
CFStringRef primaryservicepath = CFStringCreateWithFormat(NULL,NULL,CFSTR("State:/Network/Service/%#/DNS"),interfaceServiceID);
SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, CFSTR("DNSSETTING"), NULL, NULL);
CFPropertyListRef propList = SCDynamicStoreCopyValue(dynRef,primaryservicepath);
if (propList) {
CFDictionaryRef dict = (CFDictionaryRef)propList;
CFArrayRef addresses = (CFArrayRef)CFDictionaryGetValue(dict, CFSTR("ServerAddresses"));
long addressesCount = CFArrayGetCount(addresses);
for (long j = 0; j < addressesCount; j++) {
CFStringRef address = (CFStringRef)CFArrayGetValueAtIndex(addresses, j);
// Print address
CFShow(address);
}
CFRelease(propList);
}
CFRelease(dynRef);
CFRelease(primaryservicepath);
}
CFRelease(services);
CFRelease(prefsDNS);
I know it's been a long time since you needed this, but there is nothing worse than a old unsolved answer. You can't access them from "/etc/resolv.conf" because of permission issues. After much searching, and a little luck I discovered you can get it via res_ninit() function.
// Get native iOS System Resolvers
res_ninit(&_res);
res_state res = &_res;
for (int i = 0; i < res->nscount; i++) {
sa_family_t family = res->nsaddr_list[i].sin_family;
int port = ntohs(res->nsaddr_list[i].sin_port);
if (family == AF_INET) { // IPV4 address
char str[INET_ADDRSTRLEN]; // String representation of address
inet_ntop(AF_INET, & (res->nsaddr_list[i].sin_addr.s_addr), str, INET_ADDRSTRLEN);
} else if (family == AF_INET6) { // IPV6 address
char str[INET6_ADDRSTRLEN]; // String representation of address
inet_ntop(AF_INET6, &(res->nsaddr_list [i].sin_addr.s_addr), str, INET6_ADDRSTRLEN);
}
}
res_ndestroy(res);
You can use the SystemConfiguration framework. It's in C.
Update: apparently the rest of the web is harder to use than I thought. Search for the key "State:/Network/Service/ServiceID/DNS" where ServiceID is the ID of the service.
They are also available from
/etc/resolv.conf
You could read from /etc/resolv.conf.