Time from startup in linux kernel - c

I would like to retrieve time passed since kernel's start (in kernel space). It should be the match the time printk(); is using (For example:[ 5.832000] message ).
jiffies provide different time, so I am not sure it fits me.
How can I achieve this?

What about using get_monotonic_boottime? jiffies are initialized to 5 minutes before boot to ensure that there is an overflow soon after booting and detect bugs.

printk implementation lies in kernel/printk/printk.c souce file.
Here it uses following structure before writing log into buffer which we see in console.
struct printk_log {
u64 ts_nsec; /* timestamp in nanoseconds */
u16 len; /* length of entire record */
u16 text_len; /* length of text buffer */
u16 dict_len; /* length of dictionary buffer */
u8 facility; /* syslog facility */
u8 flags:5; /* internal record flags */
u8 level:3; /* syslog level */
};
ts_nsec -> This parameter is set by function "local_clock" which in turn calls "Sched_clock" [ defined in /kernel/sched/clock.c ].
unsigned long long __weak sched_clock(void)
{
return (unsigned long long)(jiffies - INITIAL_JIFFIES)
* (NSEC_PER_SEC / HZ);
}
#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
i think this will give you more insight about the printk logging

Related

Getting kernel image size in uboot

I'm attempting to create custom functionality for kernel authenticity validation on my uboot on an armv8 based platform. The method in which context I'm working in is boot_jump_linux, seen in uboot source here, around line #50.
The parameter (bootm_headers_t *images) includes the information on where the kernel is loaded in memory. With that I've been able to iterate over the specific memory area and otherwise I have everything I need, but I'm missing the information on the length of kernel data. The struct under *images references multiple relevant data structures found here:
typedef struct image_header {
uint32_t ih_magic; /* Image Header Magic Number */
uint32_t ih_hcrc; /* Image Header CRC Checksum */
uint32_t ih_time; /* Image Creation Timestamp */
uint32_t ih_size; /* Image Data Size */
uint32_t ih_load; /* Data Load Address */
uint32_t ih_ep; /* Entry Point Address */
uint32_t ih_dcrc; /* Image Data CRC Checksum */
uint8_t ih_os; /* Operating System */
uint8_t ih_arch; /* CPU architecture */
uint8_t ih_type; /* Image Type */
uint8_t ih_comp; /* Compression Type */
uint8_t ih_name[IH_NMLEN]; /* Image Name */
} image_header_t;
typedef struct image_info {
ulong start, end; /* start/end of blob */
ulong image_start, image_len; /* start of image within blob, len of image */
ulong load; /* load addr for the image */
uint8_t comp, type, os; /* compression, type of image, os type */
uint8_t arch; /* CPU architecture */
} image_info_t;
All values in the above image_header have a similar constant value, including timestamp, so that leads me to believe that they haven't been initialized. Additionally the image_info struct contains values of 0 all length related fields.
Is there some other way of determining the kernel size, or should I just fall back on to a predetermined default value?

GPS UART data written multiple times to Buffer

I am receiving/reading data from a GPS module sent via USART3 to the STM32F091.
The data gets there just fine which I confirm by sending it to my PC COM3 port and feeding it to 'u-center' (GPS evaulation software).
My problem is that I want to evaluate the data myself in my C program, and for that purpose I feed it into a Ring Buffer, however, every character of the GPS signal is written multiple times to the buffer, instead of one by one.
For example
GGGGGGGPPPPPPPPSSSSSSSS instead of GPS
I am unsure what I'm doing wrong, maybe it's something really obvious I'm overlooking after staring at this code so long.
Here's the relevant code.
stm32f0xx_it.c
#include <main.h>
void USART3_8_IRQHandler(void)
{
if (USART_FLAG_RXNE != RESET)
{
uint16_t byte = 0;
/* Data reception */
/* Clear Overrun Error Flag, necessary when RXNE is used */
USART_GetITStatus(USART3, USART_IT_ORE);
/* Read from Receive Data Register and put into byte */
byte = USART_ReceiveData(USART3);
(*pRXD3).wr = ((*pRXD3).wr + 1) % (*pRXD3).max;
(*pRXD3).Buffer[(*pRXD3).wr] = byte;
/* Send Data to PC, and reset Transmission Complete Flag */
USART_GetITStatus(USART1, USART_IT_TC);
USART_SendData(USART1, byte);
return;
}
return;
}
uartGPS.h
....
struct GPSuart
{
BYTE Buffer[255];
WORD max;
WORD re;
WORD wr;
};
....
main.h
....
extern volatile BYTE B_ser_txd_3[255];
extern volatile BYTE B_ser_rxd_3[255];
extern volatile struct GPSuart TXD_uart_3;
extern volatile struct GPSuart RXD_uart_3;
extern volatile struct GPSuart *pRXD3;
extern volatile struct GPSuart *pTXD3;
....
Let me know if I should provide additional information.
This:
if (USART_FLAG_RXNE != RESET)
does not test a flag, that code is inspecting the flag constant itself, which is not what you meant.
You need more code, to access the UART's status register and check the flag:
if (USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) != RESET)

Converting from C++ language to C (from class to struct) to use HDC1080 sensor with ATTiny841

Today I'm trying to convert this library: Arduino library for ClosedCube_HDC1080 Humidity and Temperature sensor to use it with an ATTiny841 ATTiny841 datasheet, to do it I'm going to use the Fleury's Library to use the ATTiny841 as Master and the HDC1080 as Slave.
My problem is that I have some issues to convert from the C++ language that is used in the HDC1080 library for Arduino to the ATTiny, which use C language, for that I would show you header files to explain myself.
HDC1080_Registers;
class ClosedCube_HDC1080 {
public:
ClosedCube_HDC1080();
void begin(uint8_t address);
uint16_t readManufacturerId(); // 0x5449 ID of Texas Instruments
uint16_t readDeviceId(); // 0x1050 ID of the device
HDC1080_Registers readRegister();
void writeRegister(HDC1080_Registers reg);
void heatUp(uint8_t seconds);
float readTemperature();
float readHumidity();
float readT(); // short-cut for readTemperature
float readH(); // short-cut for readHumidity
private:
uint8_t _address;
uint16_t readData(uint8_t pointer);
};
#endif
This is from the header (.h) file of HDC1080 sensor, I read that class function is not available in C language, so I decide to use struct function, which I saw that is available in C language, but in examples that I saw on Internet, they only use struct function to declare variables, and functions not like:
ClosedCube_HDC1080();
void begin(uint8_t address);
HDC1080_Registers readRegister();
void writeRegister(HDC1080_Registers reg);
void heatUp(uint8_t seconds);
They are define it outside of the struct function, so I get confused with those void's which are inside of the class function, this is reason why I looking for some help. I just need to know:
How to declare those functions to work with the struct
Is going to be much easier to define them later in the C (.c) file?
Thanks for your time and your patience, is my first time converting from one language to another.
Because the only internal state in that class is a single uint8_t, and this code is run on a microcontroller, it is much better to just supply that address as a parameter to each function.
First, note that my suggestions below are derivative of the ClosedCube HDC1080 Arduino library, and therefore licensed under the same license:
/*
Arduino Library for Texas Instruments HDC1080 Digital Humidity and Temperature Sensor
Originally written by AA for ClosedCube; this suggested conversion by Nominal Animal
---
The MIT License (MIT)
Copyright (c) 2016-2017 ClosedCube Limited
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
ATtinys are small 8-bit microcontrollers, so it's best to avoid using the float type. Instead, I suggest you use units of 1/1000 degrees Celsius for temperature (25000 referring to 25 degrees Celsius), and 1/100000 for humidity (50000 referring to 50% of relative humidity).
The interface to the adapted library can be quite simple:
void HDC1080_begin(const uint8_t address);
void HDC1080_heater(const uint8_t address, const uint8_t seconds);
uint16_t HDC1080_manufacturer(const uint8_t address);
uint16_t HDC1080_device_id(const uint8_t address);
int32_t HDC1080_temperature(const uint8_t address);
uint32_t HDC1080_humidity(const uint8_t address);
If we assume we keep temperature and humidity precision at 14 bits (configured by HDC1080_begin(), we don't need the user to set or read the configuration register.
The example code shows that HDC1080_manufacturer() should return 0x5449, and HDC1080_device_id() should return 0x1050.
Since we don't know what kind of interface the "Fleury's Library" has, I shall show the implementation of the above functions with comments (starting with /* I2C:) instead of actual library calls.
The static ones are internal functions only used by the abovementioned functions, not "user" code.
#define HDC1080_TEMPERATURE ((uint8_t)0x00)
#define HDC1080_HUMIDITY ((uint8_t)0x01)
#define HDC1080_CONFIGURATION ((uint8_t)0x02)
#define HDC1080_SERIAL_ID_FIRST ((uint8_t)0xFB)
#define HDC1080_SERIAL_ID_MID ((uint8_t)0xFC)
#define HDC1080_SERIAL_ID_LAST ((uint8_t)0xFD)
#define HDC1080_MANUFACTURER_ID ((uint8_t)0xFE)
#define HDC1080_DEVICE_ID ((uint8_t)0xFF)
/* Bits 15..8 of the HDC1080 configuration.
Heater disabled, 14 bit precision for
both temperature and relative humidity.
See page 15 of
http://www.ti.com/lit/ds/symlink/hdc1080.pdf
for other possibilities.
*/
#define HDC1080_CONFIG_HI ((uint8_t)0)
static uint16_t HDC1080_read(const uint8_t address, const uint8_t item)
{
uint8_t hi, lo;
/* I2C: Prepare to send to i2c address 'address'. */
/* I2C: Send 8 bits 'item'. */
/* I2C: End transmission. */
/* Delay for 9 ms (0.009 seconds). */
/* I2C: Prepare to read 2 bytes from i2c address 'address'. */
hi = /* I2C: Read byte. */
lo = /* I2C: Read byte. */
return (((uint16_t)hi) << 8) | lo;
}
void HDC1080_begin(const uint8_t address)
{
/* I2C: Prepare to send to i2c address 'address'. */
/* I2C: Send 8 bits: HDC1080_CONFIGURATION (=0x02). */
/* I2C: Send 8 bits: HDC1080_CONFIG_HI (=0x00). */
/* I2C: Send 8 bits: 0. */
/* I2C: End transmission. */
/* Delay for 10 ms = 0.01 seconds. */
}
void HDC1080_heater(const uint8_t address, const uint8_t seconds)
{
uint8_t s, i;
/* I2C: Prepare to send to i2c address 'address'. */
/* I2C: Send 8 bits: HDC1080_CONFIGURATION (=0x02). */
/* I2C: Send 8 bits: 48 (=0x30). */
/* I2C: Send 8 bits: 0. */
/* I2C: End transmission. */
/* Delay for 10 ms = 0.01 seconds. */
for (s = 0; s < seconds; s++) {
for (i = 0; i < 66; i++) {
/* I2C: Prepare to send to i2c address 'address'. */
/* I2C: Send 8 bits 'item'. */
/* I2C: End transmission. */
/* Delay for 20 ms (0.020 seconds). */
/* I2C: Prepare to read 4 bytes from i2c address 'address'. */
/* I2C: Read byte. (Ignore the value.) */
/* I2C: Read byte. (Ignore the value.) */
/* I2C: Read byte. (Ignore the value.) */
/* I2C: Read byte. (Ignore the value.) */
}
}
/* I2C: Prepare to send to i2c address 'address'. */
/* I2C: Send 8 bits: HDC1080_CONFIGURATION (=0x02). */
/* I2C: Send 8 bits: HDC1080_CONFIG_HI (=0x00). */
/* I2C: Send 8 bits: 0. */
/* I2C: End transmission. */
/* Delay for 10 ms = 0.01 seconds. */
}
uint16_t HDC1080_manufacturer(const uint8_t address)
{
return HDC1080_read(address, HDC1080_MANUFACTURER_ID);
}
uint16_t HDC1080_device_id(const uint8_t address)
{
return HDC1080_read(address, HDC1080_DEVICE_ID);
}
int32_t HDC1080_temperature(const uint8_t address)
{
uint16_t temp1 = HDC1080_read(address, HDC1080_TEMPERATURE) >> 2;
return (int_t)(((uint32_t)20625 * temp1 + (uint32_t)1024) >> 11) - (int32_t)40000;
}
uint32_t HDC1080_humidity(const uint8_t address)
{
uint16_t temp1 = HDC1080_read(address, HDC1080_HUMIDITY);
return ((uint32_t)3125 * temp1 + (uint32_t)1024) >> 11;
}
Note that the relative humidity range is 0 to 99998, i.e. 0%RH to 99.998% RH. This is not an error, and the formula is taken from the datasheet and losslessly scaled to the new range. Similarly, the possible temperature range is -40000 to +124989, corresponding to -40°C to +124.989°C, and this too is according to the TI datasheet, losslessly scaled to the new range. The + (uint32_t)1024 term in both ensures correct rounding (to nearest).
You do still need to implementing the /* I2C: and /* Delay comments using whatever library you have at hand.

STM32F0 USB CDC_Init_FS() and CDC_Receive_FS() using CubeMX

I am using this code to capture data over the USB. The top code crashes the program once a character is received. The bottom works just fine, although I cannot save the data as I want. The top crashes (endless loop) even before calling CDC_Receive_FS()...which is never called. The bottom calls CDC_Receive_FS() as expected.
For the life of me, I cannot see what is wrong with how I am calling my struct that holds an array of buffers that I loop through.
/* Send Data over USB CDC are stored in this buffer */
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
#define MAX_COMMANDS_IN_BUFFER 10 //max commands that can be received and saved without overwriting. Each command has a max size of APP_RX_DATA_SIZE
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
#define APP_RX_DATA_SIZE 256
#define APP_TX_DATA_SIZE 256
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
static struct
{
uint32_t Buffer_Number_Receiving, Buffer_Number_Processing; //Buffer_Number_Receiving is the current position in buffer to receive incoming data. Buffer_Number_Processing is the index of buffer which is being processed.
uint8_t IsCommandDataReceived; // > 0 , data were received. 0 means no data is available
uint8_t UserRxBufferFS[MAX_COMMANDS_IN_BUFFER][APP_RX_DATA_SIZE];//it could save <MaxCommandsInBuffer> number of commands
uint8_t CommandsLens[MAX_COMMANDS_IN_BUFFER]; //save the len of each command
} s_RxBuffers;
static int8_t CDC_Init_FS(void)
{
hUsbDevice_0 = &hUsbDeviceFS;
/* USER CODE BEGIN 3 */
/* Set Application Buffers */
USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, 0);
USBD_CDC_SetRxBuffer(hUsbDevice_0, s_RxBuffers.UserRxBufferFS[s_RxBuffers.Buffer_Number_Receiving] );//Set the buffer to receive incoming data
USBD_CDC_ReceivePacket(hUsbDevice_0);
return (USBD_OK);
/* USER CODE END 3 */
}
This does not:
/* Received Data over USB are stored in this buffer */
uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* Send Data over USB CDC are stored in this buffer */
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
static int8_t CDC_Init_FS(void)
{
hUsbDevice_0 = &hUsbDeviceFS;
/* USER CODE BEGIN 3 */
/* Set Application Buffers */
USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, 0);
USBD_CDC_SetRxBuffer(hUsbDevice_0, UserRxBufferFS);
USBD_CDC_ReceivePacket(hUsbDevice_0);
return (USBD_OK);
}
Loop
The line here (the use of this buffer) seems to be the culprit:
USBD_CDC_SetRxBuffer(hUsbDevice_0, s_RxBuffers.UserRxBufferFS[s_RxBuffers.Buffer_Number_Receiving] );//Set the buffer to receive incoming data
Any help/insight would be greatly appreciated.
I would make the Rx_Buffer monodimensional and handle the command history separatly.
static struct
{
uint32_t Buffer_Number_Receiving, Buffer_Number_Processing; //Buffer_Number_Receiving is the current position in buffer to receive incoming data. Buffer_Number_Processing is the index of buffer which is being processed.
uint8_t IsCommandDataReceived; // > 0 , data were received. 0 means no data is available
uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
uint8_t CommandsLens[MAX_COMMANDS_IN_BUFFER]; //save the len of each command
} s_RxBuffers;
Apart from this, since you are usinc a struct (s_RxBuffers type), I think you are not passing the buffer as a pointer in the right way to your function.
I think you should do something like this:
USBD_CDC_SetRxBuffer(hUsbDevice_0, &s_RxBuffers.UserRxBufferFS[0] );//Set the buffer to receive incoming data

Correct way of implementing a uart receive buffer in a small ARM microcontroller?

I am looking for ideas for a receive buffer for a small application dealing with 15 byte packets at 921.6Kbaud over rs485. I am thinking of using a circular buffer as the interface between the UART ISR and main. As it is a microprocessor I was wanting to put
while (uartindex!=localindex) { do stuff }
in the
while (;;) {do forever}
part of main but I have been told this is not acceptable.
How do people deal with their uarts under similar circumstances?
ISR should fill a FIFO. Main should consume it.
Bellow a very simple fifo algorithm:
#define RINGFIFO_SIZE (1024) /* serial buffer in bytes (power 2) */
#define RINGFIFO_MASK (RINGFIFO_SIZE-1ul) /* buffer size mask */
/* Buffer read / write macros */
#define RINGFIFO_RESET(ringFifo) {ringFifo.rdIdx = ringFifo.wrIdx = 0;}
#define RINGFIFO_WR(ringFifo, dataIn) {ringFifo.data[RINGFIFO_MASK & ringFifo.wrIdx++] = (dataIn);}
#define RINGFIFO_RD(ringFifo, dataOut){ringFifo.rdIdx++; dataOut = ringFifo.data[RINGFIFO_MASK & (ringFifo.rdIdx-1)];}
#define RINGFIFO_EMPTY(ringFifo) (ringFifo.rdIdx == ringFifo.wrIdx)
#define RINGFIFO_FULL(ringFifo) ((RINGFIFO_MASK & ringFifo.rdIdx) == (RINGFIFO_MASK & (ringFifo.wrIdx+1)))
#define RINGFIFO_COUNT(ringFifo) (RINGFIFO_MASK & (ringFifo.wrIdx - ringFifo.rdIdx))
/* buffer type */
typedef struct{
uint32_t size;
uint32_t wrIdx;
uint32_t rdIdx;
uint8_t data[RINGFIFO_SIZE];
} RingFifo_t;
RingFifo_t gUartFifo;
(Care must be taken with this FIFO algorithm, size MUST be power of 2)
The ISR should behave like this:
void ISR_Handler()
{
uint8_t c;
while(UART_NotEmpty()) {
c = UART_GetByte();
RINGFIFO_WR(gUartFifo, c);
}
}
And the Main:
while(1)
{
if (!RINGFIFO_EMPTY(gUartFifo)) {
/* consume fifo using RINGFIFO_RD */
}
}
This algorithm reads the FIFO directly from the main loop, you should use a intermediate layer that checks if there is a full packet in the buffer, and deals with it, in such a manner that main would be like this:
uint8_t ptrToPacket;
uint32_t packetSize;
while(1)
{
if (!Uart_HasValidPacket()) {
Uart_GetPacket(&ptrToPacket, &packetSize)
/* Process packet using ptrToPacket and packetSize */
}
}
The approach you suggest would probably be workable if the uartindex is never written in the main loop (except to initialize it while interrupts are disabled), and localindex is never touched by the interrupt routine.
I would suggest that you make your buffer size be a power of 2, use unsigned integers for the two indices, and allow them to count freely over their full 32-bit size; use bit masking when indexing your buffer in both the "stuff" and "fetch" routines. If you do that, then
(unsigned)(uartindex-localindex)
should indicate how many characters are in the buffer, even when it's completely full, without requiring special-case behavior in the buffer-full case and without limiting an N-byte buffer to holding N-1 items.
Note that while the typecast in the aforementioned expression isn't strictly necessary, I would recommend including it since it makes obvious that the wrapping behavior when subtracting unsigned quantities is deliberate and expected.

Resources