Linux Kernel Source browsing using cscope

Source code browsing in large projects is always tedious job to narrow down. In repositories like Linux Kernel, where the source code grows everyday needs regular updating and indexing to keep the search efficient and correct.

For browsing the source code in Linux Kernel, there are few options and built-in ways to remember when using ‘cscope‘ and ‘ctags‘. This blog shows those options.

Note: This blog will not explain how to use cscope and ctags for browsing.

Linux Kernel Make provides a direct way to index the source code by the following command.

make cscope tags

We can filter our search to specific architecture by specifying the ARCH option

make ARCH=arm cscope tags

Both of the above command is equivalent to the following cscope and ctags command.

cscope -bqkR ; ctags -R

Where,

-b Build the cross-reference only

-q Enable  fast  symbol  lookup  via  an  inverted index

-k For kernel mode (avoids indexing /usr/include and other system directories)

-R Recursive for all directories

Refer man page of cscope and ctags for more options.

Accessing UART in MSP430F5418

UART is the traditional serial communication protocol used. It offers only two pins RX and TX for sending and receiving characters serially. A microcontroller can have more than one UART. For instance MSP430F5418 microcontroller has two UART’s (UART and enhanced UART). Just read the desired controller datasheet for getting the info.

There are two methods of using UART.

  • Polling mode

  • Interrupt mode

Commonly interrupt will be used for reception and polling is used for transmission. Here, I will use both methods. Code used in this article is for MSP430F5418 microcontroller. But, this can be ported to any microcontroller series with minor adjustments. Changes had to be made in the registers and interrupt handlers.

The USCI (Universal Serial Communication Interface) module in MSP430F5418 is responsible for serial communications. It has support for both synchronous protocols (SPI, I2C) and asynchronous protocols (UART, eUART). This controller comes with two USCI modules A and B.

  • USCI A controls UART, IrDA, SPI

  • USCI B controls SPI, I2C

IrDA is Infrared encoder/decoder and eUART is Enhanced UART which supports auto baud rate detection.

Prerequisites

Before sending/transmitting through UART there are various things which needs to be done. It includes selecting the RX/TX pins, USCI reset, selecting clock source, determining baud rate and finally enabling the USCI module…Let us look into the software part for more detail.

Configure the Clock source

Select the pins where the crystal is connected, using the PSEL instruction. After that, select the clock source. !!!yep I can your voice, what is the use of clock in asynchronous mode? The reason is that clock source is necessary for the generation of baud rate to synchronize both transmitter and receiver. I had selected SMCLK. You can select as per your wish. The available clocks are SMCLK, ACLK, UCAxCLK.

void clk_config(void) {
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P7SEL |= 0x03; // Port select XT1
UCSCTL3 |= SELREF_2; // FLL Ref = REFO
UCSCTL6 &= ~XT1OFF; // Set XT1 On
UCSCTL6 |= XT1DRIVE_0 + XTS; // Max drive strength, adjust
// according to crystal frequency.
// LFXT1 HF mode
delay_ms(10);

// Loop until XT1,XT2 & DCO stabilizes
do
{
UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);
// Clear XT2,XT1,DCO fault flags
SFRIFG1 &= ~OFIFG; // Clear fault flags
}while (SFRIFG1&OFIFG); // Test oscillator fault flag

UCSCTL4 = SELA_0 + SELS_0 + SELM_0; // Select ACLK, SMCLK, MCLK as LFXT1
}

Here, the clock source is selected as the high frequency crystal oscillator connected to PORT7 pins 0 and 1. As you can see from the code above, the drive strength is selected as per the crystal oscillator frequency. I had used 4MHz crystal, but you can connect up to the maximum allowed frequency.

Note: While using the external crystal it is necessary to check the oscillator fault flags. This will avoid you a lot of troubles. If your fault flag is set even you had connected the crystal properly, do check the soldering point of the crystal. A small dry soldering will spoil your day.

Initializing UART

First step is to select the RX/TX pin on Port3. Using PSEL enables us to select the UART pins as they are also used as general purpose I/O pins. Then, clearing UCSWRST bit in UCA0CTL1 register resets UART. Baud rate can be generated using external clock source (UCAxCLK) and internal clock sources (SMCLK, ACLK) depending upon the selection of UCSSELx bit. Then, the baud rate generator is configured for 9600 baud from 4MHz SMCLK. UCA0MCTL register is used to provide the necessary modulation. Finally, the UCSWRST is reset to initialize the UART module with the selected configuration.

void uart_init_9600(void) {
P3SEL = 0x30; // Enable TX/RX pins
UCA0CTL1 |= UCSWRST; // Reset USCI
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 0xA0; // Baud rate setting (4MHz 9600)
UCA0BR1 = 0x01; //
UCA0MCTL |= UCBRS_1 + UCBRF_0; // Modulation UCBRSx=1, UCBRFx=0
UCA0CTL1 &= ~UCSWRST; // Enable UART
// UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt
// __bis_SR_register(GIE); // interrupts enabled
}

Note: The UCSWRST bit should be set before configuring the USCI registers. Finally, it should be reset to enable UART.

Polling mode

In this mode the interrupts are not used. Instead the interrupt flags are polled in order to transmit and receive. The interrupt flags are always set during TX and RX irrespective of enabling or disabling interrupts.

Transmitting Characters

Transmission can be enabled by writing to UCA0TXBUF. If the buffer is empty UCTXIFG flag will be set, when it is full it will bet reset. Here, the flag is polled untill it is set. Once, it is set the data will be written to the buffer and the data will be transferred to the Transmit shift register then transmitted via TX pin. The TX flag will automatically reset once the data is loaded into buffer and will be set when it is transmitted.

void uart_put_char(char data)
{
while (!(UCA0IFG&UCTXIFG)); // Is USCI_A0 TX buffer ready?
UCA0TXBUF = data; // Transmit the data
return;
}

Receiving Characters

Method used for transmission is used for reception also. The UCRXIFG is polled until it is set. When there is data in UCA0RXBUF the flag will be set, once the data is read it will be automatically reset.

char uart_get_char(void)
{
unsigned char rec_data;
while (!(UCA0IFG&UCRXIFG)); // Is USCI_A0 RX buffer ready?
rec_data = UCA0RXBUF; // Read the data
return rec_data;
}

Interrupt mode

Using interrupts is the recommended way over polling, because polling causes the time of the controller to be wasted. Hence, interrupts are used to save the processor time. Also, if you were not aware of the timing of the receiving character, using  interrupt will be handy. MSP430F5418 uses same interrupt handler for both transmission and reception. If the TX and RX interrupt are enabled the interrupt request will be generated during transmission and reception.

Uncomment the last two lines in uart_init_9600() function to enable interrupt. It is to be noted that the interrupt is enabled only for reception.

Interrupt handler

#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
{
switch(__even_in_range(UCA0IV,4))
{
case 0:break; // Vector 0 - no interrupt
case 2: // Vector 2 - RXIFG
buffer = UCA0RXBUF; // Read the data
break;
case 4:break; // Vector 4 - TXIFG
default: break;
}
}

When a byte is arrived it will be stored in the UCA0RXBUF buffer, then the interrupt flag will be set and the RX ISR will be called. Inside the ISR, the data byte will be read, then the UCRXIFG flag will be automatically reset.

Delay function

Using the accurate delay in your code is recommended. When it comes to delay, many of us will use the for loop for generating the delay. But, that will not be accurate. TI doesn’t provides any delay function in their libraries. So, I had written a delay function, which will be far more accurate than the delay generated using for loop.

I used for loop too :_)

inline void delay_ms(unsigned int k) {
unsigned int j;
for(j=0;j<k;j++) {
_delay_cycles(4000);
}
}

[Bash Tricks]: sudo to last run command

To re-run the previous command, we can use the below special way in bash.

!! #This re-runs the previous command

But the question is, why should i run ‘!!’ instead of using up arrow for previous command. One quick use case would be for running ‘sudo’.

We often end up in ‘Permission denied’ error and re-run the same command using ‘sudo’ either by re-typing the whole command or by giving up arrow and navigate to the beginning using ‘Home’ Button or ‘Side Arrows’ or using ‘Ctrl + a’ (as mentioned in Quick Linux CLI tips, at least it was the best way).

Another best way to re-run the previous command with ‘sudo’ can be the following.

sudo !!

Re run the previous command with sudo

  • Re run the previous command with sudo

Here is the working video of  sudo to last run command

https://youtu.be/_hiv3ef7bg4

[Bash Tricks]: Editing wrongly typed command

 

We often used to type a lengthy command and realize the error after running the command. To correct this error, either we used to re-type the whole command or edit (after up arrow). This can be easily handled with bash tricks by using ‘^’.

Example:

cp /some/very/long/path/for/the/source /some/extra/loong/path/for/destination

Note the wrong spell ‘loong’ in destination path. To resolve this, either we used to re-type the whole command or edit the spell for correct destination.

The above can be done in one liner bash tricks as below.

^loong^long

Here is the working video of  Editing wrongly typed command

https://youtu.be/HEZJ1t_XfKA

[Bash Tricks]: Re-run a range of ‘history’ commands

Sometime we may want to run a range of commands which was run in the past (captured in ‘history‘ command). This can be achieved using ‘fc’ command.

Run ‘history’ command to find the range you want to re-run. For example, range from 1000 to 1010.

fc 1000 1010

The above command will copy the range of commands to a temporary file (same can be saved as shell script if you wish to re-run in future) and open it. The default editor is ‘vim’, use ‘:w [filename]’ to save to new file.

Running a single command from history can be done using ![command number in history]. For example ,

!1000 #This will run the command in 1000th line in history. !1000:p #Just previewing without running

Note: ‘fc’ is bash built-in command. So no external package is needed.

Caution: The above command will be executed once you run ‘fc’. So beware of ‘rm’ and similar commands. Try out in /tmp