Compare commits
10 Commits
43e1b1fce1
...
6d01541ddf
Author | SHA1 | Date |
---|---|---|
Pratham Patel | 6d01541ddf | |
Pratham Patel | 54a9d8e3ab | |
Pratham Patel | 11e7805a4e | |
Pratham Patel | d6ba5569b8 | |
Pratham Patel | 94165256cf | |
Pratham Patel | dcfbda130b | |
Pratham Patel | c3303f3f18 | |
Pratham Patel | 191b79ea01 | |
Pratham Patel | b30b110789 | |
Pratham Patel | d102dfdf14 |
|
@ -0,0 +1,2 @@
|
|||
.hugo_build.lock
|
||||
resources/
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "themes/hugo-coder"]
|
||||
path = themes/hugo-coder
|
||||
url = https://github.com/luizdepra/hugo-coder.git
|
|
@ -0,0 +1,337 @@
|
|||
+++
|
||||
draft = false
|
||||
date = 2022-10-06T10:30:00+05:30
|
||||
slug = "immutable-vars-vs-constants-rs.md"
|
||||
title = "Dfferences between Constants and Variables in Rust"
|
||||
description = "No really, why do constants exist among \"immutable\" variables?"
|
||||
tags = [ "rust", "educational" ]
|
||||
+++
|
||||
|
||||
The reason why the Rust language's developers can advertise features like
|
||||
_thread safety_ and _memory safety guarantee_ is because of a fundamental
|
||||
design ideology of immutable variables. Immutable variables are the type of
|
||||
variables where, once you assign a value, it does not change.
|
||||
|
||||
Rust also has constants. So you might wonder "Why does Rust have Immutable
|
||||
variables _and_ Constants? Aren't they the same thing?"
|
||||
|
||||
In this blog post, I will explain the basics of variables and constants
|
||||
in Rust, and how an immutable variable differs from a mutable variable.
|
||||
|
||||
## Immutable variables VS Constants
|
||||
|
||||
If, like me, Rust is not your first programming language, this confusion is
|
||||
bound to occur sooner rather than later--"Why do either immutable variables
|
||||
or constants exist in Rust?"
|
||||
|
||||
If you have written a simple program in Rust, you will realize that Rust has
|
||||
2 types of variables. One is the type which allows changing a value, even
|
||||
after it is assigned, called _mutable variables_. The second type is the one
|
||||
in question, immutable variables. Unless explicitly specified, Rust assumes
|
||||
a variable is immutable. Meaning, once a value is assigned to your variable,
|
||||
that value will never be allowed to be changed.
|
||||
|
||||
Rust only has one type for constants. The one which makes sense. Immutable by
|
||||
default. Once a value is assigned, it is not allowed to change.
|
||||
|
||||
## Type inferencing
|
||||
|
||||
When you declare a variable in Rust, you do it using the `let` keyword. This
|
||||
is different than other low-level languages like C and C++, where you are to
|
||||
explicitly specify the data-type of a variable using the appropriate keyword
|
||||
like, `int`, `float`, `char`, etc.
|
||||
|
||||
Using the `let` keyword is necessary, but specifying a variable's data-type
|
||||
is not necessary. You can either leave it to the Rust compiler (`rustc`) to
|
||||
take a guess--which hardly misfires--or you can annotate the type yourself.
|
||||
|
||||
This guessing that `rustc` does is called "type inferencing".
|
||||
|
||||
Type inferencing is absent for constants. It is the job of a programmer to
|
||||
provide a type for a constant that is declared.
|
||||
|
||||
Take a look at the following code:
|
||||
|
||||
Filename: const_example.rs
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let my_var = -128;
|
||||
const MY_CONST = -128;
|
||||
}
|
||||
```
|
||||
|
||||
In here, I am declaring an immutable variable (`my_var`) with the value "-128"
|
||||
and a constant (`MY_CONST`) with the same value of "-128". Another similarity
|
||||
is that neither of them are type annotated.
|
||||
|
||||
Let's try and compile this.
|
||||
|
||||
```bash
|
||||
$ rustc const_example.rs
|
||||
error: missing type for `const` item
|
||||
--> const_example.rs:3:11
|
||||
|
|
||||
3 | const MY_CONST = -128;
|
||||
| ^^^^^^^^ help: provide a type for the constant: `MY_CONST: i32`
|
||||
|
||||
error: aborting due to previous error
|
||||
```
|
||||
|
||||
Hmm...
|
||||
|
||||
`rustc` is complaining about an error on line 3 (where we declared our
|
||||
constant). The highlighted part is the name (`MY_CONST`).
|
||||
|
||||
The help states "provide a type for the constant". The help message also
|
||||
included a "recommended/suggested type" (`i32`) but it was not applied.
|
||||
|
||||
Hence, one of the difference between an immutable variable and a constant in
|
||||
Rust is that constants **need** type annotation. Type inferencing is **not**
|
||||
applicable to constants.
|
||||
|
||||
## Scope of declaration
|
||||
|
||||
Another point of difference between an immutable variable and a constant in
|
||||
Rust is its scope of declaration.
|
||||
|
||||
Constants can be declared globally (before/outside the `main` function).
|
||||
Variables, immutable or otherwise, cannot be declared globally.
|
||||
|
||||
Let's see this with an example.
|
||||
|
||||
Filename: const_example.rs
|
||||
|
||||
```rust
|
||||
const MY_CONST:i32 = -128;
|
||||
let my_var: i32 = -128;
|
||||
|
||||
fn main() {
|
||||
println!("{my_var} {MY_CONST}");
|
||||
}
|
||||
```
|
||||
|
||||
As you can see here, I have mostly the same code as above, but I have moved
|
||||
both, the variable and the constant declaration, in the global scope.
|
||||
|
||||
'tis compile time!
|
||||
|
||||
```bash
|
||||
$ rustc const_example.rs
|
||||
error: expected item, found keyword `let`
|
||||
--> const_example.rs:2:1
|
||||
|
|
||||
2 | let my_var: i32 = -128;
|
||||
| ^^^ expected item
|
||||
|
||||
error: aborting due to previous error
|
||||
```
|
||||
|
||||
An error :(
|
||||
|
||||
The way I wrote the code should give you a hint. We have an error on the
|
||||
2<sup>nd</sup> line. Our constant is declared on the 1<sup>st</sup> line.
|
||||
|
||||
This means, `rustc` did not see any problems with a constant in the global
|
||||
scope. But it does have a problem with our immutable variable if it is
|
||||
declared in the global scope.
|
||||
|
||||
## Assignable values
|
||||
|
||||
Another major difference between variables (immutable or otherwise) and
|
||||
constants in Rust is that a constant **cannot** have a value that can be
|
||||
calculated **only at run-time**.
|
||||
|
||||
What do I mean by this?
|
||||
|
||||
Take a look at the following code:
|
||||
|
||||
Filename: const_example.rs
|
||||
|
||||
```rust
|
||||
cat const_example.rs
|
||||
fn main() {
|
||||
let pi: f32 = 3.14;
|
||||
const PI_TIMES_TWO: f32 = pi * 2;
|
||||
}
|
||||
```
|
||||
|
||||
In this code, I am declaring an immutable variable (`pi`) and assigning it the
|
||||
value of "3.14". Next, I declare a constant, with the same type as `pi`,
|
||||
and I assign it the value of `pi * 2`.
|
||||
|
||||
Shall we compile?
|
||||
|
||||
```bash
|
||||
$ rustc const_example.rs
|
||||
error[E0435]: attempt to use a non-constant value in a constant
|
||||
--> const_example.rs:3:31
|
||||
|
|
||||
3 | const PI_TIMES_TWO: f32 = pi * 2;
|
||||
| ------------------ ^^ non-constant value
|
||||
| |
|
||||
| help: consider using `let` instead of `const`: `let PI_TIMES_TWO`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0435`.
|
||||
```
|
||||
|
||||
As you can see, even though `pi` is an immutable variable, we get this error.
|
||||
This is because `PI_TIMES_TWO` is dependent on the value stored in `pi`
|
||||
to determine its own value. This is problematic because the values of
|
||||
variables are **not** evaluated at compile-time.
|
||||
|
||||
The value assigned to a constant **must not** be calculated/evaluated at
|
||||
_run-time_.
|
||||
|
||||
## Compile-time vs Run-time
|
||||
|
||||
As I just proved, constants can not be assigned a value that will be
|
||||
calculated at run-time. That must raise a question if the core reason for the
|
||||
existence of immutable variables and constants must be related to the
|
||||
differences in run-time and compile-time.
|
||||
|
||||
While I am **not** someone who has contributed to the design of the Rust
|
||||
language, I am inclined to assume that this might be the reason.
|
||||
|
||||
You can use the value assigned to a constant during compile-time, to make
|
||||
decisions _while_ the code is being compiled. This can not be done using
|
||||
variables, immutable or otherwise.
|
||||
|
||||
Let me demonstrate this using an example.
|
||||
|
||||
Filename: const_example.rs
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let arr_len_var: usize = 5;
|
||||
const ARR_LEN_CONST: usize = 5;
|
||||
|
||||
let arr_from_const: [i32; ARR_LEN_CONST];
|
||||
let arr_from_var: [i32; arr_len_var];
|
||||
}
|
||||
```
|
||||
|
||||
In this example, I am doing the following:
|
||||
|
||||
1. Declare an immutable variable with the value "5".
|
||||
2. Declare a constant with the value "5".
|
||||
3. Create an empty array, using the value of an immutable variable as the
|
||||
"array size/length".
|
||||
4. Create another empty array, using the value of a constant as the "array
|
||||
size/length"
|
||||
|
||||
If, the jibberish that I just wrote above is correct, we should expect a
|
||||
compilation error on the 6<sup>th</sup> line.
|
||||
|
||||
```bash
|
||||
$ rustc const_example.rs
|
||||
error[E0435]: attempt to use a non-constant value in a constant
|
||||
--> const_example.rs:6:29
|
||||
|
|
||||
2 | let arr_len_var: usize = 5;
|
||||
| --------------- help: consider using `const` instead of `let`: `const arr_len_var`
|
||||
...
|
||||
6 | let arr_from_var: [i32; arr_len_var];
|
||||
| ^^^^^^^^^^^ non-constant value
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0435`.
|
||||
```
|
||||
|
||||
As expected.
|
||||
|
||||
`rustc` has 2 messages for us. The first message--after looking at the
|
||||
6<sup>th</sup> line--is a suggestion for us; to change `arr_len_var` from
|
||||
a variable to a constant.
|
||||
|
||||
The second message is an error message. It is complaining that the value
|
||||
which determines the length of an array, is a "non-constant value".
|
||||
|
||||
"But I thought the values of immutable variables could never change?! Does
|
||||
that not equate to a _non-constant value_?"
|
||||
|
||||
You are correct, but this is something different. You see--this is where I am
|
||||
applying my knowledge of what I learnt about compiler design from my
|
||||
college--constants are also _evaluated_ at compile-time.
|
||||
|
||||
This means, the following line -
|
||||
|
||||
```rust
|
||||
const PI: f32 = 3.14;
|
||||
println!("{PI}");
|
||||
```
|
||||
|
||||
gets replaced with the following in the first few passes of the Rust compiler.
|
||||
|
||||
```rust
|
||||
const PI: f32 = 3.14;
|
||||
println!("3.14");
|
||||
```
|
||||
|
||||
The constant got evaluated (expanded), at compile-time. This will not be be
|
||||
the case for a variable, immutable or otherwise.
|
||||
|
||||
This is also what happens when we use a constant to determine the length/size
|
||||
of an array.
|
||||
|
||||
## Shadows
|
||||
|
||||
You might know about shadowing in Rust. It refers to the act of referring
|
||||
to a different storage/address using the same name.
|
||||
|
||||
Below is an example of shadowing:
|
||||
|
||||
```rust
|
||||
let five = 5;
|
||||
let five = 6;
|
||||
```
|
||||
|
||||
Here, on the first line, we are declaring an immutable variable `five`. It
|
||||
assigned the value "5". In the immediate next line, we declare the variable
|
||||
`five` again. This time, we assign it "6".
|
||||
|
||||
What this does is, when `five` was first declared and assigned the value "5",
|
||||
it was given a memory address to store that "5" which we assigned to it.
|
||||
Assume this memory address to be `0x01`.
|
||||
|
||||
Then, when we declared `five` again; this time with a different value, "6";
|
||||
a different memory address was given to our variable `five`. This, new memory
|
||||
address stored the value "6". Assume this memory address to be `0x02`.
|
||||
|
||||
Now, the older memory address (`0x01`) is not overwritten with "6", instead of
|
||||
"5". It is still kept--maybe because this shadow was a local change and we
|
||||
will need the previous value again? who knows--intact. But now, when we ask,
|
||||
"Hey `five`, what is your assigned value?", it will check the memory location
|
||||
`0x02` and give us a value from there; which is "6".
|
||||
|
||||
This isn't possible for constants.
|
||||
|
||||
- You can not shadow a constant with a constant (of any type).
|
||||
- You can not shadow a constant with a variable (of any type).
|
||||
- You can not shadow a variable with a constant (of any type).
|
||||
|
||||
## Minor nit-picks
|
||||
|
||||
A few minor differences between a constant and an immutable variable are as
|
||||
follows:
|
||||
|
||||
- Variables are immutable by default, but they can also be mutable, if
|
||||
asked nicely. On the contrary, constants are _always_ immutable. (You cannot
|
||||
use the keyword `mut` next to the `const` keyword.)
|
||||
- To declare a constant, we use the `const` keyword, but to declare an
|
||||
immutable variable, we use the `let` keyword. A variable can be made
|
||||
immutable if, at the time of declaration, the `mut` keyword is used alongside
|
||||
the `let` keyword.
|
||||
|
||||
## Conclusion
|
||||
|
||||
The intelligent mind who were designing the Rust language were obviously not
|
||||
out of their minds when they created variables that default to immutability
|
||||
when constants would also exist.
|
||||
|
||||
To recap, constants need type annotations, but they can be declared in the
|
||||
global scope; values assigned to constants cannot be something that is
|
||||
calculated at run-time and they can not be shadowed.
|
|
@ -0,0 +1,83 @@
|
|||
+++
|
||||
draft = false
|
||||
date = 2022-10-09T10:30:00+05:30
|
||||
slug = "convert-mutable-var-to-immutable-rs.md"
|
||||
title = "Convert a mutable variable to immutable in Rust"
|
||||
description = "Fore_shadowing_"
|
||||
tags = [ "rust", "educational" ]
|
||||
+++
|
||||
|
||||
The immutability of Rust's variables is a curse and a boon. It is a life saver
|
||||
when you are dealing with multi-threaded code. A curse when you want to modify
|
||||
the value.
|
||||
|
||||
So what do you do now? You add a `mut` after the `let` and make it mutable.
|
||||
Some time down the line (haha, get it?), you realize that you need the
|
||||
immutability. How do you turn a mutable variable into an immutable variable?
|
||||
|
||||
## Shadow it
|
||||
|
||||
Most of the times, the solution you are looking for is to shadow the mutable
|
||||
variable with the immutable variable.
|
||||
|
||||
Take the following code snippet for example:
|
||||
|
||||
File: test.rs
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let mut x = 1;
|
||||
x = x + 1;
|
||||
println!("{x}");
|
||||
let x = x;
|
||||
x = x + 3;
|
||||
}
|
||||
```
|
||||
|
||||
And, compiling...
|
||||
|
||||
```bash
|
||||
$ rustc test.rs
|
||||
error[E0384]: cannot assign twice to immutable variable `x`
|
||||
--> test.rs:6:5
|
||||
|
|
||||
5 | let x = x;
|
||||
| -
|
||||
| |
|
||||
| first assignment to `x`
|
||||
| help: consider making this binding mutable: `mut x`
|
||||
6 | x = x + 3;
|
||||
| ^^^^^^^^^ cannot assign twice to immutable variable
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0384`.
|
||||
```
|
||||
|
||||
(The unused variable warning from `rustc` is snipped.)
|
||||
|
||||
`rustc` is complaining that on line 6, column 5 of "test.rs", it is referring
|
||||
to `x` as immutable.
|
||||
|
||||
But didn't we declare `x` as `mut` on line 2? Yes, we did.
|
||||
|
||||
Now, check the 5<sup>th</sup> line. There I assigned `x` to itself, making use
|
||||
of Rust's _shadowing_ feature. The name `x` is now pointing to a different
|
||||
storage that is immutable, but has the value of `&mut x` assigned to it.
|
||||
|
||||
{{< notice info >}}
|
||||
Please note that in the above explanation, I only use "`&mut x`" to demonstrate
|
||||
that the _value_ of mutable variable `x` gets copied. This does not mean that
|
||||
the new `x` will point to `&mut x`.
|
||||
{{< /notice >}}
|
||||
|
||||
## Conclusion
|
||||
|
||||
To turn an existing mutable variable into an immutable variable (that Rust
|
||||
provides a thread-safe guarantee for), you can shadow the existing mutable
|
||||
variable with a new immutable variable.
|
||||
|
||||
```rust
|
||||
let mut foo; // foo is mutable
|
||||
let foo = foo; // foo shadows [mutable foo] and is now immutable
|
||||
```
|
|
@ -0,0 +1,322 @@
|
|||
+++
|
||||
draft = false
|
||||
date = 2023-02-22T12:36:00+05:30
|
||||
slug = "visionfive-2-initial-review.md"
|
||||
title = "Hands on and initial review of the VisionFive 2"
|
||||
description = "So RISC-V is a thing, huh."
|
||||
tags = [ "riscv" ]
|
||||
+++
|
||||
|
||||
Since a long time, RISC-V was in my news feed. I have no idea about RISC-V
|
||||
other than that it is an open source ISA (not implementation). That made me
|
||||
curious and I wanted to get something RISC-y to understand the hype first-hand.
|
||||
|
||||
In August of 2022, I came across the Kickstarter announcement from StarFive
|
||||
([here](https://www.kickstarter.com/projects/starfive/visionfive-2)) about the
|
||||
VisionFive 2. Following hardware features peaked my interest the *most*:
|
||||
|
||||
- Dual Gigabit Ethernet ports (some _Super early bird_ models have 1x 1000M
|
||||
and 1x 100M ports)
|
||||
- Presence of QSPI flash for `u-boot`
|
||||
- The SBC was available with 8 GB of RAM (that is the minimum for me)
|
||||
|
||||
The VisionFive 2 also has one M.2 slot for an NVMe (2280) drive, but it doesn't
|
||||
interest me as much. Particularly because it only has the bandwidth of **1x
|
||||
PCIe 2.0** lane. Also because I can not afford a _"good"_ NVMe drive at the
|
||||
moment.
|
||||
|
||||
I don't want to put in a cheap NVMe drive because the cheap ones usually omit
|
||||
DRAM. That isn't a problem on a moderately fast computer. But on a computer
|
||||
whose CPU (SiFive U74) [allegedly] performs similarly to an ARM A55 core, said
|
||||
latency hit is more noticeable.
|
||||
|
||||
{{< notice info >}}
|
||||
On the note of NVMe, the one thing missing from the hardware perspective is
|
||||
the screw to hold the NVMe drive itself.
|
||||
{{</ notice >}}
|
||||
|
||||
|
||||
## Initial software setup
|
||||
|
||||
_For now, one is expected to form their opinions on hardware performance based
|
||||
on the [Debian image provided the vendor](https://debian.starfivetech.com/)._
|
||||
|
||||
**Before you flash the image provided by the vendor, the board firmware
|
||||
_needs_ to be updated. Please do that first.**
|
||||
|
||||
|
||||
### Updating firmware
|
||||
|
||||
The firmware can be easily updated by following these steps:
|
||||
|
||||
1. Download 3 assets from VisionFive 2's
|
||||
[latest SDK release](https://github.com/starfive-tech/VisionFive2/releases/latest):
|
||||
`sdcard.img`, `u-boot-spl.bin.normal.out`, `visionfive2_fw_payload.img`
|
||||
2. `sudo dd if=sdcard.img conv=sync status=progress bs=1M of=/dev/<YOUR_DEV_HERE>`
|
||||
3. `mkdir temp-dir`
|
||||
4. `sudo mount /dev/<YOUR_DEV_HERE>4 temp-dir`
|
||||
5. `sudo cp u-boot-spl.bin.normal.out visionfive2_fw_payload.img temp-dir/root/`
|
||||
6. `sudo umount /dev/<YOUR_DEV_HERE>4`
|
||||
7. Eject the SD Card from your computer, insert it in VisionFive 2 and power
|
||||
it up. The green LED should start blinking.
|
||||
8. Plug the network cable on the Ethernet port that is next to the HDMI port.
|
||||
9. `ssh root@<IP_ADDRESS>` (passwd: `starfive`)
|
||||
10. Run the command `cat /proc/mtd` and you should have the following output:
|
||||
```
|
||||
dev: size erasesize name
|
||||
mtd0: 00020000 00001000 "spl"
|
||||
mtd1: 00300000 00001000 "uboot"
|
||||
mtd2: 00100000 00001000 "data"
|
||||
```
|
||||
11. If the partition information is correct, update the `spl` and `uboot`
|
||||
firmware using the following commands:
|
||||
```
|
||||
flashcp -v u-boot-spl.bin.normal.out /dev/mtd0
|
||||
flashcp -v visionfive2_fw_payload.img /dev/mtd1
|
||||
```
|
||||
|
||||
Done! Now `systemctl poweroff` and flash the vendor's Debian image to your SD
|
||||
card and boot it up.
|
||||
|
||||
|
||||
### Setup with vendor's image
|
||||
|
||||
Although the SD Card image provided by the vendor worked fine for me, people
|
||||
have reported two major things missing from their kernel. The modules for
|
||||
BTRFS are not built and IPv6 isn't supported either. We will compile the
|
||||
kernel soon, but there are other problems with the image that need to be
|
||||
tackled first.
|
||||
|
||||
|
||||
#### Manually expand the root partition
|
||||
|
||||
Unlike most images available for the Raspberry Pi, this image does not
|
||||
automatically expand the root partition. So first, resize your `/` partition
|
||||
using `parted`:
|
||||
|
||||
```bash
|
||||
root@starfive:~# parted /dev/mmcblk1
|
||||
GNU Parted 3.5
|
||||
Using /dev/mmcblk1
|
||||
Welcome to GNU Parted! Type 'help' to view a list of commands.
|
||||
(parted) resizepart 3 100%
|
||||
Warning: Partition /dev/mmcblk1p3 is being used. Are you sure you want to
|
||||
continue?
|
||||
Yes/No? Y
|
||||
(parted) q
|
||||
Information: You may need to update /etc/fstab.
|
||||
```
|
||||
|
||||
Resize the filesystem using `resize2fs`:
|
||||
|
||||
```bash
|
||||
root@starfive:~# resize2fs /dev/mmcblk1p3
|
||||
resize2fs 1.46.5 (30-Dec-2021)
|
||||
Filesystem at /d[ 192.744328] EXT4-fs (mmcblk1p3): resizing filesystem from 1280507 to
|
||||
31186944 blocks
|
||||
ev/mmcblk1p3 is mounted on /; on-line resizing required
|
||||
old_desc_blocks = 1, new_desc_blocks = 15
|
||||
[ 196.934822] EXT4-fs (mmcblk1p3): resized filesystem to 31186944
|
||||
The filesystem on /dev/mmcblk1p3 is now 31186944 (4k) blocks long.
|
||||
```
|
||||
|
||||
Verify the change using the 'df' command. Best reboot now to prevent any
|
||||
soft-errors.
|
||||
|
||||
|
||||
#### Update Debian keyring
|
||||
|
||||
To run `apt update` without any errors, the Debian keyring needs to be updated.
|
||||
This can be easily remedied by manually downloading the `.deb` file for the
|
||||
Debian keyring package from [here](https://packages.debian.org/sid/all/debian-ports-archive-keyring/download) (don't worry, it is architecture agnostic).
|
||||
|
||||
Choose your nearest mirror and download it. Then, like any other package, do a
|
||||
`dpkg -i debian-ports-archive-keyring*.deb`.
|
||||
|
||||
Now, you can `apt update` flawlessly :wink:
|
||||
|
||||
|
||||
#### OPTIONAL: Update APT sources
|
||||
|
||||
**Please note that there is a reason why the APT sources point to a snapshot.
|
||||
That is because it is a "known good" state of the packages. I am not
|
||||
accountable if your system breaks. I am not a sysadmin.**
|
||||
|
||||
But this is what I have done to make sure that I stay up-to-date with any
|
||||
developments in the ecosystem.
|
||||
|
||||
```bash
|
||||
root@starfive:~# cat <<EOF > /etc/apt/sources.list
|
||||
deb http://deb.debian.org/debian-ports sid main
|
||||
deb http://deb.debian.org/debian-ports unreleased main
|
||||
deb-src http://deb.debian.org/debian sid main
|
||||
EOF
|
||||
|
||||
root@starfive:~# apt update
|
||||
```
|
||||
|
||||
|
||||
#### MISC
|
||||
|
||||
Better do some housekeeping now...
|
||||
|
||||
```bash
|
||||
root@starfive:~# passwd # use a strong password
|
||||
root@starfive:~# userdel -r user
|
||||
root@starfive:~# useradd -m -G <GROUPS> -s /bin/bash <USER_NAME>
|
||||
root@starfive:~# visudo # I enabled 'NOPASSWD' for my user
|
||||
```
|
||||
|
||||
|
||||
## Software status of the VisionFive 2
|
||||
|
||||
Other than the minor inconvenience of updating the board firmware, setting
|
||||
up the vendor's Debian image, everything else seems to mostly work for me.
|
||||
|
||||
As new as this SBC is, there already are 5 total offerings for compatible
|
||||
images.
|
||||
|
||||
1. The vendor provided [Debian Sid image](https://debian.starfivetech.com)
|
||||
2. An "experimental" [Debian Sid image](https://forum.rvspace.org/t/experimental-debian-sid-image/1517)
|
||||
3. An [Arch Linux image](https://forum.rvspace.org/t/arch-linux-image-for-visionfive-2/1459)
|
||||
4. [Build your own Debian images](https://forum.rvspace.org/t/build-your-own-debain-images/1881)
|
||||
5. A community image of [OpenSUSE Tumbleweed](https://en.opensuse.org/HCL:VisionFive2)
|
||||
|
||||
The OpenSUSE image, at the time of writing this, _seems_ to be using the latest
|
||||
Linux kernel that is available (6.2-rc8) and adding StarFive's patches that are
|
||||
for the VisionFive 2. Every other image listed above is using the [StarFive 5.15.0 kernel](https://github.com/starfive-tech/linux/tree/JH7110_VisionFive2_devel).
|
||||
|
||||
I have tested images #1, #2 and #3 and I can confirm that the following things
|
||||
are working as **_I_** expected:
|
||||
|
||||
- The hardware reset switch works
|
||||
- The GPIO pins work[^1] (along with UART)
|
||||
- Both of the Gigabit Ethernet ports on my board work at the max speed[^2]
|
||||
- All 4 of the front USB 3.0 ports work (didn’t test speed)
|
||||
- HDMI port works[^3]
|
||||
|
||||
[^1]: I haven't tested _all the pins_. I used pins 4, 6, 8, 10, and 14. These
|
||||
work without any issue so I assume all 40 pins work as intended.
|
||||
|
||||
[^2]: You can get 948-ish MBit/s of throughput from each port, which lines up
|
||||
with real world performance of other Gigabit NICs. But, sending traffic in from
|
||||
one port and receiving it from another port is limited to 500-ish MBit/s of
|
||||
throughput due to the way the PHYs are wired ("multiplexed").
|
||||
|
||||
[^3]: I don't have a use for display out (on the VF2). I only plugged it in and
|
||||
booted the SBC up. For what it is worth, the boot logs show up when connected
|
||||
to my 2160p monitor. **No further graphics testing was performed**, since that
|
||||
is not my primary aim with this SBC.
|
||||
|
||||
{{< notice info >}}
|
||||
No offence, but I won't be trying out the OpenSUSE image anytime soon. I
|
||||
despise PascalCase in a _package manager_ of all things. Firefox is called
|
||||
`MozillaFirefox`. **WHY?!**
|
||||
{{</ notice >}}
|
||||
|
||||
I am daily driving cwt's Arch Linux image. The kernel in this image is the
|
||||
vendor's 5.15.0 Linux kernel. This kernel was compiled to enable the support
|
||||
for IPv6 and BTRFS.
|
||||
|
||||
The only modification that I had to perform was to add the following line to
|
||||
the `/etc/pacman.conf` file:
|
||||
|
||||
```
|
||||
IgnorePkg = linux-api-headers
|
||||
```
|
||||
|
||||
I had to do this because the Linux kernel installed is the vendor's 5.15.0
|
||||
kernel and the version of the `linux-api-headers` package is `6.1.9`.
|
||||
|
||||
{{< notice warning >}}
|
||||
This image has an issue with **_rebooting_**. When you try to reboot, the board
|
||||
just shuts down. Though, I am looking into fixing this issue.
|
||||
{{</ notice >}}
|
||||
|
||||
---
|
||||
|
||||
People on the RVSpace forum reported that the XU4 fan by Hardkernel fits on
|
||||
their board ([buy here](https://www.hardkernel.com/shop/cooling-fan-xu4-blue/)).
|
||||
So I ordered one. **The fan header on the fan and on the board are
|
||||
incompatible.** So I removed the connector from the fan and soldered the wires
|
||||
to the jumper wires and inserted it into my GPIO pins. It works now :smile:
|
||||
|
||||
With the fan on, and compiling the StarFive's Linux tree for the VisionFive 2
|
||||
using `make all -j4`, I never saw the temps go above 42 C. This is quite an
|
||||
achievement because I am in India (it's very hot here) and in a room that is
|
||||
without an AC.
|
||||
|
||||
![btop running on VisionFive 2](/images/visionfive_2_review_btop_screenshot.png)
|
||||
|
||||
The compilation of StarFive's VisionFive 2 Linux kernel tree using the
|
||||
following command completed in 2 hours and 15 minutes. That's _really quick_
|
||||
for such a machine!
|
||||
|
||||
```bash
|
||||
make clean
|
||||
make mrproper
|
||||
make starfive_visionfive2_defconfig
|
||||
ARCH=riscv CFLAGS="-march=rv64imafdc_zicsr_zba_zbb -mcpu=sifive-u74 -mtune=sifive-7-series -O2 -pipe" make all -j4
|
||||
```
|
||||
|
||||
{{< notice warning >}}
|
||||
You will need to patch the file `arch/riscv/Makefile` to compile the kernel
|
||||
successfully. Here is the [patch](https://github.com/hexdump0815/linux-starfive-visionfive2-kernel/blob/main/misc.vf2/patches/make-newer-binutils-work.patch).
|
||||
{{</ notice >}}
|
||||
|
||||
|
||||
## My thoughts so far
|
||||
|
||||
Since the RISC-V ISA is pretty new, there are still some packages that have
|
||||
not been ported yet. As a Neovim user, the biggest hit I received was when
|
||||
I noticed that RISC-V support from **upstream** LuaJIT is missing. Though, that
|
||||
is [being worked on](https://github.com/LuaJIT/LuaJIT/issues/628).
|
||||
|
||||
The Arch Linux maintainer [felixonmars](https://github.com/felixonmars)--who is
|
||||
also porting a lot of packages to RISC-V--has made the Neovim package depend on
|
||||
`lua51` instead of `luajit` ([relevant git commit](https://github.com/felixonmars/archriscv-packages/commit/7b7f04a28cbe6a04f663a14c914ba4d63b081ede)).
|
||||
Neovim wouldn't even install on Debian due to the missing dependency of LuaJIT,
|
||||
but on Arch Linux, I can at least install and use Neovim, albeit without the
|
||||
traditional Lua support.
|
||||
|
||||
I have installed the packages that I have listed below. I haven't tested _all_
|
||||
of them, but of what I did test, they work as I expect them to do on my
|
||||
Raspbery Pi or on my x86 computer.
|
||||
|
||||
```
|
||||
android-tools arch-install-scripts aria2 bandwhich base base-devel bat btop cargo-audit cargo-auditable cargo-bloat cargo-depgraph cargo-outdated cargo-spellcheck cargo-watch choose chrony cifs-utils dhcpcd dog dua-cli dust exa fd figlet firewalld gcc git git-lfs groff hd-idle hdparm htop iotop iperf iperf3 linux-firmware lsb-release lsof man-db man-pages mkinitcpio mlocate namcap nano neofetch neovim networkmanager nfs-utils nload nvme-cli opendoas openssh parted paru ripgrep rsync rustup skim smartmontools sudo tealdeer tmux tre tree unrar unzip usbutils wget which wireguard-tools wireless-regdb wol xmlto yt-dlp zsh zsh-autosuggestions zsh-completions zsh-syntax-highlighting
|
||||
```
|
||||
|
||||
{{< notice note >}}
|
||||
**My current workflow does not involve making use of the iGPU in any capacity
|
||||
whatsoever.** Hence I will not make any _personal comments_ on it yet. But,
|
||||
people have reported some issues with the display output when the SBC is
|
||||
connected to a 2160p monitor. On the first day, when I couldn't find my UART
|
||||
cable, I had to rely on the display output of the board. So I connected the
|
||||
HDMI port to my **2160p** monitor, and, for what it is worth, it at least
|
||||
showed me the boot logs. Though, I did see a black screen instead of the login
|
||||
manager. I haven't done any further testing in this area since.
|
||||
{{< /notice >}}
|
||||
|
||||
---
|
||||
|
||||
The state of hardware on the SBC seems good enough for my use: as a development
|
||||
machine and to build software for RISC-V.
|
||||
|
||||
StarFive is [upstreaming](https://rvspace.org/en/project/JH7110_Upstream_Plan)
|
||||
software components. The only thing StarFive is not upstreaming is the GPU
|
||||
drivers. That commitment is the responsibility of Imagination, as per their
|
||||
[post](https://developer.imaginationtech.com/open-source-gpu-driver/).
|
||||
|
||||
As of now, I have no gripes as the vendor is not withholding any patches; of
|
||||
what is available, works, the vendor is making an effort to upstream as much as
|
||||
they can.
|
||||
|
||||
To repeat myself for the _n<sup>th</sup>_ time, of what packages are available,
|
||||
they work as one might expect from a PC/laptop. Having such a low cost device
|
||||
with minor issues, like the display output not working as intended at 2160p
|
||||
resolution, (**in the context of a developer/porting machine**) is a _STEAL_!
|
||||
|
||||
I am very happy with it and I will be using this to learn Linux kernel
|
||||
development (using :crab:) and help port more ARM64/AMD64 software to it. Let
|
||||
me know if you want Rocky Linux on this! :wink:
|
|
@ -0,0 +1,74 @@
|
|||
+++
|
||||
draft = true
|
||||
date = 2002-03-01T00:00:00+05:30
|
||||
slug = "poorly-thought-out-title.md"
|
||||
title = "Poorly thought out title"
|
||||
description = "Shorter than a 140 char tweet."
|
||||
tags = [ ]
|
||||
+++
|
||||
|
||||
## Lorem Ipsum
|
||||
|
||||
### What is Lorem Ipsum?
|
||||
|
||||
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
|
||||
|
||||
### Where does it come from?
|
||||
|
||||
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.
|
||||
|
||||
#### Origins
|
||||
|
||||
The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from "de Finibus Bonorum et Malorum" by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
|
||||
|
||||
### Why do we use it?
|
||||
|
||||
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
|
||||
|
||||
### Where can I get some?
|
||||
|
||||
There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.<br>
|
||||
- <cite>Taken from [lipsum.com](https://www.lipsum.com/)[^1]</cite>
|
||||
|
||||
[^1]: [lipsum.com](https://www.lipsum.com/)
|
||||
|
||||
{{< notice note >}} One note here. {{< /notice >}}
|
||||
|
||||
{{< notice tip >}} I'm giving a tip about something. {{< /notice >}}
|
||||
|
||||
{{< notice example >}} This is an example. {{< /notice >}}
|
||||
|
||||
{{< notice question >}} Is this a question? {{< /notice >}}
|
||||
|
||||
{{< notice info >}} Notice that this box contain information. {{< /notice >}}
|
||||
|
||||
{{< notice warning >}} This is the last warning! {{< /notice >}}
|
||||
|
||||
{{< notice error >}} There is an error in your code. {{< /notice >}}
|
||||
|
||||
{{< youtube dQw4w9WgXcQ>}}
|
||||
|
||||
{{< twitter_simple 1562083939509886983 >}}
|
||||
|
||||
```bash
|
||||
echo 'Hello world'
|
||||
```
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("Hello world\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
println!("Hello world");
|
||||
}
|
||||
```
|
||||
|
||||
```python
|
||||
print("Hello world")
|
||||
```
|
|
@ -0,0 +1,6 @@
|
|||
+++
|
||||
title = "README.md"
|
||||
draft = false
|
||||
+++
|
||||
|
||||
Documentation about hobby projects is always empty :(
|
89
hugo.toml
89
hugo.toml
|
@ -1,3 +1,86 @@
|
|||
baseURL = 'https://example.org/'
|
||||
languageCode = 'en-us'
|
||||
title = 'My New Hugo Site'
|
||||
baseURL = "https://blog.thefossguy.com/"
|
||||
title = "Pratham Patel's blog"
|
||||
theme = "hugo-coder"
|
||||
|
||||
languageCode = "en"
|
||||
defaultContentLanguage = "en"
|
||||
enableEmoji = true
|
||||
|
||||
paginate = 20
|
||||
|
||||
|
||||
[markup]
|
||||
[markup.highlight]
|
||||
noClasses = false
|
||||
|
||||
[params]
|
||||
author = "Pratham Patel"
|
||||
description = "Pratham Patel's blog"
|
||||
gravatar = "thefirst1322@gmail.com"
|
||||
info = "haccerman"
|
||||
|
||||
# https://www.iso.org/iso-8601-date-and-time-format.html
|
||||
dateFormat = "2006-01-02"
|
||||
|
||||
# always left to right text, nothing barbaric here
|
||||
rtl = false
|
||||
|
||||
colorScheme = "dark"
|
||||
hideColorSchemeToggle = true
|
||||
|
||||
maxSeeAlsoItems = 10
|
||||
|
||||
[[params.social]] # TODO: a page with link to my contributions to kernel
|
||||
name = "Linux Kernel"
|
||||
icon = "fa fa-2x fa-linux"
|
||||
weight = 2
|
||||
url = "https://blog.thefossguy.com"
|
||||
|
||||
[[params.social]]
|
||||
name = "Gitea"
|
||||
icon = "fa fa-2x fa-git"
|
||||
weight = 2
|
||||
url = "https://git.thefossguy.com/thefossguy"
|
||||
|
||||
[[params.social]]
|
||||
name = "GitLab"
|
||||
icon = "fa fa-2x fa-gitlab"
|
||||
weight = 3
|
||||
url = "https://gitlab.com/thefossguy"
|
||||
|
||||
[[params.social]]
|
||||
name = "GitHub"
|
||||
icon = "fa fa-2x fa-github"
|
||||
weight = 4
|
||||
url = "https://github.com/thefossguy"
|
||||
|
||||
[[params.social]]
|
||||
name = "Twitter"
|
||||
icon = "fa fa-2x fa-twitter"
|
||||
weight = 5
|
||||
url = "https://nitter.it/thefossguy"
|
||||
|
||||
[[params.social]]
|
||||
name = "RSS"
|
||||
icon = "fa fa-2x fa-rss"
|
||||
weight = 6
|
||||
url = "https://blog.thefossguy.com/index.xml"
|
||||
rel = "alternate"
|
||||
type = "application/rss+xml"
|
||||
|
||||
[[params.social]]
|
||||
name = "Donate?"
|
||||
icon = "fa fa-2x fa-heart-o"
|
||||
weight = 7
|
||||
url = "https://github.com/sponsors/thefossguy"
|
||||
|
||||
[menu]
|
||||
[[menu.main]]
|
||||
name = "Blog"
|
||||
weight = 1
|
||||
url = "posts/"
|
||||
|
||||
[[menu.main]]
|
||||
name = "README"
|
||||
weight = 2
|
||||
url = "readme"
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 700 KiB |
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
Subproject commit c4665043f9957b7ed9b5a07c7074bb520563a5ba
|
Loading…
Reference in New Issue