Thursday, April 30, 2020

OAL - Operating System Abstraction Layer

What is the Operating System Abstraction Layer?
- A small layer of software that allows programs to run on many different operating systems and hardware platforms - Independent of the underlying OS & hardware - Self-contained

Why do we want it?
 - Removes dependencies from any one operating system - Promotes portable, reusable flight software - Core FSW can be built for multiple processors and operating systems - Example: different missions require different hardware & operating system

What does it do?
- Allows developers to write and maintain one version of code - Allows for easy reuse across different missions with different hardware - Bonus: Allows for desktop development of flight software; reduces impact of potential hardware delays

Functionality - Standard APl's
Abstracted ID'S and information
- All entities named Task API - Create, Delete, Exit, Delay, Set Priority, Get Info, Register, Get ID, Get ID by Name Queue API - Create, Delete, Get (wl timeout), Put, Get ID, Get ID by Name, Get Info, Semaphore API - Binary Semaphores - Counting Semaphores - Mutexes - Create, Delete, Take, Give, Get Info, Timed Wait, Get ID by Name Misc API - Millisecs to System Ticks, Ticks to MicroSecs, Get Time, Interrupt DisablelEnable and LocWUnlock, Printing utility


Functionality (2)
- File System APl's
Abstracted FS - The file system has the same interface to the user no matter the underlying OS File

System API - Make FS, Remove FS, lnit FS, Mount, Unmount, Get Physical Device Name File API - Create, Remove, Open, Close, Read, Write, Lseek, Rename, Copy, Move Files - Make, Remove, Open, Close, Read Files - Get Info on File Descriptors - Send Shell Command to a file

ARM Coretex A9 Tutorial | Core Register Access

Stack Pointer (SP/R13)
The processor uses SP as a pointer to the active stack. More...

Functions

__STATIC_INLINE __ASM void __set_SP (uint32_t stack)
 Set Stack Pointer. More...
 
__STATIC_INLINE __ASM void __set_SP_usr (uint32_t topOfProcStack)
 Set USR/SYS Stack Pointer. More...
 

Description

The Stack Pointer is banked per processor mode. Accessing the active stack pointer actually returns/modifies the stack pointer of the current processor execution mode.
ModeActual SP
User/SystemSP_usr
HypervisorSP_hyp
SupervisorSP_svc
AbortSP_abt
UndefinedSP_und
MonitorSP_mon
IRQSP_irq
FIQSP_fiq
Consider __set_SP and __set_SP_usr to access this register.

Function Documentation

__STATIC_INLINE __ASM void __set_SP(uint32_t stack)
Parameters
[in]stackStack Pointer value to set
This function assigns the given value to the current stack pointer.
__STATIC_INLINE __ASM void __set_SP_usr(uint32_t topOfProcStack)
Parameters
[in]topOfProcStackUSR/SYS Stack Pointer value to set
This function assigns the given value to the User/System Stack Pointer (SP_usr).

Example:
To set value for Stack Pointer Register:
uint32_t maskValue = 0x0001;

__set_SP(maskValue);








ARM Coretex A9 Tutorial | System and Clock Configuration

Functions

void SystemInit (void)
 Function to Initialize the system. More...
 
void SystemCoreClockUpdate (void)
 Function to update the variable SystemCoreClockMore...
 

Variables

uint32_t SystemCoreClock
 Variable to hold the system core clock value. More...
 

Description

Arm provides a template file system_device.c that must be adapted by the silicon vendor to match their actual device. As a minimum requirement, this file must provide:
  • A device-specific system configuration function, SystemInit().
  • A global variable that contains the system frequency, SystemCoreClock.
The file configures the device and, typically, initializes the oscillator (PLL) that is part of the microcontroller device. This file might export other functions or variables that provide a more flexible configuration of the microcontroller system.
Note
Please pay special attention to the static variable SystemCoreClock. This variable might be used throughout the whole system initialization and runtime to calculate frequency/time related values. Thus one must assure that the variable always reflects the actual system clock speed. Be aware that a value stored to SystemCoreClock during low level initialization (i.e. SystemInit()) might get overwritten by C library startup code. Thus its highly recommended to call SystemCoreClockUpdate at the beginning of the user main() routine.

Code Example

The code below shows the usage of the variable SystemCoreClock and the functions SystemInit() and SystemCoreClockUpdate() with an arbitrary Arm Cortex-A9.
#include "ARMCA9.h"
uint32_t coreClock_1 = 0; /* Variables to store core clock values */
uint32_t coreClock_2 = 0;
int main (void) {
coreClock_1 = SystemCoreClock; /* Store value of predefined SystemCoreClock */
SystemCoreClockUpdate(); /* Update SystemCoreClock according to register settings */
coreClock_2 = SystemCoreClock; /* Store value of calculated SystemCoreClock */
if (coreClock_2 != coreClock_1) { /* Without changing the clock setting both core clock values should be the same */
// Error Handling
}
while(1);
}

Function Documentation

void SystemCoreClockUpdate(void )
Updates the variable SystemCoreClock and must be called whenever the core clock is changed during program execution. The function evaluates the clock register settings and calculates the current core clock.
void SystemInit(void )
Initializes the microcontroller system. Typically, this function configures the oscillator (PLL) that is part of the microcontroller device. For systems with a variable clock speed, it updates the variable SystemCoreClock. SystemInit is called from the file startup_device.

Variable Documentation


uint32_t SystemCoreClock
Holds the system core clock, which is the system clock frequency supplied to the SysTick timer and the processor core clock. This variable can be used by debuggers to query the frequency of the debug timer or to configure the trace clock speed.
Attention
Compilers must be configured to avoid removing this variable in case the application program is not using it. Debugging systems require the variable to be physically present in memory so that it can be examined to configure the debugger.

ARM Core A9 Tutorial | Basic CMSIS Example

#include <ARMCA9.h> // File name depends on device used
static const uint32_t TICK_RATE_HZ = 1000U;
uint32_t volatile msTicks; // Counter for millisecond Interval
static void SysTick_Handler( void )
{
msTicks++; // Increment Counter
}
// We use the Private Tiemer (PTIM) of the Cortex-A9 FVP Model here.
// In general the available Timers are highly vendor specific for Cortex-A processors.
void private_timer_init(void) {
PTIM_SetLoadValue ((SystemCoreClock/TICK_RATE_HZ) - 1U);
/* Install SysTick_Handler as the interrupt function for PTIM */
/* Determine number of implemented priority bits */
/* Set lowest priority -1 */
/* Enable IRQ */
IRQ_Enable ((IRQn_ID_t)PrivTimer_IRQn);
}
/* Delay execution for given amount of ticks */
void Delay(uint32_t ticks) {
uint32_t tgtTicks = msTicks + ticks; // target tick count to delay execution to
while (msTicks == tgtTicks) {
__WFE (); // Power-Down until next Event/Interrupt
}
}
/* main function */
int main(void)
{
/* Initialize device HAL here */
private_timer_init();
static uint8_t ledState = 0;
/* Infinite loop */
while (1)
{
/* Add application code here */
ledState = !ledState;
Delay(500);
}
}

Linear Algebra data type - ARM defination

There are some date type which we will use to linear algebra:

+ Floating Point.
+  The Q15 value
For example: Q15 vector absolute value.
void arm_abs_q15(
  q15_t * pSrc,
  q15_t * pDst,
  uint32_t blockSize);

* The Q15 value -1 (0x8000) will be saturated to the maximum allowable positive value 0x7FFF.   

So,what is q15 valule???
 /**
   * @brief 16-bit fractional data type in 1.15 format.
   */
  typedef int16_t q15_t;

If your signal is presently centered around 0x8000 (32768) then just invert bit 15 (15..0) of your data.  This is what the AtoD on the dsPIC does.  In this way what used to be 0x0000 will be 0x8000 and what used to be 0xFFFF will be 0x7FFF.

Now your data will range from 0x8000 (-1.0) to 0x0000 (0.0) to 0x7FFF (1-(1/32768)).  0x7FFF doesn't quite make it to 1.0.

Even though you can have a data type of "fractional" if you include the dsp.h file, it really is an "int" as far as the compiler is concerned.  So no, I don't believe you can display it as fractional.  The fractional data type will work with the dsp functions in the library or any inline functions you design using the DSP portion of the dsPIC as long as you know it is being treated as fractional.

You need to convert them to a range of -1.00<n<1.00, multiply by 32768, then convert to hex. For instance, 0.500 is 0x4000.


And other data type:
/**
   * @brief 8-bit fractional data type in 1.7 format.
   */
  typedef int8_t q7_t;

  /**
   * @brief 16-bit fractional data type in 1.15 format.
   */
  typedef int16_t q15_t;

  /**
   * @brief 32-bit fractional data type in 1.31 format.
   */
  typedef int32_t q31_t;

  /**
   * @brief 64-bit fractional data type in 1.63 format.
   */
  typedef int64_t q63_t;

  /**
   * @brief 32-bit floating-point type definition.
   */
  typedef float float32_t;

  /**
   * @brief 64-bit floating-point type definition.
   */

  typedef double float64_t;

ARM - DSP Tutorial $1 - Example Class Marks Calculation

/**   
 * @defgroup ClassMarks Class Marks Example 
 *
 * \par Description:
 * \par
 * Demonstrates the use the Maximum, Minimum, Mean, Standard Deviation, Variance
 * and Matrix functions to calculate statistical values of marks obtained in a class.
 *
 * \note This example also demonstrates the usage of static initialization.
 * 
 * \par Variables Description:
 * \par
 * \li \c testMarks_f32 points to the marks scored by 20 students in 4 subjects
 * \li \c max_marks     Maximum of all marks
 * \li \c min_marks     Minimum of all marks
 * \li \c mean          Mean of all marks
 * \li \c var           Variance of the marks
 * \li \c std           Standard deviation of the marks
 * \li \c numStudents   Total number of students in the class
 *
 * \par CMSIS DSP Software Library Functions Used:
 * \par
 * - arm_mat_init_f32()
 * - arm_mat_mult_f32()
 * - arm_max_f32()
 * - arm_min_f32()
 * - arm_mean_f32()
 * - arm_std_f32()
 * - arm_var_f32()
 *
 * <b> Refer  </b>
 * \link arm_class_marks_example_f32.c \endlink
 *
 */


/** \example arm_class_marks_example_f32.c
  */ 
#include "arm_math.h"

#define USE_STATIC_INIT

 /* ----------------------------------------------------------------------
** Global defines 
** ------------------------------------------------------------------- */

#define TEST_LENGTH_SAMPLES (20*4)

/* ----------------------------------------------------------------------
** List of Marks scored by 20 students for 4 subjects
** ------------------------------------------------------------------- */ 
const float32_t testMarks_f32[TEST_LENGTH_SAMPLES] = 
{   
42.000000, 37.000000, 81.000000, 28.000000,
83.000000, 72.000000, 36.000000, 38.000000,
32.000000, 51.000000, 63.000000, 64.000000,
97.000000, 82.000000, 95.000000, 90.000000,
66.000000, 51.000000, 54.000000, 42.000000,
67.000000, 56.000000, 45.000000, 57.000000,
67.000000, 69.000000, 35.000000, 52.000000,
29.000000, 81.000000, 58.000000, 47.000000,
38.000000, 76.000000, 100.000000, 29.000000,
33.000000, 47.000000, 29.000000, 50.000000,
34.000000, 41.000000, 61.000000, 46.000000,
52.000000, 50.000000, 48.000000, 36.000000,
47.000000, 55.000000, 44.000000, 40.000000,
100.000000, 94.000000, 84.000000, 37.000000,
32.000000, 71.000000, 47.000000, 77.000000,
31.000000, 50.000000, 49.000000, 35.000000,
63.000000, 67.000000, 40.000000, 31.000000,
29.000000, 68.000000, 61.000000, 38.000000,
31.000000, 28.000000, 28.000000, 76.000000,
55.000000, 33.000000, 29.000000, 39.000000
}; 


/* ----------------------------------------------------------------------
* Number of subjects X 1 
* ------------------------------------------------------------------- */ 
const float32_t testUnity_f32[4] = 
{   
1.000,  1.000, 1.000,  1.000
};


/* ----------------------------------------------------------------------
** f32 Output buffer
** ------------------------------------------------------------------- */ 
static float32_t testOutput[TEST_LENGTH_SAMPLES];


/* ------------------------------------------------------------------
* Global defines 
*------------------------------------------------------------------- */
#define NUMSTUDENTS  20
#define     NUMSUBJECTS  4

/* ------------------------------------------------------------------
* Global variables 
*------------------------------------------------------------------- */

uint32_t  numStudents = 20;
uint32_t  numSubjects = 4; 
float32_t max_marks, min_marks, mean, std, var;
uint32_t student_num;   

/* ----------------------------------------------------------------------------------
* Main f32 test function.  It returns maximum marks secured and student number
* ------------------------------------------------------------------------------- */

int32_t main()
{

#ifndef  USE_STATIC_INIT

  arm_matrix_instance_f32 srcA;
  arm_matrix_instance_f32 srcB;
  arm_matrix_instance_f32 dstC; 

/* Input and output matrices initializations */ 
arm_mat_init_f32(&srcA, numStudents, numSubjects, (float32_t *)testMarks_f32); 
arm_mat_init_f32(&srcB, numSubjects, 1, (float32_t *)testUnity_f32); 
arm_mat_init_f32(&dstC, numStudents, 1, testOutput); 

#else

/* Static Initializations of Input and output matrix sizes and array */
arm_matrix_instance_f32 srcA = {NUMSTUDENTS, NUMSUBJECTS, (float32_t *)testMarks_f32};
arm_matrix_instance_f32 srcB = {NUMSUBJECTS, 1, (float32_t *)testUnity_f32};
arm_matrix_instance_f32 dstC = {NUMSTUDENTS, 1, testOutput};

#endif


/* ----------------------------------------------------------------------
*Call the Matrix multiplication process function 
* ------------------------------------------------------------------- */
arm_mat_mult_f32(&srcA, &srcB, &dstC);

/* ----------------------------------------------------------------------
** Call the Max function to calculate max marks among numStudents
** ------------------------------------------------------------------- */
arm_max_f32(testOutput, numStudents, &max_marks, &student_num); 

/* ----------------------------------------------------------------------
** Call the Min function to calculate min marks among numStudents
** ------------------------------------------------------------------- */
arm_min_f32(testOutput, numStudents, &min_marks, &student_num); 

/* ----------------------------------------------------------------------
** Call the Mean function to calculate mean
** ------------------------------------------------------------------- */
arm_mean_f32(testOutput, numStudents, &mean);

/* ----------------------------------------------------------------------
** Call the std function to calculate standard deviation
** ------------------------------------------------------------------- */
arm_std_f32(testOutput, numStudents, &std);

/* ----------------------------------------------------------------------
** Call the var function to calculate variance
** ------------------------------------------------------------------- */
arm_var_f32(testOutput, numStudents, &var);

    while(1);                             /* main function does not return */
}

Wednesday, April 29, 2020

Explain very Detail about MIPI-CSI2

- What is Virtual Channel:

+ Allow connection of multiple devices to same Bus.

+ Multiple sensors are all aggregated sent as a single stream.

The Lattice Semiconductor MIPI CSI-2 Virtual Channel Aggregation reference design for CrossLink™ devices offers up to five-channel aggregation. A different virtual channel identification (ID) is assigned to each receiver (RX) channel. CrossLink has two MIPI hard macro IPs, which can be used as MIPI TX or RX module (D-PHY Hard IP). The RX module can also be realized by a soft macro utilizing general DDR modules (D-PHY Soft IP).



Question:
1.We 'd like to realize real time souround view camera system by using 4 camera.
But i.MX6Q don't have 4 parallel video capture ports. Max 2 only. (=paralle1 and parallel2)
So Can we capture 4 camera signals simultaneously via MIPI-CSI2(4lane) ?
According to the reference manual,  it seem to accept  interleaved 4 streaming video data.

Answer:
yes, that should be possible. The MIPI-CSI-2 port knows up to 4 virtual channels. Those can be routed to the two IPU blocks (2 each). You need to make sure that each stream uses a different virtual channel. The IPU has to be set to accept two virtual channels each.

Attached a diagram I drew during a discussion with FIL about this topic. Hope this clarifies the isue. Note that the IPU will take care of converting the incoming format to either RGB8888 or YUV4:4.4 before writing the data into memory.

Friday, April 17, 2020

Creating FAT Filesystems in Linux Embedded Board

Sometime we need to allocate much more space to run code which require large of space to run and return trace log.

For example with Board Linux NXP
- Show available space:
dh -h

- Lisk all block existed in Board
lsblk

Installing Required Tools:

You can easily format USB flash drives as FAT. In order to do that, you need to have dosfstools installed.  The package name is that same in all the common Linux distributions. It should already be installed on your computer. If it isn’t, just use your package manager to install dosfstools.
On Ubuntu/Debian, you can install dosfstools with the following command:
sudo apt install dosfstools -y
On CentOS 7 or RHEL 7, you can install dosfstools with the following command:
sudo yum install dosfstools -y

Formatting a USB Flash Drive as FAT:

Now, insert the USB flash drive that you want to format as FAT.
Then, run the following command to find the device name of your USB flash drive.
sudo lsblk
As you can see, the 4 GB USB flash drive has the device name sdb in my case. So, I can access it as /dev/sdb. It may be different for you. Make sure you replace it with yours from now on.
As you can see, I already have a partition /dev/sdb1 on my USB flash drive. So, I don’t have to create a partition. But if you don’t have a partition already, then you should create one first.
If you do have a partition, then unmount the partition first if it is mounted (as in my case). Otherwise, you won’t be able to format it.

To unmount the partition, run the following command:
sudo umount /dev/sdb1
Suppose you don’t have a partition on your USB flash drive for some reason. You can use fdisk to easily create one.
To do that, open /dev/sdb with fdisk as follows:
sudo fdisk /dev/sdb
Now, press o and press <Enter> to create a new DOS partition table.
Now, to create a new partition, press n and then press <Enter>. You should see the following options. We want to create a primary partition. So, just press <Enter> (to select the default option).
Back to Top