Loosing some bytes on USART transmission with STM32L1XX - c

I'm facing a problem with the communication between my computer and my board stm32L152RE.
I try to send a string of 1024 bytes and write it on my flash board.
For that, i send packets of 32 bytes.
The algorithm is simple :
I erase my memory with enought space to write my string of 1024
I receive 32 bytes in a string buffer
I write them on the flash
I do that until i receive 1024 bytes and the I stop.
The problem is , when i print what i have in memory step by step, I only receive 16 bytes and i don't know why
Here's my code, maybe it will help understand my program
/*
* bootloader.c
*
* Created on: 9 juin 2015
* Author: tgloaguen
*/
#include "usart.h"
#include "stm32l1xx_flash.h"
#define WRITE_START_ADDR 0x08000000
#define WRITE_END_ADDR 0x08000FFF
#define FLASH_PAGE_SIZE ((uint16_t)0x100) //If a page is 256 bits
#define MY_BL_FUNCTIONS __attribute__((section(".bootsection")))
void BootLoader(void) MY_BL_FUNCTIONS;
FLASH_Status Flash_Write ( uint32_t StartAddress, uint8_t *p, uint32_t Size ) MY_BL_FUNCTIONS;
uint8_t Flash_Erase() MY_BL_FUNCTIONS;
void Receive_Data(char * buffer,int size)MY_BL_FUNCTIONS;
void Receive_Size(char * buffer, int *sizeData)MY_BL_FUNCTIONS;
void BootLoader(void) {
//clear all ITs
USART_ITConfig( USART1, USART_IT_RXNE, DISABLE );
//SendString("HELLO",USART2);
uint8_t status,i;
char buffer[33];
//en dur
uint16_t *adr = WRITE_START_ADDR;
uint16_t sizeBin = 1024,k = 0,k_hexa = 0x20;
//Receive size of BIN
// Receive_Size(buffer,&sizeBin);
Flash_Erase();
//if sizeBin ok
//receive frames
do
{
//receive 32 bytes
Receive_Data(buffer,32);
GPIO_ToggleBits(GPIOA, GPIO_Pin_5);
// //write a sector (1024k)
status = Flash_Write(adr , buffer, 0x20);
// on check si on ecrit bien au bon endroit
SendString("\r\n ", USART2);
// //increment cpt
k += 32;
adr = adr + k_hexa;
// //check CRC
// //TODO
//
} while (k < sizeBin);
SendString("nickel ", USART2);
}
void Receive_Size(char * buffer, int *sizeData) {
int i = 0;
do {
buffer[i] = Uart2ReadChar();
i++;
} while (buffer[i] != '\0');
*sizeData = (buffer[1] << 8) + buffer[0];
}
void Receive_Data(char * buffer,int size){
int i=0;
do{
buffer[i] = Uart2ReadChar();
i++;
}
while(i < size);
}
uint8_t Flash_Erase() {
uint32_t EraseCounter = 0x00, Address = 0x00;//Erase count, write address
uint32_t NbrOfPage = 0x00;//Recording to erase the pages
volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;/*FLASH complete erasure marks*/
/*Unlock FLASH*/
FLASH_Unlock();
/*Calculate the number of FLASH pages need to erase */
NbrOfPage = (WRITE_END_ADDR - WRITE_START_ADDR) / FLASH_PAGE_SIZE;
/* Remove all hang flags */
FLASH_ClearFlag ( FLASH_FLAG_EOP |
FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR |
FLASH_FLAG_SIZERR |
FLASH_FLAG_OPTVERR );
/* Erase the FLASH page*/
for(EraseCounter = 0; (EraseCounter <NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
{
FLASHStatus = FLASH_ErasePage(WRITE_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter));
}
FLASH_Lock ( );
return (uint8_t)FLASHStatus;
}
FLASH_Status Flash_Write ( uint32_t StartAddress, uint8_t *p, uint32_t Size )
{
uint32_t Address;
__IO FLASH_Status status = FLASH_COMPLETE;
Address = StartAddress;
/* Unlock the FLASH Program memory */
FLASH_Unlock ();
/* Clear all pending flags */
FLASH_ClearFlag ( FLASH_FLAG_EOP |
FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR |
FLASH_FLAG_SIZERR |
FLASH_FLAG_OPTVERR );
while ( Address < StartAddress + Size )
{
status = FLASH_FastProgramWord ( Address, *(uint32_t *)p );
//debug
SendChar('|',USART2);
SendChar(*p,USART2);
Address = Address + 4;
p = p + 4;
if ( status != FLASH_COMPLETE ) return status;
}
/* Lock the FLASH Program memory */
FLASH_Lock ( );
return status;
}

Related

Writing array to flash which is uint16_t. I am using a STM32L053 nucleo., get a hard fault error. How to convert uint16_t array to write to flash?

This is the how I'm trying to write to flash
Basically I pass my uint16_t array to a function called FLASH_WriteA which accepts the array, the destination array or the location and the length
void FLASH_WriteA(uint16_t * src, uint16_t * dest, uint16_t length_16)
{
uint32_t firstAddress= FLASH_GetFirstAddress((uint32_t)dest, PAGE_SIZE_BYTES); // gets the first address of that page
uint32_t offset = ((uint32_t)dest - seg) / 2; // offset is in words
HAL_FLASH_Unlock();
Flash_Erase_Page((uint16_t*)seg); // calls the page erase function
FLASH_Write_HAL((uint32_t *)&flashBuffer, (uint16_t*)seg, FLASH_TABLE_SIZE_BYTES); //FLASH_TABLE_SIZE_BYTES = 256 = size of array
HAL_FLASH_Lock();
}
HAL_StatusTypeDef Flash_Erase_Page(uint16_t* seg){//, uint16_t length){
//uint16_t pages = (length/page_size) + (int)((length % page_size) != 0);
uint32_t pages = 2; // page size for STM32L053 = 128 bytes
FLASH_EraseInitTypeDef EraseInitStruct;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.PageAddress = seg;
EraseInitStruct.NbPages = pages;
uint32_t PageError;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK) //Erase the Page Before a Write Operation
{
return HAL_ERROR;
}
}
void FLASH_Write_HAL(uint32_t *p_source, uint16_t* seg, uint16_t length)
{
uint32_t varToPass;
uint16_t wordcount=0;
int i;
for (i=0; i<length; i++){
varToPass = p_source[i] ;
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,seg+wordcount,varToPass);
wordcount += 4;
// if (wordcount>=256){
// break;
// }
}
}

Sound player can't read WAV file produced by my program, says missing header

I am coding a program that renders a wave type (sine, square, wavetooth, etc.) and writes it to a file. The problem is that sound player says the header is missing even though I wrote it. The data types are supposed to be written in little endian.
I tried re-writing the I/O functions multiple times in different ways to no avail. I tried filling the array with the data to be written with test data and even that doesn't work. There's something wrong when the file is written.
Main function:
int main (int argc, char** argv){
if (argc != 6){
printf("Error: expecting more arguments\n");
return -1;
}
//First argument: voice
int voice = atof(argv[1]);
//Second argument: frequency
float frequency = atof(argv[2]);
//Third argument: amplitude
float amplitude = atof(argv[3]);
//Fourth argument: numsample
int numsamples = atof(argv[4]);
//Fifth argument: output file name
char* filename = argv[5];
int16_t buffer[numsamples*2];
memset(buffer, 0.1, numsamples*2);
if (check_args(voice, frequency, amplitude) != 0) {
//Sine wave
if (voice == 0) {
//render_sine_wave_stero(buffer, numsamples, frequency, amplitude);
}
//If square wave
else if (voice == 1){
//render_square_wave_stereo(buffer, numsamples, frequency, amplitude);
}
//Sawtooth
else if (voice == 2) {
//render_sawtooth_wave_stero(buffer, numsamples, frequency, amplitude);
}
FILE *outputfile = fopen(filename, "wb+");
if (outputfile == NULL){
printf("Error: file failed to open");
return 1;
}
write_wave_header(outputfile, numsamples);
write_s16_buf(outputfile, buffer, numsamples*2);
fclose(outputfile);
printf("Finished\n");
Header writing function:
#define PI 3.14159265358979323846
#define SAMPLES_PER_SECOND 44100u
#define NUM_CHANNELS 2u
#define BITS_PER_SAMPLE 16u
void write_wave_header(FILE *out, unsigned num_samples) {
/*
* See: http://soundfile.sapp.org/doc/WaveFormat/
*/
uint32_t ChunkSize, Subchunk1Size, Subchunk2Size;
uint16_t NumChannels = NUM_CHANNELS;
uint32_t ByteRate = SAMPLES_PER_SECOND * NumChannels * (BITS_PER_SAMPLE/8u);
uint16_t BlockAlign = NumChannels * (BITS_PER_SAMPLE/8u);
/* Subchunk2Size is the total amount of sample data */
Subchunk2Size = num_samples * NumChannels * (BITS_PER_SAMPLE/8u);
Subchunk1Size = 16u;
ChunkSize = 4u + (8u + Subchunk1Size) + (8u + Subchunk2Size);
/* Write the RIFF chunk descriptor */
write_bytes(out, "RIFF", 4u);
write_u32(out, ChunkSize);
write_bytes(out, "WAVE", 4u);
/* Write the "fmt " sub-chunk */
write_bytes(out, "fmt ", 4u); /* Subchunk1ID */
write_u32(out, Subchunk1Size);
write_u16(out, 1u); /* PCM format */
write_u16(out, NumChannels);
write_u32(out, SAMPLES_PER_SECOND); /* SampleRate */
write_u32(out, ByteRate);
write_u16(out, BlockAlign);
write_u16(out, BITS_PER_SAMPLE);
/* Write the beginning of the "data" sub-chunk, but not the actual data */
write_bytes(out, "data", 4); /* Subchunk2ID */
write_u32(out, Subchunk2Size);
}
IO functions:
void write_byte(FILE* out, char val){
fwrite(&val, sizeof(char), 1, out);
}
void write_bytes(FILE* out, const char data[], unsigned n){
for (unsigned i=0; i<n; i++){
write_byte(out, data[n]);
}
}
void write_u16(FILE* out, uint16_t value){
char bytes[] = {0, 0};
//Lowest byte
bytes[0] = value & 0xFF;
//Biggest byte
bytes[1] = value>>8;
write_bytes(out, bytes, 2u);
//fwrite(&value, sizeof(uint16_t), 1, out);
}
void write_u32(FILE* out, uint32_t value){
uint16_t first = value & 0x0000FFFF;
uint16_t second = value >> 16;;
write_u16(out, first);
write_u16(out, second);
//fwrite(&value, sizeof(uint32_t), 1, out);
}
void write_s16(FILE* out, int16_t value){
uint16_t newV = (uint16_t)value;
write_u16(out, newV);
//fwrite(&value, sizeof(int16_t), 1, out);
}
void write_s16_buf(FILE* out, const int16_t buf[], unsigned n){
for (unsigned i=0; i<n; i++){
write_s16(out, buf[n]);
}
}
I expected the file produced by calling ./render_tone 1 100 0.1 44100 out.wav to be readable by a sound player but the out.wav results in an error saying the header is missing on read.
You have a typo (I assume) in your write_bytes() function:
void write_bytes(FILE* out, const char data[], unsigned n){
for (unsigned i=0; i<n; i++){
write_byte(out, data[n]);
}
}
you should use data[i] instead of data[n]. Right now if you call:
write_bytes(out, "RIFF", 4u);
it will write \0 character (NUL terminating the c-string) 4 times.

UDP Transfer - Implementing CRC-16 [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I'm a complete newbie in C and have an assignment that states I have to implement CRC-16 into a given UDP File Transfer solution. Given code is as follows:
#pragma comment(lib, "ws2_32.lib")
#include "stdafx.h"
#include <winsock2.h>
#include "ws2tcpip.h"
#include <stdio.h>
#define TARGET_IP "10.4.115.122"
//#define TARGET_IP "127.0.0.1"
#define BUFFERS_LEN 1024
#define SIZE_PACKET 10 // we can send up to 9 999 999 999 packets
#define HEADER_LEN (SIZE_PACKET + 5)
#define DATA_LEN (BUFFERS_LEN - HEADER_LEN)
//#define SENDER
#define END {getchar();return 0;}
#define RECEIVER
typedef struct Data
{
int size;
char *data;
}Data;
#ifdef SENDER
#define TARGET_PORT 5005
#define LOCAL_PORT 8888
#endif // SENDER
#ifdef RECEIVER
#define TARGET_PORT 8888
#define LOCAL_PORT 5005
#endif // RECEIVER
void InitWinsock()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
}
void print(char *data, int size)
{
for (int i = 0; i < size; i++)
{
if (data[i] == '\0')
{
printf("\\0");
}
else
{
printf("%c", data[i]);
}
}
printf("\n");
}
void clearBuffer(char *buffer, int size)
{
/* Put NULL character on the array */
for (int i = 0; i < size; i++)
{
buffer[i] = '\0';
}
}
void createHeaderBuffers(char *buffer, int info, int size)
{
// create the array containing the number of the packet and the data length
char temp[HEADER_LEN];
clearBuffer(temp, HEADER_LEN);
sprintf(temp, "%d", info);
int size_temp = strlen(temp);
int begin = size - size_temp;
for (int i = 0; i < size; i++)
{
if (i < begin) // fill the begining of the array with zero
{
buffer[i] = '0';
}
else // add the usefull info at the end e.g : 0000052
{
buffer[i] = temp[i - begin];
}
}
}
int createBuffer( char *buffer, char *data,int numPacket,int dataLength)
{
/* Create the buffer we will send*/
char numPacket_c[SIZE_PACKET+1];
char dataLength_c[5];
clearBuffer(buffer, BUFFERS_LEN);
clearBuffer(numPacket_c, 4);
clearBuffer(dataLength_c, 5);
createHeaderBuffers(numPacket_c, numPacket, SIZE_PACKET); // create the array containing the number of the packet
createHeaderBuffers(dataLength_c, dataLength, 4); // create the array containing the length of the data
for (int i = 0; i < BUFFERS_LEN; i++)
{
char ch;
if (i < SIZE_PACKET) // start by adding the number of the packet byte by byte
{
buffer[i] = numPacket_c[i];
}
else if (i < SIZE_PACKET+4) // then we add the length of the data
{
buffer[i] = dataLength_c[i- SIZE_PACKET];
}
else if (i < HEADER_LEN) // the the flag to say if it(s the end of the file
{
if(dataLength < DATA_LEN -1)
buffer[i] = '1';
else
buffer[i] = '0';
}
else if (i < HEADER_LEN + dataLength) // the the data
{
buffer[i] = data[i - HEADER_LEN];
}
else // fill the rest of the buffer with NULL character
{
buffer[i] = '\0';
}
}
return 0;
}
void copy(char *dest, char *source, int size)
{
/* Copy a buffer in another one byte by byte */
//printf("%s\n", source);
for (int i = 0; i < size; i++)
{
dest[i] = source[i];
//printf("%c\n", source[i]);
}
}
void readFile(char *buffer, int size, char *data, int *numPacket, int *dataLength, int *isEnd)
{
//print(buffer, size);
char isEnd_c[2];
char numPacket_c[SIZE_PACKET + 1];
char dataLength_c[5];
clearBuffer(isEnd_c, 2);
clearBuffer(numPacket_c, SIZE_PACKET + 1);
clearBuffer(dataLength_c, 5);
clearBuffer(data, DATA_LEN + 1);
for (int i = 0; i < size; i++)
{
if (i < SIZE_PACKET) // read the number of the packet
{
numPacket_c[i] = buffer[i];
printf("%c", buffer[i]);
}
else if (i < SIZE_PACKET + 4) // read the length of the data
{
dataLength_c[i - SIZE_PACKET] = buffer[i];
}
else if (i < HEADER_LEN) // read the isEnd FLAG
{
printf("\n%c\n", buffer[i]);
isEnd_c[0] = buffer[i];
}
else // read the data
{
data[i - HEADER_LEN] = buffer[i];
}
}
*numPacket = atoi(numPacket_c);
*isEnd = atoi(isEnd_c);
*dataLength = atoi(dataLength_c);
printf("%d ; %d ; %d\n", *numPacket, *dataLength, *isEnd);
}
unsigned short crc16(const unsigned char* numPacket, unsigned char length) {
unsigned char x;
unsigned short crc = 0xFFFF;
while (length--) {
x = crc >> 8 ^ *numPacket++;
x ^= x >> 4;
crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x << 5)) ^ ((unsigned short)x);
}
return crc;
}
//**********************************************************************
int main()
{
SOCKET socketS;
InitWinsock();
struct sockaddr_in local;
struct sockaddr_in from;
int fromlen = sizeof(from);
local.sin_family = AF_INET;
local.sin_port = htons(LOCAL_PORT);
local.sin_addr.s_addr = INADDR_ANY;
socketS = socket(AF_INET, SOCK_DGRAM, 0);
if (bind(socketS, (sockaddr*)&local, sizeof(local)) != 0) {
printf("Binding error!\n");
getchar(); //wait for press Enter
return 1;
}
//**********************************************************************
#ifdef SENDER
FILE *fp, *fp1;
char buffer_tx[BUFFERS_LEN];
int numPacket = 0;
char numberPacket[BUFFERS_LEN];
int isEnd = 0;
char test[100];
char header[HEADER_LEN];
char data[DATA_LEN];
char dataContent[DATA_LEN];
int len;
int num;
char *token;
sockaddr_in addrDest;
addrDest.sin_family = AF_INET;
addrDest.sin_port = htons(TARGET_PORT);
InetPton(AF_INET, _T(TARGET_IP), &addrDest.sin_addr.s_addr);
char *name = "test.jpg";
fp = fopen(name, "rb");
if (fp == NULL)
{
printf("error opening file\n");
}
fseek(fp, 0L, SEEK_END);
int sz = ftell(fp);
rewind(fp);
sz = (int)(sz / DATA_LEN) + 1;
strncpy(buffer_tx, name, BUFFERS_LEN); //put the nam of the file in the buffer
sendto(socketS, buffer_tx, BUFFERS_LEN, 0, (sockaddr*)&addrDest, sizeof(addrDest)); // send the name of the file
recvfrom(socketS, buffer_tx, BUFFERS_LEN, 0, (sockaddr*)&from, &fromlen); // wait aknowledgment
clearBuffer(buffer_tx, BUFFERS_LEN);
sprintf(buffer_tx, "%d", sz);
sendto(socketS, buffer_tx, BUFFERS_LEN, 0, (sockaddr*)&addrDest, sizeof(addrDest)); // send size of file
recvfrom(socketS, buffer_tx, BUFFERS_LEN, 0, (sockaddr*)&from, &fromlen); // wait aknowledgment
// This is to be sure that the receiver receive the name and the size correctly in the right order
clearBuffer(buffer_tx, BUFFERS_LEN);
clearBuffer(dataContent, DATA_LEN);
int n = 1;
int dataLength = 0;
while ((n = fread(dataContent, 1, DATA_LEN - 1,fp)) > 0) // read data of the file
{
clearBuffer(buffer_tx, BUFFERS_LEN); // clear the buffer for further utilisation
createBuffer(buffer_tx, dataContent, numPacket++, n); // add the header to the data |numPacket|dataLength|isEnd|data|
sendto(socketS, buffer_tx, BUFFERS_LEN, 0, (sockaddr*)&addrDest, sizeof(addrDest)); // send the packet
}
fclose(fp);
#endif // SENDER
#ifdef RECEIVER
FILE *fp;
char buffer_rx[BUFFERS_LEN];
Data *data;
int n = 0;
int k;
int how_many = 310;
//strncpy(buffer_rx, "12:1|salut", BUFFERS_LEN);
printf("Waiting for datagram ...\n");
int numPacket = 0;
int isEnd = 0;
int size = 0;
char size_file_c[BUFFERS_LEN];
int size_file = 0;
char header[HEADER_LEN];
char d[DATA_LEN + 1];
char name[BUFFERS_LEN];
char output[30];
char salut[DATA_LEN + 1];
sockaddr_in addrDest;
addrDest.sin_family = AF_INET;
addrDest.sin_port = htons(TARGET_PORT);
InetPton(AF_INET, _T(TARGET_IP), &addrDest.sin_addr.s_addr);
recvfrom(socketS, name, BUFFERS_LEN, 0, (sockaddr*)&from, &fromlen); // receiving name of file
sendto(socketS, name, BUFFERS_LEN, 0, (sockaddr*)&addrDest, sizeof(addrDest)); // send aknowledgment
recvfrom(socketS, size_file_c, BUFFERS_LEN, 0, (sockaddr*)&from, &fromlen); // receiving size of file
sendto(socketS, size_file_c, BUFFERS_LEN, 0, (sockaddr*)&addrDest, sizeof(addrDest)); // send aknowledgment
size_file = atoi(size_file_c);
// This is to be sure that the receiver receive the name and the size correctly in the right order
data = (Data *)calloc(size_file, sizeof(Data)); // allocate memory for the data
//closesocket(socketS);
//END;
//analyseBuffer(buffer_rx,d, &numPacket, &isEnd);
for (int i = 0; i < size_file; i++)
{
printf("waiting packet\n");
if ((k = recvfrom(socketS, buffer_rx, BUFFERS_LEN, 0, (sockaddr*)&from, &fromlen)) == SOCKET_ERROR) // receive a packet
{
printf("error during reception");
getchar();
return -1;
}
else
{
readFile(buffer_rx, BUFFERS_LEN, d, &numPacket, &size, &isEnd); // analyse the pacet to extract the data, the number of the packet, the data lenght and if it's the end
data[numPacket].data = (char*) calloc(size, 1); // allocate only the necessary memory
data[numPacket].size = size;
//print(d, DATA_LEN);
copy(data[numPacket].data, d, data[numPacket].size); // copy only the usefull info (without '\0')
printf("%d ; %d\n", i, size_file);
if (isEnd)
break;
clearBuffer(buffer_rx, BUFFERS_LEN); // clear the buffer for further utilisation
}
}
printf("file name : %s\n", name);
printf("enter the name of new file to be saved\n");
scanf("%s", output); // ask the user to set a file name
fp = fopen(output, "wb");
for (int i = 0; i <size_file; i++)
{
fwrite(data[i].data, data[i].size, 1, fp); // write the data to the file in the right order
}
fclose(fp); // close the file
closesocket(socketS);
#endif // RECEIVER
//**********************************************************************
getchar(); //wait for press Enter
return 0;
}
Notice the CRC-16 function , which is:
unsigned short crc16(const unsigned char* numPacket, unsigned char length) {
unsigned char x;
unsigned short crc = 0xFFFF;
while (length--) {
x = crc >> 8 ^ *numPacket++;
x ^= x >> 4;
crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x << 5)) ^ ((unsigned short)x);
}
return crc;
}
My question is : What is the best/easiest way to implement the CRC-16 function I have here? Do I pass a unsigned short crc parameter variable to the createBuffer() function, call the crc16() function inside the createBuffer() function and take the value it returns and assign it to the parameter value and then append it to the buffer?
Or is there a much simpler way to do it that I'm currently not thinking about?
Regarding What is the best/easiest way to implement the CRC-16 function I have here?
First, it appears your CRC-16 function is already implemented. How to use it is illustrated below.
CRC functions are typically used to take a file or buffer of any size as input, and produce a unique value for the purpose of verifying the contents of the file.
Here is a simple example of how I would use this function to read two types of input... (note, bufIn, and buf can be arrays of much larger sizes)
int main(void)
{
unsigned char bufIn[] = {1,45,76,23,245,9,54,55,210,90,23,54,78,14,27,86,34};
char buf[] = {"lkjahsloiwuyhfajsldnaouiyhrqkuhsldajnfdlakdsfa;jsidurfaliu;adjklflkja;sdlkjasdklfauiea;e"};
unsigned short crcOut1, crcOut2;
crcOut1 = crc16(bufIn, sizeof(bufIn)); //for bufIn returns 0x7782
crcOut2 = crc16(buf, sizeof(buf)); //for buf returns 0x98FB
return 0;
}
EDIT to address question in comment...
In your code, one possible way to use this is to call the crc16() function inside your fread while loop:
unsigned short packetCrc;
while ((n = fread(dataContent, 1, DATA_LEN - 1,fp)) > 0) // read data of the file
{
packetCrc = crc16(dataContent, n);
// verify packetCrc value against some expected value perhaps?
clearBuffer(buffer_tx, BUFFERS_LEN); // clear the buffer for further utilisation
createBuffer(buffer_tx, dataContent, numPacket++, n); // add the header to the data |numPacket|dataLength|isEnd|data|
sendto(socketS, buffer_tx, BUFFERS_LEN, 0, (sockaddr*)&addrDest, sizeof(addrDest)); // send the packet
}

XV6 crashes when trying to implement triple indirection in xv6 operating system

The original xv6-rev7 operating system contains:
12 directed blocks
1 indirect blcok(points to 128 blocks)
This means we have 140 blocks.
Each block's size is 512KB ==> 512 * 140 = 71,680 ~= 70KB is the limit of file's size in xv6.
I want to implemet triple indirect access in xv6 in order to support files with size of 40MB.
In order to do it I will need to implement double indirect before the triple indirect.
So I took 2 directed blocks from the 12 I had.
1 for the double indirect and the other for the triple indirect.
This is what I have right now:
Direct: 10 blocks
Single indirect: 128
Double indirect: 128*128
Triple indirect: 4*128*128 (I am using 4 instead of 128 because this is enough for 40MB)
This is why #define NDIRECT 10 and uint addrs[NDIRECT+3];
File's size limit = (10 + 128 + 128*128 + 4*128*128)*512kb = 42,013,696 ~= 42MB
So I understand the concept.
The implementation of the triple-indirection is in function bmap in file fs.c.
This is how it looks:
For some reason when I am trying to create file with size of 8.5MB it fails:
I am using bochs emulator
I am also not sure to what values I need to change in mkfs.c:
int nblocks = 20985;
int nlog = LOGSIZE;
int ninodes = 200;
int size = 21029;
fs.h:
// On-disk file system format.
// Both the kernel and user programs use this header file.
// Block 0 is unused.
// Block 1 is super block.
// Blocks 2 through sb.ninodes/IPB hold inodes.
// Then free bitmap blocks holding sb.size bits.
// Then sb.nblocks data blocks.
// Then sb.nlog log blocks.
#define ROOTINO 1 // root i-number
#define BSIZE 512 // block size
// File system super block
struct superblock {
uint size; // Size of file system image (blocks)
uint nblocks; // Number of data blocks
uint ninodes; // Number of inodes.
uint nlog; // Number of log blocks
};
#define NDIRECT 10
#define NINDIRECT (BSIZE / sizeof(uint))
#define MAXFILE (NDIRECT + NINDIRECT + NINDIRECT*NINDIRECT + 4*NINDIRECT*NINDIRECT)
// On-disk inode structure
struct dinode {
short type; // File type
short major; // Major device number (T_DEV only)
short minor; // Minor device number (T_DEV only)
short nlink; // Number of links to inode in file system
uint size; // Size of file (bytes)
uint addrs[NDIRECT+3]; // Data block addresses
};
// Inodes per block.
#define IPB (BSIZE / sizeof(struct dinode))
// Block containing inode i
#define IBLOCK(i) ((i) / IPB + 2)
// Bitmap bits per block
#define BPB (BSIZE*8)
// Block containing bit for block b
#define BBLOCK(b, ninodes) (b/BPB + (ninodes)/IPB + 3)
// Directory is a file containing a sequence of dirent structures.
#define DIRSIZ 14
struct dirent {
ushort inum;
char name[DIRSIZ];
};
fs.c:
// Return the disk block address of the nth block in inode ip.
// If there is no such block, bmap allocates one.
static uint
bmap(struct inode *ip, uint bn)
{
uint addr, *a;
struct buf *bp;
if(bn < NDIRECT){
if((addr = ip->addrs[bn]) == 0)
ip->addrs[bn] = addr = balloc(ip->dev);
return addr;
}
bn -= NDIRECT;
if(bn < NINDIRECT){
// Load indirect block, allocating if necessary.
if((addr = ip->addrs[NDIRECT]) == 0)
ip->addrs[NDIRECT] = addr = balloc(ip->dev);
bp = bread(ip->dev, addr);
a = (uint*)bp->data;
if((addr = a[bn]) == 0){
a[bn] = addr = balloc(ip->dev);
log_write(bp);
}
brelse(bp);
return addr;
}
/* Double indirect */
bn -= NINDIRECT;
if(bn < NINDIRECT*NINDIRECT){
// Load 2nd indirect block, allocating if necessary.
if((addr = ip->addrs[NDIRECT+1]) == 0) // 2d block. NDIRECT+1 is to get the index vector
ip->addrs[NDIRECT+1] = addr = balloc(ip->dev);
bp = bread(ip->dev, addr);
a = (uint*)bp->data;
if ((addr = a[bn/(NINDIRECT)]) == 0) { /* get index for 1st
indirection. (NINDIRECT is 128) */
a[bn/(NINDIRECT)] = addr = balloc(ip->dev);
log_write(bp);
}
brelse(bp); /* release the double indirect table
(main level) */
bp = bread(ip->dev, addr);
a = (uint*)bp->data;
if ((addr = a[bn%(NINDIRECT)]) == 0) { /* get the 2nd level table */
a[bn%(NINDIRECT)] = addr = balloc(ip->dev);
log_write(bp);
}
brelse(bp);
return addr;
}
/* Triple indirect */
bn -= NINDIRECT*NINDIRECT;
if(bn < 4*NINDIRECT*NINDIRECT){
// Load 3rd indirect block, allocating if necessary.
if((addr = ip->addrs[NDIRECT+2]) == 0) // 3d block. NDIRECT+2 is to get the index vector
ip->addrs[NDIRECT+2] = addr = balloc(ip->dev);
bp = bread(ip->dev, addr);
a = (uint*)bp->data;
if ((addr = a[bn/(NINDIRECT*4)]) == 0) { /* get index for 2st
indirection. (NINDIRECT is 128) */
a[bn/(NINDIRECT*4)] = addr = balloc(ip->dev);
log_write(bp);
}
brelse(bp);
bp = bread(ip->dev, addr);
a = (uint*)bp->data;
if ((addr = a[bn/(NINDIRECT*NINDIRECT*4)]) == 0) {
a[bn/(NINDIRECT*NINDIRECT*4)] = addr = balloc(ip->dev);
log_write(bp);
}
brelse(bp);
if ((addr = a[bn%(NINDIRECT*NINDIRECT*4)]) == 0) {
a[bn%(NINDIRECT*NINDIRECT*4)] = addr = balloc(ip->dev);
log_write(bp);
}
brelse(bp);
return addr;
}
panic("bmap: out of range");
}
mkfs.c:
#define stat xv6_stat // avoid clash with host struct stat
#include "types.h"
#include "fs.h"
#include "stat.h"
#include "param.h"
int nblocks = 20985;
int nlog = LOGSIZE;
int ninodes = 200;
int size = 21029;
bigfile.c:
#include "types.h"
#include "stat.h"
#include "user.h"
#include "fcntl.h"
void
help()
{
printf(1, "usage:\nfiles <name> <letter> <num>\n"
"e.g. nfiles foo a 40\n creates a file foo, with 40 times the letter a\n");
}
void
num2str(int i, char str[3])
{
str[2]=i%10+'0';
i=i/10;
str[1]=i%10+'0';
i=i/10;
str[0]=i%10+'0';
i=i/10;
}
#define BUF_SZ 512
int
main(int argc, char *argv[])
{
int i, count, fd, n;
// char *name;
// char c;
char buf[BUF_SZ];
if (argc !=4) {
help();
exit();
}
count = atoi(argv[3]);
if((fd=open(argv[1], O_CREATE|O_RDWR))<0) {
printf(2,"Failed to open file: %s\n", argv[1]);
exit();
}
for (i=0; i<BUF_SZ;i++)
buf[i]=argv[2][0];
for (i=0; i<count/BUF_SZ;i++)
if ((n=write(fd,buf,BUF_SZ)) != BUF_SZ)
{
printf(2,"Failed 1 to Write count=%d\n",i*BUF_SZ);
exit();
}
for (i=0; i<count%BUF_SZ;i++)
if ((n=write(fd,argv[2],1)) != 1)
{
printf(2,"Failed 2 to Write count=%d\n",count-i);
exit();
}
exit();
}
1.The number of nblocks which is defined in mkfs.c is insufficient.
int nblocks = 20985;
int nlog = LOGSIZE;
int ninodes = 200;
int size = 21029;
You have defined:
#define MAXFILE (NDIRECT + NINDIRECT + NINDIRECT*NINDIRECT + 4*NINDIRECT*NINDIRECT
which equals: 10+128+128^2+4*128^2 = 82058.
Just pick a number of nblocks which is greater than 82058, and update size accordingly.
2.In your bmap() function, in the triple indirection code, your first level of indirection is to a four-entry array (as you mentioned in your diagram).
Once you know to which of these four entries you should access, you're back with the double indirection problem, which you already solved.
So, in order to know which of the four entries you should access, you can use this:
if((addr = a[bn/(NINDIRECT*NINDIRECT)]) == 0){
a[bn/(NINDIRECT*NINDIRECT)] = addr = balloc(ip->dev);
log_write(bp);
}
You then could decrease bn like so:
bn -= ((NINDIRECT*NINDIRECT)*(bn/(NINDIRECT*NINDIRECT)));
and solve the double indirection problem again.

How to print an integer in Nios 2?

I've written code than handles interrupts and I added a function that will do something "useful" (calculating the next prime) and that should handle interrupts. The interrupts are working but not printing the calculated primes from within the while loop, while it is printing the time if I don't try to print the prime.
I think that putchar can't be used since a) It's for characters and I want to print an int and b) putchar uses interrupts so I must do it some other way.
When I tried with printf("%d",next) it didn't work either, why? How should I do to print the next prime from the main loop?
The program is
#include <stddef.h>
#include <stdio.h>
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "sys/alt_alarm.h"
#include "alt_types.h"
#include "alt_irq.h"
extern int initfix_int(void);
extern void puttime(int* timeloc);
extern void puthex(int time);
extern void tick(int* timeloc);
extern void delay(int millisec);
extern int hexasc(int invalue);
#define TRUE 1
#define KEYS4 ( (unsigned int *) 0x840 )
#define TIMER1 ( (unsigned int *) 0x920 )
#define PERIOD (49999)
#define NULL_POINTER ( (void *) 0)
#define NULL ( (void *) 0)
#define PRIME_FALSE 0 /* Constant to help readability. */
#define PRIME_TRUE 1 /* Constant to help readability. */
volatile int timeloc = 0x5957;
volatile int RUN = 1;
volatile int * const de2_pio_keys4_base = (volatile int *) 0x840;
volatile int * const de2_pio_keys4_intmask = (volatile int *) 0x848;
volatile int * const de2_pio_keys4_edgecap = (volatile int *) 0x84c;
volatile int * de2_pio_hex_low28 = (volatile int *) 0x9f0;
const int de2_pio_keys4_intindex = 2;
const int de2_pio_keys4_irqbit = 1 << 2;
/* The alt_alarm must persist for the duration of the alarm. */
static alt_alarm alarm;
/*
* The callback function.
*/
alt_u32 my_alarm_callback(void* context) {
/* This function is called once per second */
if (RUN == 1) {
tick(&timeloc);
puttime(&timeloc);
puthex(timeloc);
}
return alt_ticks_per_second();
}
void n2_fatal_error() {
/* Define the pattern to be sent to the seven-segment display. */
#define N2_FATAL_ERROR_HEX_PATTERN ( 0xcbd7ff )
/* Define error message text to be printed. */
static const char n2_fatal_error_text[] = "FATAL ERROR";
/* Define pointer for pointing into the error message text. */
register const char * cp = n2_fatal_error_text;
/* Send pattern to seven-segment display. */
*de2_pio_hex_low28 = N2_FATAL_ERROR_HEX_PATTERN;
/* Print the error message. */
while (*cp) {
//out_char_uart_0( *cp );
cp = cp + 1;
}
/* Stop and wait forever. */
while (1)
;
}
/*
* Interrupt handler for de2_pio_keys4.
* The parameters are ignored here, but are
* required for correct compilation.
* The type alt_u32 is an Altera-defined
* unsigned integer type.
*/
void irq_handler_keys(void * context, alt_u32 irqnum) {
alt_u32 save_value;
save_value = alt_irq_interruptible(de2_pio_keys4_intindex);
/* Read edge capture register of the de2_pio_keys4 device. */
int edges = *de2_pio_keys4_edgecap;
*de2_pio_keys4_edgecap = 0;
/* If action on KEY0 */
if (edges & 1) {
/* If KEY0 is pressed now */
if ((*de2_pio_keys4_base & 1) == 0) {
if (RUN == 0) {
RUN = 1;
} else {
RUN = 0;
}
}
/* If KEY0 is released now */
else if ((*de2_pio_keys4_base & 1) != 0) {
}
alt_irq_non_interruptible(save_value);
} else if (edges & 2) {
/* If KEY1 is pressed now */
if ((*de2_pio_keys4_base & 2) == 0) {
tick(&timeloc);
puttime(&timeloc);
puthex(timeloc);
}
/* If KEY1 is released now */
else if ((*de2_pio_keys4_base & 2) != 0) {
}
alt_irq_non_interruptible(save_value);
}
else if (edges & 4) {
/* If KEY2 is pressed now */
if ((*de2_pio_keys4_base & 4) == 0) {
timeloc = 0x0;
puttime(&timeloc);
puthex(timeloc);
}
/* If KEY2 is released now */
else if ((*de2_pio_keys4_base & 4) != 0) {
}
alt_irq_non_interruptible(save_value);
}
else if (edges & 8) {
/* If KEY3 is pressed now */
if ((*de2_pio_keys4_base & 8) == 0) {
timeloc = 0x5957;
puttime(&timeloc);
puthex(timeloc);
}
/* If KEY3 is released now */
else if ((*de2_pio_keys4_base & 8) != 0) {
}
alt_irq_non_interruptible(save_value);
}
}
/*
* Initialize de2_pio_keys4 for interrupts.
*/
void keysinit_int(void) {
/* Declare a temporary for checking return values
* from system-calls and library functions. */
register int ret_val_check;
/* Allow interrupts */
*de2_pio_keys4_intmask = 15;
/* Set up Altera's interrupt wrapper for
* interrupts from the de2_pio_keys4 device.
* The function alt_irq_register will enable
* interrupts from de2_pio_keys4.
* Return value is zero for success,
* nonzero for failure. */
ret_val_check = alt_irq_register(de2_pio_keys4_intindex, NULL_POINTER,
irq_handler_keys);
/* If there was an error, terminate the program. */
if (ret_val_check != 0)
n2_fatal_error();
}
/*
* NextPrime
*
* Return the first prime number larger than the integer
* given as a parameter. The integer must be positive.
*/
int nextPrime(int inval) {
int perhapsprime; /* Holds a tentative prime while we check it.
*/
int testfactor; /* Holds various factors for which we test
perhapsprime. */
int found; /* Flag, false until we find a prime. */
if (inval < 3) /* Initial sanity check of parameter. */
{
if (inval <= 0)
return (1); /* Return 1 for zero or negative input. */
if (inval == 1)
return (2); /* Easy special case. */
if (inval == 2)
return (3); /* Easy special case. */
} else {
/* Testing an even number for primeness is pointless, since
* all even numbers are divisible by 2. Therefore, we make sure
* that perhapsprime is larger than the parameter, and odd. */
perhapsprime = (inval + 1) | 1;
}
/* While prime not found, loop. */
for (found = PRIME_FALSE; found != PRIME_TRUE; perhapsprime += 2) {
/* Check factors from 3 up to perhapsprime/2. */
for (testfactor = 3; testfactor <= (perhapsprime >> 1); testfactor +=
1) {
found = PRIME_TRUE; /* Assume we will find a prime. */
if ((perhapsprime % testfactor) == 0) { /* If testfactor divides perhapsprime... */
found = PRIME_FALSE; /* ...then, perhapsprime was non-prime. */
goto check_next_prime;
/* Break the inner loop,
go test a new perhapsprime. */
}
}
check_next_prime: ; /* This label is used to break the inner loop. */
if (found == PRIME_TRUE) /* If the loop ended normally,
we found a prime. */
{
return (perhapsprime); /* Return the prime we found. */
}
}
return (perhapsprime); /* When the loop ends,
perhapsprime is a real prime. */
}
int main() {
int next = 3;
/* Remove unwanted interrupts.
* A nonzero return value indicates failure. */
if (initfix_int() != 0)
n2_fatal_error();
keysinit_int();
if (alt_alarm_start(&alarm, alt_ticks_per_second(), my_alarm_callback, NULL)
< 0) {
printf("No system clock available\n");
}
while( 1 ) /* Loop forever. */
{
next = nextPrime(next);
//printf("%d",next);
//printf("P %d ", next);
}
return 0;
}
int hex7seg(int digit) {
int trantab[] = { 0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00,
0x10, 0x08, 0x03, 0x46, 0x21, 0x06, 0x0e };
register int tmp = digit & 0xf;
return (trantab[tmp]);
}
void puthex(int inval) {
unsigned int hexresult;
hexresult = hex7seg(inval);
hexresult = hexresult | (hex7seg(inval >> 4) << 7);
hexresult = hexresult | (hex7seg(inval >> 8) << 14);
hexresult = hexresult | (hex7seg(inval >> 12) << 21);
IOWR_ALTERA_AVALON_PIO_DATA(DE2_PIO_HEX_LOW28_BASE, hexresult);
}
Basically your code is working fine on me. The only problem is with printing, for some reason you should print a newline before such as:
printf("start program\n");
while( 1 ) /* Loop forever. */
{
next = nextPrime(next);
printf("%d",next);
}

Resources