cJSON can`t parse more than 4 elements - stm32

Trying to use cJSON parser with STM32F103C8T6 and KEIL IDE
The problem is that the parser works pretty well with up to 4 elements of the JSON string, when trying to add the fifth element it gives up.
This code seems to be OK:
#include "cJSON.h"
const char * my_json_string =
"{\"device\":\"16\",\"class\":\"master\",\"call\":\"start\",\"ar1\":\"10\"}";
int main (void){
char * device;
char * cls;
char * call;
char * arg1;
cJSON * root = cJSON_Parse(my_json_string);
if (root == NULL){
printf(cJSON_GetErrorPtr());
return 0;
}
cJSON * dev = cJSON_GetObjectItem(root, "device");
cJSON * cla = cJSON_GetObjectItem(root, "class");
cJSON * cl = cJSON_GetObjectItem(root, "call");
cJSON * ar1 = cJSON_GetObjectItem(root, "ar1");
device = dev->valuestring;
cls = cla->valuestring;
call = cl->valuestring;
arg1 = ar1->valuestring;
printf (device);
printf (cls);
printf (call);
printf (arg1);
}
When I add the fifth pair of key-value to the string
const char * my_json_string =
"{\"device\":\"16\",\"class\":\"master\",\"call\":\"start\",\"ar1\":\"10\",\"ar2\":\"20\"}";
it throws an error pointer
,"ar2":"20"}
The same code, compiled with NetBeans IDE for the desktop works fine.
Here is the RAM map of the STM32, I see no problems here:
Execution Region RW_IRAM1 (Base: 0x20000000, Size: 0x00000ea0, Max: 0x00005000, ABSOLUTE)
Base Addr Size Type Attr Idx E Section Name Object
0x20000000 0x00000014 Data RW 5 .data system_stm32f10x.o
0x20000014 0x00000014 Data RW 18 .data main.o
0x20000028 0x00000008 Data RW 35 .data usart_f10x.o
0x20000030 0x0000000b Data RW 56 .data led_matrix_64x32.o
0x2000003b 0x00000001 PAD
0x2000003c 0x00000004 Data RW 63 .data time_f10x.o
0x20000040 0x00000014 Data RW 155 .data cjson.o
0x20000054 0x00000004 Data RW 357 .data mc_w.l(mvars.o)
0x20000058 0x00000004 Data RW 358 .data mc_w.l(mvars.o)
0x2000005c 0x00000041 Zero RW 34 .bss usart_f10x.o
0x2000009d 0x00000003 PAD
0x200000a0 0x00000800 Zero RW 54 .bss led_matrix_64x32.o
0x200008a0 0x00000200 Zero RW 7 HEAP startup_stm32f10x_md.o
0x20000aa0 0x00000400 Zero RW 6 STACK startup_stm32f10x_md.o

The problem is that 512 kB for the HEAP size was too low.

Related

How to force my section in the very end of flash?

I have my linker script with such memory layout
MEMORY{
ram : ORIGIN = 0x0, LENGTH = 0x1000 /* 4KB of RAM starting at address 0x0 */
flash : ORIGIN = 0x20000000, LENGTH = 0xC000 /* 48KB of flash starting at address 0x20000000 */
}
and I want to add two section in the very end of my flash(let's say .section1 and .section2)
but I don't know the length of my section unless I compile it
In my expectation, my flash layout will look like this:
start address
section
0x20000000
.text
0x20000000+.text size
.data
0x20000000+.text size + .data size
.mdata
0x20000000+.text size + .data size + .mdata
(empty flash)
0x2000C000-.section2 size - section1 size
.section1
0x2000C000-.section2 size
.section2
How should I do in my linker script?
I don't know how to wrote it for now I just force my address like this. but its not what I want.
.section1 :{
*(.section1)
} >flash :AT (0x2000A000)
.section2 :{
*(.section2)
} >flash :AT (0x2000B000)

GNU ASM .section directive not working/linker issue

I'm trying to move my _start function to 0x0, as it is the bootloader.
Flash ROM exists from 0x0 to the first 128MB (=1Gb), other memory is DDR3 RAM but we will map RAM to 0x80000000 to 0xFFFFFFFF.
The issue is with the directive .section ".vect", the _start address is not going into the .vect section, it is going into the .text section.
_start:
.section ".vect" /* I've tried .section .vect and I've tried moving above _start */
b ResetHandler
b UndefHandler
b SVC_Handler
b PrefetchAbortHandler
b DataAbortHandler
b NotUsedHandler
b IRQ_Handler
b FIQ_Handler
1:
b 1b /* Hang and don't return */
In my linker script, the MEMORY command and then the start of SECTIONS is:
MEMORY
{
vect (rx) : o = 0x0, l = 1M
rom (rx) : o = 1M, l = 127M
ram (wx) : o = 0x80000000, l = 0x80000000
}
SECTIONS
{
.vect : ALIGN(64)
{
. = 0x0;
*(.vect*)
VectTableEnd = .;
VectTableSize = SIZEOF(.vect);
} > vect
.... (.text, .bss, .data, .stack, etc are other SECTIONS entries)
}
But no matter what, the _start assembly function code gets shoved into the standard .text section, not at address 0x0. Does anyone know what I'm going wrong?
The code is targetted at bare-metal ARMv7A machines, compiled/linked with arm-none-eabi-as/ld
Cheers.
No surprises here if your _start label ends up in .text:
/* implicitly default section .text */
_start:
/* still the same section .text */
.section .vect
/* explicitly the section .vect */
b ResetHandler
You probably want to switch the section before defining the _start label to make that label end up in the intended section.
/* implicitly default section .text */
.section .vect
/* explicitly the section .vect */
_start:
b ResetHandler
Using the name _start as the symbol for a vector table is a bit weird (I would have expected a symbol like __vectors or vector_table), but that is beyond the scope of this question.

Raspberry Pi Pico I2C pins not working (MicroPython)

I have connected an ssd1306 OLED and BME280 to my Pico. Everything works like a charm when connected to Pin 0 (sda) and 1 (scl) i2c pins. But due to my very bad planning, I have to switch to any other i2c pins. Once connected I cannot get it to work.
I have changed from i2c = machine.I2C(0, scl=machine.Pin(1), sda=machine.Pin(0),freq=400000) to i2c = machine.I2C(0, scl=machine.Pin(13), sda=machine.Pin(12),freq=400000) and others, but to no avail.
Code snippet:
import machine
import bme280
import time
from machine import Pin, I2C, ADC
from ssd1306 import SSD1306_I2C
i2c = machine.I2C(0, scl=machine.Pin(13), sda=machine.Pin(12),freq=400000)
bme = bme280.BME280(i2c=i2c)
oled = SSD1306_I2C(128, 64, i2c)
Error I'm getting is:
Traceback (most recent call last): File "<stdin>", line 9, in <module> File "/lib/bme280.py", line 75, in __init__ OSError: 5
Which is:
dig_88_a1 = self.i2c.readfrom_mem(self.address, 0x88, 26) from bme280.py (standard driver)
I have performed an i2c scan and it does return correct addresses on the new pins.
So I had a Similar Problem to you I had the ssd1306 OLED and I kept getting
\\Traceback (most recent call last):
File "<stdin>", line 5, in <module>
File "/lib/ssd1306.py", line 110, in __init__
File "/lib/ssd1306.py", line 36, in __init__
File "/lib/ssd1306.py", line 71, in init_display
File "/lib/ssd1306.py", line 115, in write_cmd
OSError: [Errno 5] EIO
Im running the QT PI from addafuit but its a RP2040 chip and I'm running micro python.
Anyhow, I pressed the restart button on the board and It magically started working. Just like you, my i2c scan was getting the right address.
the code I ended up using that worked for me was
from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
i2c = I2C(0,sda=Pin(24),scl=Pin(25),freq=40000)
oled = SSD1306_I2C(128,64,i2c)
oled.fill(0)
oled.text("Hello",0,0)
oled.show()
and for the ssd1306 driver, I used
# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
from micropython import const
import framebuf
# register definitions
SET_CONTRAST = const(0x81)
SET_ENTIRE_ON = const(0xA4)
SET_NORM_INV = const(0xA6)
SET_DISP = const(0xAE)
SET_MEM_ADDR = const(0x20)
SET_COL_ADDR = const(0x21)
SET_PAGE_ADDR = const(0x22)
SET_DISP_START_LINE = const(0x40)
SET_SEG_REMAP = const(0xA0)
SET_MUX_RATIO = const(0xA8)
SET_COM_OUT_DIR = const(0xC0)
SET_DISP_OFFSET = const(0xD3)
SET_COM_PIN_CFG = const(0xDA)
SET_DISP_CLK_DIV = const(0xD5)
SET_PRECHARGE = const(0xD9)
SET_VCOM_DESEL = const(0xDB)
SET_CHARGE_PUMP = const(0x8D)
# Subclassing FrameBuffer provides support for graphics primitives
# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
class SSD1306(framebuf.FrameBuffer):
def __init__(self, width, height, external_vcc):
self.width = width
self.height = height
self.external_vcc = external_vcc
self.pages = self.height // 8
self.buffer = bytearray(self.pages * self.width)
super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
self.init_display()
def init_display(self):
for cmd in (
SET_DISP | 0x00, # off
# address setting
SET_MEM_ADDR,
0x00, # horizontal
# resolution and layout
SET_DISP_START_LINE | 0x00,
SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
SET_MUX_RATIO,
self.height - 1,
SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
SET_DISP_OFFSET,
0x00,
SET_COM_PIN_CFG,
0x02 if self.width > 2 * self.height else 0x12,
# timing and driving scheme
SET_DISP_CLK_DIV,
0x80,
SET_PRECHARGE,
0x22 if self.external_vcc else 0xF1,
SET_VCOM_DESEL,
0x30, # 0.83*Vcc
# display
SET_CONTRAST,
0xFF, # maximum
SET_ENTIRE_ON, # output follows RAM contents
SET_NORM_INV, # not inverted
# charge pump
SET_CHARGE_PUMP,
0x10 if self.external_vcc else 0x14,
SET_DISP | 0x01,
): # on
self.write_cmd(cmd)
self.fill(0)
self.show()
def poweroff(self):
self.write_cmd(SET_DISP | 0x00)
def poweron(self):
self.write_cmd(SET_DISP | 0x01)
def contrast(self, contrast):
self.write_cmd(SET_CONTRAST)
self.write_cmd(contrast)
def invert(self, invert):
self.write_cmd(SET_NORM_INV | (invert & 1))
def show(self):
x0 = 0
x1 = self.width - 1
if self.width == 64:
# displays with width of 64 pixels are shifted by 32
x0 += 32
x1 += 32
self.write_cmd(SET_COL_ADDR)
self.write_cmd(x0)
self.write_cmd(x1)
self.write_cmd(SET_PAGE_ADDR)
self.write_cmd(0)
self.write_cmd(self.pages - 1)
self.write_data(self.buffer)
class SSD1306_I2C(SSD1306):
def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False):
self.i2c = i2c
self.addr = addr
self.temp = bytearray(2)
self.write_list = [b"\x40", None] # Co=0, D/C#=1
super().__init__(width, height, external_vcc)
def write_cmd(self, cmd):
self.temp[0] = 0x80 # Co=1, D/C#=0
self.temp[1] = cmd
self.i2c.writeto(self.addr, self.temp)
def write_data(self, buf):
self.write_list[1] = buf
self.i2c.writevto(self.addr, self.write_list)
class SSD1306_SPI(SSD1306):
def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
self.rate = 10 * 1024 * 1024
dc.init(dc.OUT, value=0)
res.init(res.OUT, value=0)
cs.init(cs.OUT, value=1)
self.spi = spi
self.dc = dc
self.res = res
self.cs = cs
import time
self.res(1)
time.sleep_ms(1)
self.res(0)
time.sleep_ms(10)
self.res(1)
super().__init__(width, height, external_vcc)
def write_cmd(self, cmd):
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
self.cs(1)
self.dc(0)
self.cs(0)
self.spi.write(bytearray([cmd]))
self.cs(1)
def write_data(self, buf):
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
self.cs(1)
self.dc(1)
self.cs(0)
self.spi.write(buf)
self.cs(1)
So the only advice and can give to you is to try to press the restart button.

Script is displaying Unicode onto my character LCD

I am trying to get my Raspberry Pi 3 to display information taken from a MS SQL database onto a 2x16 character LCD. I have a script that gets the string from the database then writes it to a .txt and another that reads the .txt and displays it on the LCD. When it displays, however, it is in Unicode instead of "plain text." Is there a way to convert this so the LCD will display it properly?
I cannot insert a picture, but it is displaying like this: (u'thewordineedhere',)
This is the script I am using to get the string and write to the .txt
import pymssql
conn = pymssql.connect(server='###.##.###.##',port='1433', user='User_Name',
password='Password', database='Database_Name')
cursor = conn.cursor()
cursor.execute('Select Distinct * From Database_Name')
results = cursor.fetchall()
my_file = open("output.txt","w")
for string in results:
print (string)
my_file.write(str(string) +"\n")
my_file.close
conn.commit()
conn.close()
This is the script that reads it and displays on the LCD.
import I2C_LCD_driver
from time import *
f = open('output.txt','r')
data = f.read()
mylcd = I2C_LCD_driver.lcd()
mylcd.lcd_display_string(data, 1)
mylcd.lcd_display_string("", 2)
If necessary I can provide the I2C_LCD_driver.py, /etc/odbc.ini, /etc/odbcinst.ini, and /etc/freetds/freetds.conf scripts as well.
Here is the I2C_LCD_driver.py
# -*- coding: utf-8 -*-
# Original code found at:
# https://gist.github.com/DenisFromHR/cc863375a6e19dce359d
"""
Compiled, mashed and generally mutilated 2014-2015 by Denis Pleic
Made available under GNU GENERAL PUBLIC LICENSE
# Modified Python I2C library for Raspberry Pi
# as found on http://www.recantha.co.uk/blog/?p=4849
# Joined existing 'i2c_lib.py' and 'lcddriver.py' into a single library
# added bits and pieces from various sources
# By DenisFromHR (Denis Pleic)
# 2015-02-10, ver 0.1
"""
# i2c bus (0 -- original Pi, 1 -- Rev 2 Pi)
I2CBUS = 1
# LCD Address
ADDRESS = 0x3F
import smbus
from time import sleep
class i2c_device:
def __init__(self, addr, port=I2CBUS):
self.addr = addr
self.bus = smbus.SMBus(port)
# Write a single command
def write_cmd(self, cmd):
self.bus.write_byte(self.addr, cmd)
sleep(0.0001)
# Write a command and argument
def write_cmd_arg(self, cmd, data):
self.bus.write_byte_data(self.addr, cmd, data)
sleep(0.0001)
# Write a block of data
def write_block_data(self, cmd, data):
self.bus.write_block_data(self.addr, cmd, data)
sleep(0.0001)
# Read a single byte
def read(self):
return self.bus.read_byte(self.addr)
# Read
def read_data(self, cmd):
return self.bus.read_byte_data(self.addr, cmd)
# Read a block of data
def read_block_data(self, cmd):
return self.bus.read_block_data(self.addr, cmd)
# Read a single byte
def read(self):
return self.bus.read_byte(self.addr)
# Read
def read_data(self, cmd):
return self.bus.read_byte_data(self.addr, cmd)
# Read a block of data
def read_block_data(self, cmd):
return self.bus.read_block_data(self.addr, cmd)
# commands
LCD_CLEARDISPLAY = 0x01
LCD_RETURNHOME = 0x02
LCD_ENTRYMODESET = 0x04
LCD_DISPLAYCONTROL = 0x08
LCD_CURSORSHIFT = 0x10
LCD_FUNCTIONSET = 0x20
LCD_SETCGRAMADDR = 0x40
LCD_SETDDRAMADDR = 0x80
# flags for display entry mode
LCD_ENTRYRIGHT = 0x00
LCD_ENTRYLEFT = 0x02
LCD_ENTRYSHIFTINCREMENT = 0x01
LCD_ENTRYSHIFTDECREMENT = 0x00
# flags for display on/off control
LCD_DISPLAYON = 0x04
LCD_DISPLAYOFF = 0x00
LCD_CURSORON = 0x02
LCD_CURSOROFF = 0x00
LCD_BLINKON = 0x01
LCD_BLINKOFF = 0x00
# flags for display/cursor shift
LCD_DISPLAYMOVE = 0x08
LCD_CURSORMOVE = 0x00
LCD_MOVERIGHT = 0x04
LCD_MOVELEFT = 0x00
# flags for function set
LCD_8BITMODE = 0x10
LCD_4BITMODE = 0x00
LCD_2LINE = 0x08
LCD_1LINE = 0x00
LCD_5x10DOTS = 0x04
LCD_5x8DOTS = 0x00
# flags for backlight control
LCD_BACKLIGHT = 0x08
LCD_NOBACKLIGHT = 0x00
En = 0b00000100 # Enable bit
Rw = 0b00000010 # Read/Write bit
Rs = 0b00000001 # Register select bit
class lcd:
#initializes objects and lcd
def __init__(self):
self.lcd_device = i2c_device(ADDRESS)
self.lcd_write(0x03)
self.lcd_write(0x03)
self.lcd_write(0x03)
self.lcd_write(0x02)
self.lcd_write(LCD_FUNCTIONSET | LCD_2LINE | LCD_5x8DOTS | LCD_4BITMODE)
self.lcd_write(LCD_DISPLAYCONTROL | LCD_DISPLAYON)
self.lcd_write(LCD_CLEARDISPLAY)
self.lcd_write(LCD_ENTRYMODESET | LCD_ENTRYLEFT)
sleep(0.2)
# clocks EN to latch command
def lcd_strobe(self, data):
self.lcd_device.write_cmd(data | En | LCD_BACKLIGHT)
sleep(.0005)
self.lcd_device.write_cmd(((data & ~En) | LCD_BACKLIGHT))
sleep(.0001)
def lcd_write_four_bits(self, data):
self.lcd_device.write_cmd(data | LCD_BACKLIGHT)
self.lcd_strobe(data)
# write a command to lcd
def lcd_write(self, cmd, mode=0):
self.lcd_write_four_bits(mode | (cmd & 0xF0))
self.lcd_write_four_bits(mode | ((cmd << 4) & 0xF0))
# write a character to lcd (or character rom) 0x09: backlight | RS=DR<
# works!
def lcd_write_char(self, charvalue, mode=1):
self.lcd_write_four_bits(mode | (charvalue & 0xF0))
self.lcd_write_four_bits(mode | ((charvalue << 4) & 0xF0))
# put string function with optional char positioning
def lcd_display_string(self, string, line=1, pos=0):
if line == 1:
pos_new = pos
elif line == 2:
pos_new = 0x40 + pos
elif line == 3:
pos_new = 0x14 + pos
elif line == 4:
pos_new = 0x54 + pos
self.lcd_write(0x80 + pos_new)
for char in string:
self.lcd_write(ord(char), Rs)
# clear lcd and set to home
def lcd_clear(self):
self.lcd_write(LCD_CLEARDISPLAY)
self.lcd_write(LCD_RETURNHOME)
# define backlight on/off (lcd.backlight(1); off= lcd.backlight(0)
def backlight(self, state): # for state, 1 = on, 0 = off
if state == 1:
self.lcd_device.write_cmd(LCD_BACKLIGHT)
elif state == 0:
self.lcd_device.write_cmd(LCD_NOBACKLIGHT)
# add custom characters (0 - 7)
def lcd_load_custom_chars(self, fontdata):
self.lcd_write(0x40);
for char in fontdata:
for line in char:
self.lcd_write_char(line)
When a row of data is read from the database, it comes back as a row object which can have the individual columns accessed as if it was a list. What you're seeing is the string representation of a row object. You want the first item so you need to use string[0].
I am using Python in VS2017 on Windows, and I used pyodbc instead of pymssql:
import pyodbc
conn_str = (
r"Driver={SQL Server Native Client 11.0};"
r"Server=.\SQLEXPRESS;"
r"Database=testing;"
r"Trusted_Connection=yes;"
)
conn = pyodbc.connect(conn_str)
cursor = conn.cursor()
cursor.execute('Select Distinct Name From Names')
results = cursor.fetchall()
conn.close()
my_file = open(r"C:\temp\output.txt","w")
for string in results:
print (string[0])
my_file.write(string[0] + "\n")
my_file.close()
Notice that I closed the database as soon as possible to keep things clean, I used a full path to the file, and I had to use my_file.close() with the parentheses to make it work.

How do I print a string in one line in MARIE?

I want to print a set of letters in one line in MARIE. I modified the code to print Hello World and came up with:
ORG 0 / implemented using "do while" loop
WHILE, LOAD STR_BASE / load str_base into ac
ADD ITR / add index to str_base
STORE INDEX / store (str_base + index) into ac
CLEAR / set ac to zero
ADDI INDEX / get the value at ADDR
SKIPCOND 400 / SKIP if ADDR = 0 (or null char)
JUMP DO / jump to DO
JUMP PRINT / JUMP to END
DO, STORE TEMP / output value at ADDR
LOAD ITR / load iterator into ac
ADD ONE / increment iterator by one
STORE ITR / store ac in iterator
JUMP WHILE / jump to while
PRINT, SUBT ONE
SKIPCOND 000
JUMP PR
HALT
PR, OUTPUT
JUMP WHILE
ONE, DEC 1
ITR, DEC 0
INDEX, HEX 0
STR_BASE, HEX 12 / memory location of str
STR, HEX 48 / H
HEX 65 / E
HEX 6C / L
HEX 6C / L
HEX 6F / O
HEX 0 / carriage return
HEX 57 / W
HEX 6F / O
HEX 72 / R
HEX 6C / L
HEX 64 / D
HEX 0 / NULL char
My program ends up halting past two iterations. I can't seem to figure out how to print a set of characters in one line. Thanks.
Your value of STR_BASE is almost certainly incorrect. Based on what is here I would say it needs to be 18 instead of 12. Also you would either want to remove current null char that is between "HELLO" and "WORLD" and replace it with a space or simply remove that line, depending on your intended output.